高德地图SDK Android版开发 10 InfoWindow

news2024/11/13 12:02:38

高德地图SDK Android版开发 10 InfoWindow

  • 前言
  • 相关类和方法
    • 默认样式
      • Marker类
      • AMap类
      • AMap.OnInfoWindowClickListener 接口
    • 自定义样式(视图)
      • AMap 类
      • AMap.ImageInfoWindowAdapter 接口
    • 自定义样式(Image)
      • AMap.ImageInfoWindowAdapter 接口
  • 示例
    • 界面布局
    • MapInfoWindow类
      • 常量
      • 成员变量
      • 初始化
      • 创建与移除覆盖物
      • 设置属性
      • 自定义样式
      • 加载与移除地图
    • MapInfoWindowActivity 类
      • 控件响应事件
    • 运行效果图

前言

前文介绍高德地图添加Marker覆盖物的使用方法,Marker结合InfoWindow可展示更详尽的信息。本文将介绍以下内容:

  1. 使用SDK默认样式显示InfoWindow的方法;
  2. 自定义InfoWindow样式的方法。

相关类和方法

默认样式

  • 在高德地图SDK中,InfoWindow 是点标记的一部分,默认的 Infowindow 只显示 Marker 对象的两个属性,一个是 title 和另一个 snippet。
  • SDK 为用户提供了默认的 InfoWindow 样式,调用 Marker 类的 showInfoWindow() hideInfoWindow() 方法可以控制显示和隐藏。
  • 当改变 Markertitlesnippet 属性时,再次调用 showInfoWindow(),可以更新 InfoWindow 显示内容。

Marker类

  • 标题、文字片段和附加信息的方法
类型方法说明
StringgetSnippet()获取Marker 覆盖物的文字片段。
StringgetTitle()获取Marker 覆盖物的标题。
ObjectgetObject()获取Marker覆盖物的附加信息对象,即自定义的Marker的属性。
voidsetSnippet(String snippet)设置Marker 覆盖物的文字片段。
voidsetTitle(String title)设置Marker 覆盖物的标题。
voidsetObject(Object object)设置Marker覆盖物的附加信息对象。
  • InfoWindow的方法
类型方法说明
booleanisInfoWindowEnable()获取Marker覆盖物是否允许InfoWindow显示,
可以通过 Marker.setInfoWindowEnable(boolean) 进行设置
voidsetInfoWindowEnable(boolean enabled)设置Marker覆盖物的InfoWindow是否允许显示,默认为true。
设置为false之后, 调用Marker.showInfoWindow() 将不会生效
booleanisInfoWindowShown()返回Marker覆盖物的信息窗口是否显示,true: 显示,false: 不显示。
voidshowInfoWindow()显示 Marker 覆盖物的信息窗口。
voidhideInfoWindow()隐藏Marker覆盖物的信息窗口。

AMap类

类型方法说明
voidsetOnInfoWindowClickListener(AMap.OnInfoWindowClickListener listener)设置marker的信息窗口点击事件监听接口。

AMap.OnInfoWindowClickListener 接口

public interface OnInfoWindowClickListener {
    void onInfoWindowClick(Marker marker);
}

自定义样式(视图)

AMap 类

类型方法说明
voidsetInfoWindowAdapter(AMap.InfoWindowAdapter adapter)设置marker的信息窗口定制接口。

AMap.ImageInfoWindowAdapter 接口

用来定制Marker的信息窗口。

