SpringMVC体系结构and处理请求控制器 清疚 2022-12-05 05:19 128阅读 0赞 # SpringMVC # ## MVC设计模式: ## 首先先熟悉回忆一下MVC设计模式, [了解][Link 1] ### MVC分层设计模式: ### 它是软件**架构模式**的一种, 强制的将软件系统的: 输入 处理 输出 把软件系统分为三个部分:模型(Model) 视图(View) 控制器(Controller) ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center] **视图(View):** 负责: 数据展示 用户交互 数据验证 界面设计 …等功能; 组件: JSP 或 HTML文件… **控制器(Controller):** 负责:接收并转发请求,对请求进行处理,做出对于的响应操作; 组件:Servlet… **模型(Model):**`是应用程序的主体部分` 负责:数据业务逻辑操作处理, 实现数据的存取操作… JavaBean(Java类) 组件:业务逻辑(Service) 与数据库交互(Dao) 贯穿各层的数据模型,实体类(POJO/以前我都是entity) -------------------- ### JSP Model1 ### 只有视图 和 模型… ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 1] 当业务流程为简单的时候,可以把控制器的功能交给视图来实现, 这种模式被称为 `JSP Model1` **总结:** Model1 在一定基础上,实现了MVC :JSP( 控制层和视图层 ) + JavaBean为模型层; **但** 其中JSP 身兼数职, 又要负责数据展示, 还要注意 业务流程控制, 结构较为混乱… **而且** 也不是程序适合的 松耦合架构模式 `当业务流程复杂时候不推荐使用` ### JSP Model2 ### 这种模式就是 JSP+Servlet+JavaBean (哈哈哈,以前学过现在在学框架,有点忘记了有对这方面的笔记,在oneNote上… 还做了一个小型电商项目) ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 2] 相比 Model1 , Model2是将控制层(Servlet)单独划分出来负责业务流程的控制, 接收请求 创建所需的JavaBean实例; 并将处理后的数据,响应给视图层(JSP) **总结:** 相比 Model1 , Model2结构更清晰 JSP不在一个人抗下所有 是一个相对 `松耦合` 的架构模式; **所以**除非项目非常简单使用 Model1, 一般都使用 Model2 ### MVC处理过程 ### ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 3] **MVC 优点** 多视图共享一个模型,大大提高代码的可重用性 MVC三个模块相互独立,松耦合架构 控制器提高了应用程序的灵活性和可配置性 有利于软件工程化管理 `完美的系统架构 = 松耦合+高重用性+高扩展性` **MVC 缺点** 原理复杂 增加了系统结构和实现的复杂性 视图对模型数据的低效率访问 (中间还要经过一个控制器~必定会影响…) **`so:`**`它并不适合, 小型项目,花费大量时间将 MVC应用到并不是很大的 应用程序中通常 "得不偿失"` ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 4] **智勇建议你可以:细品细品** ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 5] -------------------- ## SpringMVC 介绍及环境搭建: ## ok, 了解了MVC设计模式之后就可以更容易的, 接收SpringMVC 框架了 SpringMCV 就是 Spring框架提供一个用于 Web应用开发中的一个框架; **SpringMVC框架介绍:** 在MVC设计模式中, SpringMVC 就是作为**控制器( Controller )** 来建立模型与视图的数据交互; `结构最清晰的MVC Model2实现` SpringMVC 框架采用松耦合 可拔插的组件结构, 相比其它 MVC框架 ,具有高度可扩展性; ### SpringMVC环境搭建: ### 在MyElicpse 中新建Web ProJect项目后配置 SpringMVC框架; **Spring MVC框架搭建步骤:** 下载jar文件并导入工程 :**(Myelicpse工具有自带的类库~ )** `spring-web-3.2.13.RELEASE.jar` Web应用开发的使用 Spring框架所需的 核心类; `spring-webmvc-3.2.13.RELEASE.jar` 框架相关的类,包含框架的 Servlets WebMVC 以及对控制器 和 视图的支持; **配置文件**在web.xml中配置< Servlet> 元素; **创建Spring MVC的配置文件**(也是Spring 核心配置文件) **创建Controller-处理请求的控制器`BeanNameUrlHandlerMapping`** (相当于以前写的 Servlet ;) **创建View-JSP** **部署运行** ## 正片开始! ## [项目连接][Link 2] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 6] 配置文件: 在web.xml中配置< Servlet> 元素; `web.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_3_0.xsd" version="3.0"> <!-- 配置SpringMVC核心控制器:DispatcherServlet DispatcherServlet:是SpringMVC的核心,负责接收请求 和 响应操作; --> <servlet> <!-- servlet-name: 声明一个名为:mvc的Servlet servlet-class: 类型是DispatcherServlet,注意别导错包咯~ --> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class> <!-- 初始化参数: 通过contextConfigLocation 属性来指定SpringMVC配置文件的位置; --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <!-- 值 1 : 配置标记服务器启动时候加载DispatcherServlet --> <load-on-startup>1</load-on-startup> </servlet> <!-- 通过servlet-mapping: 指定对应的Servlet --> <servlet-mapping> <servlet-name>mvc</servlet-name> <!-- 指定对于的Servletname --> <url-pattern>/</url-pattern> <!-- / 匹配所有的请求(不包含.jsp) /* 包含.jsp 即所有的请求都会经过 url-pattern --> </servlet-mapping> </web-app> **/ 和 / \* 的区别:** > < url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进入spring的 DispatcherServlet类 。 > < url-pattern > /\* </ url-pattern > 会匹配 \*.jsp . 因此会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。 > 映射路径为 / 【不要用/ \*,会404】 第二步可以创建 Controller(控制器) 也可以是 SpringMVC 的核心配置文件; 我还是喜欢 Controller 其实就相当于以前的 Servlet ; **创建Controller** 和Servlet 一样该控制器本质其实也是一个 JavaBean(普通的Java类) Servlet 是继承了HttpServlet **抽象类**; Controller 则是,**需要继承**:org.springframework.web.servlet.mvc.AbstractController 类; 并实现对应的 AbstractController 方法(); `HelloController.java` import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; //导包 public class HelloController extends AbstractController { //继承了 AbstractController 类 @Override //实现handleRequestInternal方法(request,response); 返回值:ModelAndView protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { //打印输出显示 System.out.println("进入Hello:Controller"); //根据url name获取作用域值; String name = request.getParameter("name"); name = "Hello:"+name; //创建一个 ModelAndView 对象; ModelAndView mav = new ModelAndView(); mav.addObject("msg",name); mav.setViewName("index"); return mav; // 这里该控制器只处理一种控制;如果有多个还需要像之前一个 url中存在一个 opt 之类的name,来确认要做的操作; // String op = request.getParameter("op"); // if("增".equals(op)){ // ....省略操作 // }else if("删".equals(op)){ // ....省略操作 // }else .... } } /* * ModelAndView(模块 和 视图): * 正如其名,它代表 SpringMVC 中呈现视图界面所使用的 Model(模型书记) 和 View(视图) * addObject(..); 设置需要返回的值,类似于 request.setAttribute(x,x); 键值方式存在数据在 Model中; * setViewName(..); 通过方法跳转到指定的页面名 经过 视图解析器,加上文件: 前缀/后缀 |最终响应浏览器; * addAllObjects(Map<String,?> map); 方法看出模型数据也是一个Map 对象; */ ok 控制器写完了就是SpringMVC的配置文件了; `applicationContext.xml` <?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <!-- 配置处理器映射 name :页面根据name名,找到对应的 控制器; class :指定对应的控制器; 作用: 将指定的URL 请求指定给一个Controller 处理; Spring 提供了多种处理器映射(不一一举例了)...根据需求选择合适的处理器映射; Spring 默认使用BeanNameUrlHandlerMapping : Spring容器根据URL名查找,同名的Bean.. 所以web.xml <url-pattern>/</url-pattern> 将根目录截取之后的 文件名;这里就是 /Hollo.html 了,就通过文件名,找到对应的 控制器; --> <bean name="/Hollo.html" class="com.wsm.controller.HelloController" /> <!-- 配置视图解析器(ViewResolver): 处理请求的最后一件事情就是 "渲染输出" 控制器做出响应最后会经过这里进行渲染输出; DispatcherServlet(前端控制器) 会查到一个视图解析器,将控制器返回的逻辑视图名称,渲染为一个指定的 实际视图文件上; Spring同样提供了多种...这里使用:InternalResourceViewResolver 总结: 请求处理方法执行完之后,最终会返回一个 ModelAndView 对象,对于那些返回String 等类型的处理方法; SpringMVC 会在内部通过ViewResolver将它们装配成一个 ModelAndView对象,它包含 "逻辑视图" "数据模型" 通常使用 InternalResourceViewResolver 作为一个视图解析器,通常用于存储 JSP 和 JSTL 等视图; --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <!-- <property name="prefix" value="前缀"></property> --> <property name="suffix" value=".jsp"></property> </bean> <!-- suffix 后缀,为视图ViewName 添加后缀; prefix 前缀,默认文件为根目录 localhost:8080/项目名/ 前缀就是 localhost:8080/项目名/前缀/文件名+后缀 方式返回浏览器; 这里建议和前面控制器搭配学习... --> </beans> 最后奉上 `index.jsp` 可以运行了 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h2>${msg }</h2> <form action="Hollo.html" method="post"> <input type="text" name="name"> <input type="submit" value="提交"> </form> </body> </html> ![在这里插入图片描述][20200910093243912.png_pic_center] 验证, 提交后程序经过了 控制器处理后,再次呈现给用户看… -------------------- ## 注解操作 + 参数传递; ## 上述示例通过 BeanNameUrlHandlerMapping 访问完成了请求与 Contorller 之间的映射关系; 那如果存在很多映射则就要写很多的 … Spring容器提供了注解~ 修改Demo… `applicationContext.xml` <?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <!-- 使用注解完成,一次需要导入对应的命名空间:context mvc 别忘了 --> <context:component-scan base-package="com.wsm.controller" /> <!-- 扫描包下注解 --> <!-- 支持mvc注解驱动 在spring中一般采用@RequestMapping注解来完成映射关系 要想使@RequestMapping注解生效 必须向上下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理。 而annotation-driven配置帮助我们自动完成上述两个实例的注入。 --> <mvc:annotation-driven/> <!-- 配置视图解析器: 处理请求的最后一件事情就是 "渲染输出" 控制器做出响应最后会经过这里进行渲染输出; DispatcherServlet(前端控制器) 会查到一个视图解析器,将控制器返回的逻辑视图名称,渲染为一个指定的 实际视图文件上; Spring同样提供了多种...这里使用:InternalResourceViewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <!-- <property name="prefix" value="前缀"></property> 注意前缀前后加 / 分隔,方便文件拼接URL --> <property name="suffix" value=".jsp"></property> </bean> <!-- suffix 后缀,为视图ViewName 添加后缀; prefix 前缀,默认文件为根目录 localhost:8080/项目名/ 前/后缀就是 localhost:8080/项目名 前缀/文件 后缀 这里建议和前面控制器搭配学习... --> </beans> `HelloController.java` package com.wsm.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; @Controller //@Controller是为了让Spring IOC容器初始化时自动扫描到; //@RequestMapping("/WSM") //@RequestMapping 声明在类上; (对应示例二,示例一注释即可..) public class HelloController { //示例一 @RequestMapping("/Hollo1.html") public ModelAndView Hollo(String name){ //方法参数 name 和表单name 一样可以自动匹配,如果不一样会返回null; //控制台打印输出显示 //所以一定要注意参数名一致哦! System.out.println("进入Hello:Controller"); name = "Hello:"+name; //参数拼接 //创建一个 ModelAndView 对象; ModelAndView mav = new ModelAndView(); mav.addObject("msg",name); //存储 mav.setViewName("index"); //返回响应 return mav; } // 这里开始使用注解修改Demo /* * 首先这里的控制器和之前已经不一样了,而是直接的一个类; 并没有继承AbstractController类来实现 controller; *@Controller * 而是使用了 @Controller 注解来使一个 JavaBean 成为一个controller(控制器); * 类也没有重写什么方法,而是在类中定义方法,声明注解 @RequestMapping 来指定对应的控制器代码操作; * 这样一方面节省了很多 控制器的类型声明,还避免了不同操作不同控制器代码的 op 验证操作;(直接根据注解找到对应的方法执行的代码,真好~) *@RequestMapping * 用来指定控制器,完成映射,页面发起请求URL : localhost:8080/项目名 根目录截取掉 剩下的来这儿匹配; 找到对应的控制器; * 写法: * @RequestMapping("/映射名") 或 @RequestMapping(value="/映射名") * 属性: * value="请求URL的匹配值" method=method=RequestMethod.GET/POST 指定控制器响应的提交方式,默认都支持; * @RequestMapping 可声明在: 方法 和 类 上面示例如下; *@RequestParam * 当方法参数与 URL name相同时自动匹配值; 不同则默认null; * @RequestParam 就是当参数与 URL name不匹进行映射匹配的操作; * 属性: * value="URL的name" required=false/true 默认true:URL中必须存在对应name进行匹配,不然参数异常 浏览器400!!为了解决建议设为 false; * defaultValue:设置默认属性值,如果没有指定,name匹配则使用默认值...eg: @RequestParam(defaultValue = "1")Integer dye 当前页默认第一页; * 扩展: * (防止忘记,URL是以 name-value 且都是字符串类型) localhost:8080/项目名/xx?name=value.. 存储方式(get显示post隐式存储) * 如果 GET/POST 存在相同Name 都会存在name中 ,逗号分隔;(请看index.jsp注释!) */ //示例二 @RequestMapping(value="/Hollo2.html") //可以看到 类/方法上各有一个注解; 使用时 URL: localhost:8080/项目名/WSM/Hollo2.html 指向该控制器; 方便分类操作,不同的控制器类针对不同的增删改查.. public String Hollo2(@RequestParam(value="name",required=false) String na,Model model){ na = "Hello:"+na; //参数拼接 //创建一个 ModelAndView 对象; ModelAndView mav = new ModelAndView(); mav.addObject("msg",na); //这里方法返回的是String 而不是 ModelAndView 所以存储在这里的数据,页面并不会在接收到了... //参数对象 model model.addAttribute("msg",na); //将数据存储在 model中,返回给页面接收; return "forward:../index.jsp"; //因为在类上加:@RequestMapping("/WSM") 会在根目录上默认加上 /WSM 所以需要 ../返回上一级目录; // 可以使用 return "redirect:页面" 或 return "forward:页面" 来完成 重定向/转发... // return 指定转发/重定向 ,跳转页面需要 文件后缀名,它不会在经过,前端控制器; 进行后缀的添加; 而是直接进行了重定向/转发; // 也不一定是非要带上 后缀。 // 重定向就相当于是重新请求了一次:当前目录 + "重定向的页面:xxxx"; URL地址发送变化; // 转发 就相当于在当前目录下请求:当前目录 + "转发 的页面:xxxx"; URL地址不发生变化; // 经过web.xml 的DispatcherServlet 因为 / 所以 .jsp 会不在经过控制器直接去找页面. 如果不加 .jsp 还是会回到 控制中走~一遍 (亲测~) } // Model对象方法; // addAttribute(String,Object); 通过 key-value 方式来存储数值,默认存储request 中; // addAttribute(Object); 没有指定 key 直接存储value 方法会默认根据对象类型来作为 key; eg: String类型 key默认为 string 页面通过 ${string} 取值; } `index.jsp` <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h2>${msg }</h2> <!-- 如果表单提交中 action url中带参数 和 post方式提交的重名name-value 获取时候会同时获取 get,post表单 修改action 中连接(方式一):Hollo1.html?name=wsm 提交查看; --> <form action="Hollo1.html" method="post"> <!-- 使用实例二action 改为:WSM/Hollo2.html --> <input type="text" name="name"> <input type="submit" value="提交"> </form> </body> </html> ## 参数传递(Controller to View) ## **1.ModelAndView** > 方法返回值为一个 ModelAndView 类型对象; > 就像实例一通过对应的方法, 进行传参, 视图名称… 至前端控制器——视图解析器… 最终返回浏览器 **2.Model** > 方法返回值是String 参数 Model 类型 (就像实例二一样) **3.Map** > 方法返回值是String 参数 Map< String,Object > 类型 > 实例中没有就是和 实例二类似, 参数为 Map< String,Object > ; > 方法中通过 Map 对象.put 存储key-value **解释:** > SpringMVC 的控制器的处理方法中 如果有 Map或Model 参数, 就会将请求内的 “隐含模型对象” 传递给这些形参, > 因此可以通过 Map 和 Model 形参对模型中数据进行读写操作, (个人比较喜欢使用Model) > **隐藏模型:** SpringMVC 在调用方法前会 创建出一个隐含的模型对象,作为模型的存储容器; > 如果传入参数为 Model ,SpringMVC 会将隐含模型传递给这些 参数存储; > 开发者可以通过 参数访问到模型中的所有数据,当然也可往模型中新增属性数据。。。。 **感谢观看-\_-** [Link 1]: https://blog.csdn.net/qq_45542380/article/details/108430944 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center]: /images/20221123/cb973167c7fb4c1ca45e0617b5c1bba0.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 1]: /images/20221123/62f13cd8653d4a21b862e02673ff31cb.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 2]: /images/20221123/f6b4a14fe81147f797f557568cd8a9b9.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 3]: /images/20221123/11355826231b4a68a4dc6bedbecf5097.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 4]: /images/20221123/e01466313ec649cc88f9bea1272c7ecf.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 5]: /images/20221123/904cfb9ce68d48748dec2e64ed445eff.png [Link 2]: https://download.csdn.net/download/qq_45542380/12839058 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1NTQyMzgw_size_16_color_FFFFFF_t_70_pic_center 6]: /images/20221123/9317ea4d52174d05ad036034ae6153a8.png [20200910093243912.png_pic_center]: /images/20221123/8b26a51857534dbc9b5cadbba17310ab.png
还没有评论,来说两句吧...