简述SprigMvc、SprigMvc快速使用案例(用户登录检测和用户退出) ╰+哭是因爲堅強的太久メ 2024-03-04 03:03 12阅读 0赞 1. 1.什么是SpringMvc 优点是什么。以及个人理解SpringMvc 2. 2.SpringMvc快速上手案例 --以及其中会遇见错误解决 -------------------- ## ## ## **1.认识Spring Mvc:** ## Spring MVC 是一种基于 Java 的 Web 应用开发框架,它是 Spring Framework 的一部分。Spring MVC 提供了一种模型-视图-控制器(Model-View-Controller,MVC)的架构模式,用于构建灵活、可扩展的 Web 应用程序。 * 模型(Model)表示应用程序的数据和业务逻辑 * 视图(View)表示用户界面 * 控制器(Controller)则协调模型和视图之间的交互。 使用 Spring MVC,开发人员可以将应用程序的不同层进行解耦,使代码更具可维护性和可测试性。 **Spring MVC 的主要特点包括:** 1. **灵活的配置**:Spring MVC 可以通过灵活的 XML 配置或基于注解的配置来定义控制器、映射 URL 和处理请求等。这使得开发人员可以根据自己的需求进行定制和扩展。 2. **强大的请求处理**:Spring MVC 提供了丰富的请求处理功能,包括 URL 映射、请求参数绑定、表单验证、文件上传等。开发人员可以通过配置或编程方式对请求进行处理,并方便地获取请求参数、处理结果并返回响应。 3. **视图解析**:Spring MVC 支持多种视图技术,包括 JSP、Thymeleaf、Freemarker 等,开发人员可以根据自己的喜好和项目需求选择合适的视图技术。 4. **拦截器和过滤器**:Spring MVC 提供了拦截器和过滤器机制,可以在请求处理前后进行拦截和处理,实现一些通用的功能,如身份验证、日志记录等。 5. **易于测试**:Spring MVC 的松耦合设计和依赖注入特性使得对控制器进行单元测试变得简单。开发人员可以使用各种测试框架(如JUnit)来编写和执行测试用例,确保代码质量和功能的正确性。 **总之**,Spring MVC 是一个成熟、功能强大的 Web 应用开发框架,它提供了丰富的功能和灵活的配置方式,可以帮助开发人员快速构建高效、可维护的 Web 应用程序。 自己感觉Spring Mvc: 感觉就是和以前的4层架构 servlet service bean dao 中的前三个相似。同时还加入许多功能,如拦截、视图、数据绑定和验证...... 替代了用户界面和控制器之间的数据交互,以及整个请求-响应的处理流程。 最终理解:Spring MVC是建立**在Servlet、Service和DAO**的**基础上**进行**封装和扩展的框架,**旨在简化Web应用程序的开发和管理。Spring MVC框架**并不是直接替代Servlet、Service和Bean**的功能,而是**在其基础上**提供了更高级、更灵活的Web开发框架。 -------------------- ## 2.SpringMvc快速上手案例: ## 案例:用户登录检测和用户退出 思想:用户登录后把id存到session中。拦截全部页面,判断是否存在id如果存在放行,(在登录页面就不要拦截了),不存在id就去登录页面。退出就是清除session信息。 和以前使用过程差不多思想,思考实现--创建项目---创建类---创建函数方法---方法调用--测试。 ### 1.创建maven项目 ### [创建Maven视频-包含解决错误方法![icon-default.png?t=N7T8][icon-default.png_t_N7T8]https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/b99e2fd2853a443ca67aeec78af31709.png][Maven_-_icon-default.png_t_N7T8_icon-default.png_t_N7T8_https_pan.baidu.com_s_1GUsdCQJhAkGcyNhRl84YOw_pwd_1234] **创建maven---progect --选war包(项目是一个需要提供 Web 服务的应用程序)** **Jar:如果你的项目是一个独立的 Java 库,将被其他项目引用,而不是部署到 Web 容器上运行,那么选择 JAR 项目类型是合适的。** **War:如果你的项目是一个需要提供 Web 服务的应用程序,需要在 Web 容器中部署并运行,那么选择 WAR 项目类型是合适的。** ![325c2597191c42bf8ec55b7137d128ea.png][] ![8ff92e5158c2413aad84b4bd7fdcf8cb.png][] ![ad087874730043ddb154c19425f17066.png][] ![e23cfe5ed8ef48f0a4bd12fd32403c94.png][] ![6ec0416d5cdf4421a45f196253f698df.png][] ### 错误解决 ### **错误1:** **POM中包含有[maven][]\-war-plugin插件,自带插件版本太低** **解决办法:** **在pom.xml中添加一段话:保存就好了** <!--配置了一个名为"maven-war-plugin"的Maven War插件 解决:Cannot access defaults field of Properties问题 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.1</version> </plugin> </plugins> </build> ![c49e1aa66c69456786a22c37a2bca0c2.png][] ![62b785c9948348c09626e7678f66923b.png][] **错误2:** **有些版本的Eclipse创建工程后pom.xml会报错:web.xml is missing and <failOnMissingWebXml> is set to true,原因是工程的webapp目录下没有自动生成web.xml和WEB-INF配置信息。办法1:右击工程->java EE Tools->Generate Deployment Descriptor Stub会自动生成配置。** ![5593a5590fe24e63a280b143136b2d18.png][] ![a8dff2beaea04c0d9aaaa979885c6b31.png][] **办法2:直接通过其他项目拷贝一个WEB-INF目录及web.xml配置也行,效果一样。** **最后:需要更新或者刷新这个maven项目:** ![6ad5c0c4885a482a9011d07c29035f19.png][] ![91c948f5a97e4eae8aea0737d94c183f.png][] 就好了。 最后创建好的maven: ![cf5c6947cc66438e80e8db678d406a87.png][] ### 2.整体结构 ### ![fa3d5d1b861f4f519e0083dbbc6498af.png][] **实现功能是 拦截 与检索用户信息 所以需要创建用户类** #### **1.创建用户类:** #### **Student** package com; public class User { private String u_id; private String u_name; public String getU_id() { return u_id; } public void setU_id(String u_id) { this.u_id = u_id; } public String getU_name() { return u_name; } public void setU_name(String u_name) { this.u_name = u_name; } @Override public String toString() { return "User [u_id=" + u_id + ", u_name=" + u_name + "]"; } public User(String u_id, String u_name) { super(); this.u_id = u_id; this.u_name = u_name; } public User() { super(); } } #### **2.创建页面:** #### **页面有首页 登录 成功 这三个页面** ![e24d253197344ff7a788bdbec41c21a5.png][] 首页:cs.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <header> <h1>首页开始界面!</h1> </header> <nav> <ul> <li><a href="login.do">按钮登录</a></li> <li><a href="text.do">按钮text.do</a></li> <li><a href="text_cs.do">按钮text_cs.do</a></li> <li><a href="deletSession.do">清除session中信息(退出用户)</a></li> </ul> </nav> <main> </main> </body> </html> 登录:login.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>登录</title> </head> <body> <form action="login.do"> <input type="text" name="u_id"> <input type="submit" value="登录"> </form> </body> </html> 成功:public\_cs.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>成功</title> </head> <body> <img alt="" src="./img/cs.png" style="width: 98%;height: 500px;"> <button onclick="redirectToJsp()">退出</button> </body> <script> function redirectToJsp() { window.location.href = "cs.jsp"; } </script> </html> #### #### #### **3.创建拦截器:** #### **LoginInterceptor** **这是一个自己创建的拦截器,继承springmav的拦截器接口HandlerInterceptor,重写三个方法preHandle postHandle afterCompletion。** **判断当前是否登录,也就是判断是否存在用户名。思想登录成功就把用户名存到session中从session中获取用户名,是否存在来确定用户是否登录。如果在登录页面就不需要获取用户名,因为正在登录或者注释就无需判断。如果你没有用户名,也就是没有获取到用户名,直接跳转到登录。** package com; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import com.fasterxml.jackson.databind.cfg.HandlerInstantiator; public class LoginInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("拦截器处理逻辑"); // 当前拦截器主要功能 //思路: 判断是否在登录界面,在用户界面直接放行,如果不在判断是否存在用户id,存在放行,不存在就重定向登录页面 System.out.println("1.1:这是拦截器,现在开始判断是否在登录界面,如果不在再次判断是否存在用户id"); // 获取当前你的url路径判断是否包含longin.jsp(登陆界面) 中的login /* * 这里注意.getRequestURI()和.getRequestURL(); * * getRequestURI() 方法返回一个String类型对象 ,只包含请求的路径部分。 * 如果请求的URL是 https://example.com/test/page.jsp?param=value,通过 getRequestURI() 方法获取到的值就是 * /test/page.jsp。 * * * getRequestURL() 方法返回一个StringBuffer对象,其中包含了整个请求的URL,包括协议、主机名、端口号、查询参数等。 * 如果请求的URL是 https://example.com/test/page.jsp?param=value,通过 getRequestURL() 方法获取到的值就是 * https://example.com/test/page.jsp。 * */ String url=request.getRequestURI(); //StringBuffer url2=request.getRequestURL(); System.out.println("1.2:获取url: "+url); int i=url.indexOf("login");//判断url中"login"位置,存在返回下标,不存在返回-1 if(i!=-1) { System.out.println("1.3:是登录页面!放行"); return true; }else { System.out.println("1.3:不是登录页面!在进行判断"); //如果不是登录界面判断是否存在id String id=(String)request.getSession().getAttribute("u_id"); if(id==null||id.equals("")) { System.out.println("1.4:没有用户id,即没有用户登录去登录页面!"); response.sendRedirect("login.jsp"); System.out.println("请输入用户id"); return false; }else { System.out.println("1.4:存在用户id: "+id); System.out.println("放行!"); return true; } } // return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { //后置处理逻辑 System.out.println("后置处理逻辑"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 完成处理后的逻辑 System.out.println("完成处理后的逻辑"); System.out.println("____________________________________________________"); } } #### **4.UserController.java配置** #### package com; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; /* * @Controller: * @Controller 注解通常用于标识一个类为 Spring MVC 控制器, * 在 Spring MVC 中,你可以使用 @Controller 注解来定义一个控制器类。控制器类通常用于处理用户的请求,并返回响应结果。 * * @RequestMapping: * @RequestMapping("/login.do") 注解则用于将请求的 URL 映射到控制器的方法上。 * 当用户发出一个 /login.do 的请求时,Spring MVC 框架就会自动调用与之对应的控制器方法并返回相应结果。 * */ @Controller public class UserController { // 实现前端页面数据的接受与传递 @RequestMapping("/login.do")//也可以写成 @RequestMapping(value = "login.do", method = RequestMethod.GET) private String user_Login(HttpSession session,String u_id) { /* *HttpSession 是 Servlet API 提供的一个接口,用于表示客户端和服务器之间的会话。 *通过使用 session 对象,你可以存储和检索与特定用户相关的数据,并在多个请求之间保持会话状态。 *简单理解就是创建共享session空间的声明 * *这里的String u_id 不是随便定义的,是前台login.jsp表单提交过来的u_id 需要一致 *如果想定义的不一样的要使用 @RequestParam("u_id ") String userID */ System.out.print("2.1: 接受前台传递的数据:"+u_id); System.out.println(" session--的数据:"+session.getAttribute("u_id")); // 把接受的数据传递到session空间共享出去 session.setAttribute("u_id", u_id);//"u_id"共享名称 u_id共享的数据(前台传递什么我共享什么) /* * ...................其他操作,这个简单案例就不做了 */ System.out.println("由于没有放行,会继续执行LoginInterceptor.java的方法!"); System.out.println("执行完剩余的后开始新一轮判断!直到放行才在走 return \"redirect:getIndex\"。"); return "redirect:getIndex";//表示在处理完登录操作后,将重定向到名为 "getIndex" 的地址 } @RequestMapping("/getIndex") private String login_中转站() { System.out.println("3.1:放行成功!"); System.out.println("3.2:重定向public_cs.jsp,结束!"); return "public_cs"; } @RequestMapping("/text") private String text0() { System.out.println("text"); return "public_cs"; } @RequestMapping("/text.do") private String text() { System.out.println("text.do"); return "public_cs"; } @RequestMapping("/text_cs.do") private String text_cs() { System.out.println("text_cs.do"); return "public_cs"; } @RequestMapping("/deletSession.do") private String deletSession(HttpSession session) { /* * 开始我们就把信息存到session共享,session中信息会在整个会话期间。 * * session.invalidate() 是一个用于使当前会话无效的方法。 * 当调用此方法时,将会销毁当前会话,并且会删除 HttpSession中存储的所有数据。 * 清除session中存的信息 * * 我们理解的退出当前用户差不多 */ session.invalidate(); return "cs"; } } #### **5.Springmvc.xml文件配置 Spring MVC 框架的相关设置和组件:** #### **这就像最后的拼接,每一个都准备好了。告诉机器启动什么、东西在什么地方、怎么执行、最后拼接好去那里。** **主要是扫描 拦截 解析** **扫描指定位置的包,就是我们创建包位置,这样机器就知到了。** **拦截,配置拦截、不拦截的目录或者文件url。调用写好的拦截函数。** **试图解析,将逻辑视图名称解析为实际的视图页面。具体来说,它会根据视图解析规则将 /WEB-INF/views/(或者根路径 /)与视图名称拼接,并添加 .jsp 后缀作为最终的视图路径。** <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--启用 Spring MVC 的注解驱动功能。 和<mvc:annotation-driven/> 则是使用闭合标签的简写形式,不需要在元素内包含任何属性或子元素 --> <mvc:annotation-driven></mvc:annotation-driven> <!--是用于配置 Spring 框架自动扫描和注册组件的元素,它会将指定包及其子包下的带有特定注解的类注册为 Spring 的组件, 以便后续在应用中进行管理和使用。 寻找带有特定注解的类,并将其注册为 Spring 的组件。 默认情况下,它会扫描并创建带有 @Component、@Controller、@Service、@Repository 等注解的类作为组件。 --> <context:component-scan base-package="com"></context:component-scan> <!--配置拦截器 包含拦截地址 放行地址 拦截器位置 --> <mvc:interceptors> <mvc:interceptor> <!--拦截地址 --> <mvc:mapping path="/**"/> <!--放行地址 --> <mvc:exclude-mapping path="/static/**"/> <mvc:exclude-mapping path="/img/**"/> <!-- 拦截器位置 --> <bean class="com.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> <!--配置视图解析器 --> <bean id="viewResolverCommon" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/" /> <property name="suffix" value=".jsp" /> </bean> </beans> #### **6.下载对应jar包** #### pom.xml: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>text</groupId> <artifactId>9_5_text</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <!--配置了一个名为"maven-war-plugin"的Maven War插件 解决:Cannot access defaults field of Properties问题 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.1</version> </plugin> </plugins> </build> <!-- 下载对应jar包 --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.7.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.7.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.7.4</version> </dependency> </dependencies> </project> #### **7.配置最后的web.xml** #### **如果讲Springmvc.xml文件是最后的拼接,那么web.xml就是开始准备以及调用Springmvc.xml的** <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>9_5_text</display-name> <welcome-file-list> <welcome-file>cs.jsp</welcome-file><!--添加一个表示启动默认去的位置如果不存在会一直向下找找不到显示报错页面 --> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> </welcome-file-list> <!-- 用于启动 Spring MVC 框架,并配置了默认的前端控制器、静态资源放行路径和动态请求拦截分发路径。 同时,还配置了要扫描的 Spring 配置文件位置,并通过监听器加载 Spring 上下文。 --> <!-- 创建了一个名为 dispatcher 的 Servlet,并将其类指定为 org.s....,这是 SpringMVC 提供的默认前端控制器。 之后,通过 <init-param> 标签设置了一个名为 contextConfigLocation 的参数,但参数值为空, 表示使用 SpringMVC 的默认配置文件 WEB-INF/<servlet-name>-servlet.xml 来配置 SpringMVC。 --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> </servlet> <!-- 配置静态资源 简单理解就是配置放行路径url。这里的default和下面的dispatcher都是Web容器(如Tomcat)中预定义的 Servlet 名称默认的 一个表静态放行,一个表动态请求拦截再分发--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.png</url-pattern> <url-pattern>/img/*"</url-pattern> </servlet-mapping> <!-- 配置拦截路径url,所有的请求都会被前端控制器拦截处理, 将 dispatcher Servlet 映射到应用程序的根路径 /。 也就是说,当用户访问应用程序的根路径时,请求会被 dispatcher Servlet 处理。其中的 Dispatcher Servlet是Spring MVC框架中的默认前端控制器。它作为Spring MVC应用程序的核心组件,负责接收所有请求并将其分发到相应的处理器(也就是控制器)进行处理。 除了上面静态放行,下面都要检测. --> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 使用 <context-param> 标签设置了一个名为 contextConfigLocation 的参数, 并将值设为 classpath*:spring-*.xml,表示要扫描位于 classpath 下的所有以 spring- 开头、以 .xml 结尾的配置文件, 并将其加载到 Spring 的上下文中。 --> <!-- 通过监听扫描spring容器: 创建前端控制器的时候读取spring-mvc.xml配置文件启动ioc容器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:springMvc.xml</param-value> </context-param> <!-- 将其类指定为 org.springframework.web.context.ContextLoaderListener。 当应用程序启动时,该监听器将会自动加载并初始化 Spring 上下文, 从而使得应用程序能够使用 Spring 容器提供的各种功能。 --> <!-- 配置监听以实例化Spring上下文 --> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> </web-app> #### **8.测试:** #### ![a793d248d9cc42ceb4a6c349cebc0701.png][] 点击按钮2和按钮3,理论是去成功的那个页面也就是public\_cs.jsp ![70c72e72e93c4029a702721edc558613.png][] ![5172732288ed4b8a8fd2d20238a05420.png][] 但是由于当前页面url不含登录login且不存在用户id所以拦截了,去了登录页面 ![3eef54deb910471890ec98d16ea0476f.png][] ![230a226237464a16af305f2aa9d966c9.png][] 这里的案例比较简单没有做数据筛选和查询等,只要输入就并表示登录成功把获取到的当中id存入session,由于有了id就放行了,到了成功界面: ![34235f793d084662960a7d5b602e7dbc.png][] ![c8e658f46e53458f9fc10477c1aadaf9.png][] 由于session中现在存了用户id,且session性质(session中信息会在整个会话期间。),所以我们现在在会到开始界面点击2,3按钮就不在要输入或者登录了,直接跳转成功。 ![3032f9d483964b0aaf8a22d54fa8d9ea.png][] ![8a40e1232f7149ac95145f6f3a272e96.png][] 但是当我们清除session中信息后就又要判断登录了。和用户退出一样。 ![4519a877e9be47bcbb71dd6388b66aaa.png][] ![5e61e1d437f743bbbf8dc80f6106df4b.png][] [icon-default.png_t_N7T8]: https://csdnimg.cn/release/blog_editor_html/release2.3.6/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=N7T8 [Maven_-_icon-default.png_t_N7T8_icon-default.png_t_N7T8_https_pan.baidu.com_s_1GUsdCQJhAkGcyNhRl84YOw_pwd_1234]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/b99e2fd2853a443ca67aeec78af31709.png [325c2597191c42bf8ec55b7137d128ea.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/1fa44e09c580465ca4ad5f6a55682bad.png [8ff92e5158c2413aad84b4bd7fdcf8cb.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/6998c86301bc42c6b07dd4166eb6df89.png [ad087874730043ddb154c19425f17066.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/6d76e8174fc64d9ba5000a3213abfa9e.png [e23cfe5ed8ef48f0a4bd12fd32403c94.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/0321033c220b45eb99e849110eadadb7.png [6ec0416d5cdf4421a45f196253f698df.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/88dc0e980f4248328dd9c19899c06198.png [maven]: https://so.csdn.net/so/search?q=maven&spm=1001.2101.3001.7020 [c49e1aa66c69456786a22c37a2bca0c2.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/ba68d49377d9488186cbdd4b38904c04.png [62b785c9948348c09626e7678f66923b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/1fed72a5c40e424e93cefb5fad62c8aa.png [5593a5590fe24e63a280b143136b2d18.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/8886c4e3f00d4ffd894fdde0ce80e669.png [a8dff2beaea04c0d9aaaa979885c6b31.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/aa267e1178034a9c8d43b907ef676051.png [6ad5c0c4885a482a9011d07c29035f19.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/6486d8c9daae435c80237840ea7d505f.png [91c948f5a97e4eae8aea0737d94c183f.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/7eb1c7a509e14e1daf95496d74712f95.png [cf5c6947cc66438e80e8db678d406a87.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/5bc6e8d3fb7946d89e0085f39710c3bb.png [fa3d5d1b861f4f519e0083dbbc6498af.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/f315d008f4b74e3fa8f1bd922f745a33.png [e24d253197344ff7a788bdbec41c21a5.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/eeecd76e2b6a4b4f80f4cddfe631a7f8.png [a793d248d9cc42ceb4a6c349cebc0701.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/3ba3588e4ff044e4971363834a1dd7ee.png [70c72e72e93c4029a702721edc558613.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/18acb674421c4ddca4a82a59de8137d4.png [5172732288ed4b8a8fd2d20238a05420.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/92b952a186134ba1ae56430c06400d0b.png [3eef54deb910471890ec98d16ea0476f.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/6a1bd634b86c4197aa8eb09daa5c2537.png [230a226237464a16af305f2aa9d966c9.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/decb75d4985d462d88a4b71e1a8baca3.png [34235f793d084662960a7d5b602e7dbc.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/fc7c4a82e3ec450385477e900220d6d2.png [c8e658f46e53458f9fc10477c1aadaf9.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/fd146d85e38046f5a3c199d70292839a.png [3032f9d483964b0aaf8a22d54fa8d9ea.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/83e8c9d8899a483a8f680d5906b29191.png [8a40e1232f7149ac95145f6f3a272e96.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/22033fdb8c5e4bcbb430fe2e74706744.png [4519a877e9be47bcbb71dd6388b66aaa.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/2ac6f654263e48beb78330a942242d47.png [5e61e1d437f743bbbf8dc80f6106df4b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/04/62c79a948eb7495080f92c2d8e8b573b.png
还没有评论,来说两句吧...