类型方法说明
android.view.ViewgetInfoWindow(Marker marker)定制展示marker信息的View。(注:可自定义背景
android.view.ViewgetInfoContents(Marker marker)定制展示marker信息的View。(注:使用默认背景
public interface InfoWindowAdapter {
    // 如果返回的View不为空且View的background不为null,则直接使用它来展示marker的信息。
    // 如果backgound为null,SDK内部会给这个View设置一个默认的background。
    // 如果这个方法返回null,内容将会从getInfoContents(Marker)方法获取。
    View getInfoWindow(Marker marker);

    // 如果返回的View不为空且View的background不为null,则直接使用它来展示marker的信息。
    // 如果backgound为null,SDK内部会给这个View设置一个默认的background。
    // 如果这个方法返回null,将使用内置的一个默认的View来展示marker的信息。
    View getInfoContents(Marker marker);
}

触发机制

  • 默认情况下,当单击某个marker时,如果该marker的Title和Snippet不为空,则会触发getInfoWindow和getInfoContents回调。
  • 另外,通过**调用Marker.showInfoWindow()**同样可以触发上面两个回调。

返回null的处理逻辑

  • 自5.2.1开始,如果getInfoWindow(Marker) 和 getInfoContents(Marker) 均返回null,将不展示InfoWindow的信息

自定义样式(Image)

说明:此方法官方指南未介绍,来自参考手册。(未做验证)

AMap.ImageInfoWindowAdapter 接口

«interface»
InfoWindowAdapter
«interface»
ImageInfoWindowAdapter
+long getInfoWindowUpdateTime()

用途:

用来实现marker与对应InfoWindow同步移动。

默认情况下,InfoWindow是一个View, 拖动地图的时候由于View 布局较慢,会有延迟的效果

为了解决此问题,新增AMap.ImageInfoWindowAdapter, InfoWindow会被转为图片,拖动地图时会跟随Marker

注意

使用ImageInfoWindowAdapter后InfoWindow作为View本身的功能被减弱,比如动态更新图片,播放Gif图片等等均无法使用。

如果想要动态的去更新infowindow内容,请务必仔细看看此接口的更新机制

更新机制

设置此接口返回值之后,会定期(默认周期无穷大)调用一个 getInfoWindow(Marker)将View转换为图片

由于将View转成图片会比较耗时,不能一直调用,而设置时间间隔可以减少一定的耗时。

调用Marker.showInfoWindow() 也可以触发调用 AMap.InfoWindowAdapter.getInfoWindow(Marker) 并将View转换为图片。

类型方法说明
longgetInfoWindowUpdateTime()自定义整个信息窗口属性间隔时间。单位为 ms

方法说明

  • 如果返回值 小于或等于 0,则认为是无穷大。
  • 如果返回值 (0,100] , 则认为是100(如果频繁将View转成图片,内存抖动会很严重,建议这个值不要太低)。
  • 如果这个想实现更小的时间间隔或者不想受这个接口约束,可以保持返回默认值,并自行设置计时器。

示例

界面布局

在这里插入图片描述

  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="MapInfoWindowActivity">

    <com.amap.api.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/bottomView"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/bottomView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/map">

        <RadioGroup
            android:id="@+id/RadioGroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/background_dark"
            android:gravity="center_horizontal"
            android:orientation="horizontal"
            android:paddingHorizontal="10dp">

            <RadioButton
                android:id="@+id/simpleMode"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:checked="true"
                android:onClick="setMarkerFlag"
                android:text="简单"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/adapter_window_mode"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="适配器(窗口)"
                android:textColor="@color/white"
                android:textStyle="bold" />

            <RadioButton
                android:id="@+id/adapter_content_mode"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="setMarkerFlag"
                android:text="适配器(内容)"
                android:textColor="@color/white"
                android:textStyle="bold" />

        </RadioGroup>

    </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

MapInfoWindow类

  • 以下是MapInfoWIndows部分代码

常量

public static final String SIMPlE_MODE = "SimpleMode";
public static final String ADAPTER_WINDOW_MODE = "AdapterWindowMode";
public static final String ADAPTER_CONTENT_MODE = "AdapterContentMode";

成员变量

// 覆盖物列表
List<BaseOverlay> overlays = new ArrayList<>();
// 选中的状态
String selectedFlag = SIMPlE_MODE;
// 气泡图标
ArrayList<BitmapDescriptor> bitmaps = new ArrayList<>();

初始化

int[] drawableIds = BubbleIcons.Number;
for (int drawableId : drawableIds) {
    BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(drawableId);
    bitmaps.add(bitmap);
}
initEvent();
private void initEvent() {
    // 设置marker的信息窗口点击事件监听接口。
    map.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
        @Override
        public void onInfoWindowClick(Marker marker) {
            // 隐藏Marker覆盖物的信息窗口。
            marker.hideInfoWindow();
        }
    });
}

创建与移除覆盖物

public void addMarkers() {
    // 构造大量坐标数据
    List<LatLng> points = new ArrayList<>();
    points.add(new LatLng(39.97923, 116.357428));
    points.add(new LatLng(39.94923, 116.397428));
    points.add(new LatLng(39.97923, 116.437428));
    points.add(new LatLng(39.92353, 116.490705));
    points.add(new LatLng(40.023537, 116.289429));
    points.add(new LatLng(40.022211, 116.406137));

    // 创建OverlayOptions的集合
    ArrayList<MarkerOptions> optionsList = new ArrayList<>();
    for (int i = 0; i < points.size(); ++i) {
        // 创建OverlayOptions属性
        MarkerOptions option = new MarkerOptions()
                .position(points.get(i))
                .icon(bitmaps.get(i))
                .title("标题" + (i + 1))
                .snippet("详细信息" + (i + 1));
        // 将OverlayOptions添加到list
        optionsList.add(option);
    }

    boolean moveToCenter = true;
    // 在地图上添一组图片标记(marker)对象,
    // 并设置是否改变地图状态以至于所有的marker对象都在当前地图可视区域范围内显示。
    ArrayList<Marker> newOverlays = map.addMarkers(optionsList, moveToCenter);
    overlays.addAll(newOverlays);
}

public void removeOverlay() {
    // 从地图上删除所有的覆盖物(marker,circle,polyline 等对象),
    // 但myLocationOverlay(内置定位覆盖物)除外。
//        boolean isKeepMyLocationOverlay = true;
//        map.clear(isKeepMyLocationOverlay);

    for (BaseOverlay overlay : overlays) {
        if (overlay instanceof Marker) {
            Marker marker = (Marker) overlay;
            marker.hideInfoWindow();
        }
    }
    overlays.clear();
}

设置属性

public void setFlag(String flag) {
    selectedFlag = flag;

    switch (selectedFlag) {
    case SIMPlE_MODE:
        map.setInfoWindowAdapter(null);
        break;
    case ADAPTER_WINDOW_MODE:
        map.setInfoWindowAdapter(new WindowModeAdapter());
        break;
    case ADAPTER_CONTENT_MODE:
        map.setInfoWindowAdapter(new ContentModeAdapter());
        break;
    }
}

说明:自定义样式参考官方Demo,WindowModeAdapterContentModeAdapter为自定义两个适配器。代码和布局见附录。

自定义样式

  • WindowModeAdapter

布局custom_info_window.xml (background+image+tItle+snippet)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@drawable/custom_info_bubble"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/badge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="5dp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:ellipsize="end"
            android:singleLine="true"
            android:textColor="#ff000000"
            android:textSize="14dp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/snippet"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            android:textColor="#ff7f7f7f"
            android:textSize="14dp" />
    </LinearLayout>

</LinearLayout>

WindowModeAdapter

private class WindowModeAdapter implements AMap.InfoWindowAdapter {
    @Override
    public View getInfoWindow(Marker marker) {
        // 加载自定义布局文件作为InfoWindow的样式
        View view = LayoutInflater.from(context).inflate(R.layout.custom_info_window, null);
        render(marker, view);
        return view;
    }

    @Override
    public View getInfoContents(Marker marker) {
        return null;
    }
}
  • ContentModeAdapter

布局custom_info_contents.xml (image+tItle+snippet)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/badge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="5dp"
        android:adjustViewBounds="true" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:ellipsize="end"
            android:singleLine="true"
            android:textColor="#ff000000"
            android:textSize="14dp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/snippet"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            android:textColor="#ff7f7f7f"
            android:textSize="14dp" />
    </LinearLayout>

</LinearLayout>

ContentModeAdapter

private class ContentModeAdapter implements AMap.InfoWindowAdapter {
    @Override
    public View getInfoWindow(Marker marker) {
        return null;
    }

    @Override
    public View getInfoContents(Marker marker) {
        // 加载自定义布局文件作为InfoWindow的样式
        View view = LayoutInflater.from(context).inflate(R.layout.custom_info_contents, null);
        render(marker, view);
        return view;
    }
}
  • render方法(设置image+title+snippet)
private void render(Marker marker, View view) {
    ImageView imageView = view.findViewById(R.id.badge);
    imageView.setImageResource(android.R.drawable.ic_menu_gallery);

    String title = marker.getTitle();
    TextView titleUi = view.findViewById(R.id.title);
    if (title != null) {
        SpannableString titleText = new SpannableString(title);
        titleText.setSpan(new ForegroundColorSpan(Color.RED), 0, titleText.length(), 0);
        titleUi.setTextSize(15);
        titleUi.setText(titleText);
    } else {
        titleUi.setText("");
    }

    String snippet = marker.getSnippet();
    TextView snippetUi = view.findViewById(R.id.snippet);
    if (snippet != null) {
        SpannableString snippetText = new SpannableString(snippet);
        snippetText.setSpan(new ForegroundColorSpan(Color.GREEN), 0, snippetText.length(), 0);
        snippetUi.setTextSize(20);
        snippetUi.setText(snippetText);
    } else {
        snippetUi.setText("");
    }
}

加载与移除地图

public void onMapLoaded() {
    addMarkers();
    setFlag(SIMPlE_MODE);
}

public void onMapDestroy() {
    removeOverlay();

    for (BitmapDescriptor bitmap : bitmaps) {
        bitmap.recycle();
    }
    bitmaps = null;
}

MapInfoWindowActivity 类

  • 以下是MapInfoWindowActivity类部分代码

控件响应事件

public void setMarkerFlag(View view) {
    boolean checked = ((RadioButton) view).isChecked();
    if (!checked)
        return;

    int id = view.getId();
    String flag;
    if (id == R.id.simpleMode)
        flag = MapInfoWindow.SIMPlE_MODE;
    else if (id == R.id.adapter_window_mode)
        flag = MapInfoWindow.ADAPTER_WINDOW_MODE;
    else if (id == R.id.adapter_content_mode)
        flag = MapInfoWindow.ADAPTER_CONTENT_MODE;
    else
        return;

    mapInfoWindow.setFlag(flag);
}

运行效果图

简单适配器(窗口)适配器(内容)
在这里插入图片描述在这里插入图片描述在这里插入图片描述
默认样式自定义:
background+image+title+snippet
自定义:
image+title+snippet

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2109172.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

215篇【大模型医疗】论文合集(附PDF)

ChatGPT的横空出世引发了新一轮生成式大模型热潮&#xff0c;作为最新技术的"试验场"&#xff0c;医疗也成为众多大模型的热门首选。 我整理了215篇医疗和大模型的论文&#xff0c;供大家学习和参考。 领215篇医疗和大模型论文

欧拉下搭建第三方软件仓库—docker

1.创建新的文件内容 切换目录到etc底下的yum.repos.d目录&#xff0c;创建docker-ce.repo文件 [rootlocalhost yum.repos.d]# cd /etc/yum.repos.d/ [rootlocalhost yum.repos.d]# vim docker-ce.repo 编辑文件,使用阿里源镜像源&#xff0c;镜像源在编辑中需要单独复制 h…

vue3的学习(2)

属性绑定 1.将一个容器中的class和id使用vue用法赋上具体的值&#xff0c;这样就可以动态的给容器添加上自己想要给其添加的class或者id或者title。 2.关键语法&#xff0c;在容器中的class或者id或者title前面加上 "v-bind:"&#xff0c;当加上"v-bind关键语…

计算机网络基础 - 应用层(2)

计算机网络基础 应用层FTP 与 EMail文件传输协议 FTP电子邮件 EMail主要组成部分SMTP概述SMTP 与 HTTP1.1 邮件报文格式报文格式多媒体扩展 MIME 邮件访问协议概述POP3IMAP DNS概述域名结构工作机理集中式设计分布式、层次数据库根 DNS 服务器顶级域 DNS 服务器权威 DNS 服务器…

公司的企业画册如何制作?

企业画册是公司形象和产品服务展示的重要载体&#xff0c;一个制作精良的企业画册不仅能展示公司的实力&#xff0c;也能提升客户对公司专业度的认可。以下是制作企业画册的步骤和要点&#xff0c;帮助你的公司画册既美观又实用。 1.要制作电子杂志,首先需要选择一款适合自己的…

OpenCV结构分析与形状描述符(7)计算轮廓的面积的函数contourArea()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算轮廓的面积。 该函数计算轮廓的面积。与 moments 类似&#xff0c;面积是使用格林公式计算的。因此&#xff0c;返回的面积与你使用 drawCo…

Mysql中的隐式COMMIT以及Savepoints的作用以及MySQL的Innodb分空间存储、设计优化、索引等几个小知识点整理

一、Mysql中的隐式COMMIT以及Savepoints的作用 Mysql默认是自动提交的&#xff0c;如果要开启使用事务&#xff0c;首先要关闭自动提交后START TRANSACTION 或者 BEGIN 来开始一个事务&#xff0c;使用ROLLBACK/COMMIT来结束一个事务。但即使如此&#xff0c;也并不是所有的操作…

零知识证明在BSV网络上的应用

​​发表时间&#xff1a;2023年6月15日 2024年7月19日&#xff0c;BSV区块链主网上成功通过使用零知识证明验证了一笔交易。 零知识证明是一种技术&#xff0c;它允许一方&#xff08;证明者&#xff09;在不透露任何秘密的情况下&#xff0c;向另一方&#xff08;验证者&…

TP-link-路由器上网设置(已有路由器再连接新的网线)

一、192.168.0.1进入管理界面&#xff0c;比如密码&#xff1a;D804D804。 二、这是设置连接账户和密码&#xff08;比如账户&#xff1a;TP-LINK_F56C 比如密码&#xff1a;D804D804&#xff09;登录后台管理、移动设备连接。比较固定。 三、 有的网络是分&#xff1a;&#…

JS面试真题 part1

JS面试真题 part1 1、说说JavaScript中的数据类型&#xff0c;储存上的差别2、说说你了解的js数据结构3、DOM常见的操作有哪些4、说说你对BOM的理解&#xff0c;常见的BOM对象你了解哪些5、 和 区别&#xff0c;分别在什么情况使用 1、说说JavaScript中的数据类型&#xff0c;…

K8s的Pv和Pvc就是为了pod数据持久化

一、 1.pv&#xff08;persistent volume&#xff09;&#xff1a;是k8s虚拟化的存储资源&#xff0c;实际上就是存储&#xff0c;列如本地的硬盘、网络文件系统&#xff08;Nfs&#xff09;、lvm、RAID、云存储。 2.pvc&#xff1a;pod对存储资源的请求&#xff0c;定义了需…

MyBatis:解决数据库字段和Java对象字段不匹配问题及占位符问题

MyBatis&#xff1a;解决数据库字段和Java对象字段不匹配问题及占位符问题 文章目录 MyBatis&#xff1a;解决数据库字段和Java对象字段不匹配问题及占位符问题一、数据库字段和Java对象字段不匹配问题1、问题描述2、解决方案2.1、方案12.2、方案22.3、方案3 二、占位符问题1、…

ELK在Linux上部署教程

Docker Compose搭建ELK Elasticsearch默认使用mmapfs目录来存储索引。操作系统默认的mmap计数太低可能导致内存不足&#xff0c;我们可以使用下面这条命令来增加内存 sysctl -w vm.max_map_count262144创建Elasticsearch数据挂载路径 mkdir -p /echola/elasticsearch/data对…

Day 3 - 5 :线性表 — 单链表

存储结构 将线性表中的各元素分布在存储器的不同存储块&#xff0c;称为结点。 结点的data域存放数据元素ai&#xff0c;而next域是一个指针&#xff0c;指向ai的直接后继ai1所在的结点。 如果要删除a1&#xff0c;只要修改a1前手元素指针的指向即可。 例如&#xff1a;需要找到…

案例——Mysql主从复制与读写分离

目录 一、为什么需要主从复制 二、主从复制原理 2.1复制类型 2.2mysql主从复制的工作过程 2.2.1mysql主从复制延迟 2.3mysql的三种同步方式 2.3.1异步复制 2.3.2同步复制 2.3.3半同步复制 2.4mysql应用场景 三、主从复制实验 3.1主从服务器事件同步 3.1.1master服务…

Web 地图服务 简介

网络地图服务 网络地图服务 由通过互联网托管的地理空间数据组成&#xff0c;其标准由开放地理空间联盟 (OGC) 制定。WMS 支持在 Web 浏览器中以地图或图像的形式交换空间信息并通过 Web 查看。 网络地图服务有很多种类型。例如&#xff0c;一些最常见的格式是 WMS、WFS、WCS…

C140 杨辉三角

C140 杨辉三角 题目题解(94)讨论(102)排行面经 new 简单 通过率&#xff1a;29.57% 时间限制&#xff1a;1秒 空间限制&#xff1a;256M 知识点C工程师牛客 校招时部分企业笔试将禁止编程题跳出页面&#xff0c;为提前适应&#xff0c;练习时请使用在线自测&#xff0c;…

tomato靶场攻略

1.使用nmap扫描同网段的端口&#xff0c;发现靶机地址 2.访问到主页面&#xff0c;只能看到一个大西红柿 3.再来使用dirb扫面以下有那些目录&#xff0c;发现有一个antibot_image 4.访问我们扫到的地址 &#xff0c;点金目录里看看有些什么文件 5.看到info.php很熟悉&#xff0…

Java对象拷贝的浅与深:如何选择?

在日常开发中&#xff0c;我们经常需要将一个对象的属性复制到另一个对象中。无论是使用第三方工具类还是自己手动实现&#xff0c;都会涉及到浅拷贝和深拷贝的问题。本文将深入讨论浅拷贝的潜在风险&#xff0c;并给出几种实现深拷贝的方式&#xff0c;帮助大家避免潜在的坑。…

SpringBoot开发——整合Logbook进行HTTP API请求响应日志输出

文章目录 1. 简介依赖管理2. 实战案例2.1 基本用法2.2 结合Logback日志记录到文件2.3 自定义核心类Logbook2.4 自定义日志输出Sink2.5 与RestTemplate集成1. 简介 记录HTTP API请求响应日志对于监控、调试和性能优化至关重要。它帮助开发者追踪API的使用情况,包括请求来源、参…