SpringMVC
SpringMVC
ssm mybatis+Spring+Spring+MVC MVC三层架构
spring : IOC 和 AOP
Spring: spring执行流程!
1、什么是SpringMVC
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
查看官方文档:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web
MVC是模型(Model)、视图(View)、控制器(Controller)的简写 是一种软件设计规范。
MVC: 模型(dao,service) 视图(jsp) 控制器(servlet)
- 是将业务逻辑、数据、显示分离的方法来组织代码。
- MVC主要作用是降低了视图与业务逻辑间的双向偶合。
- MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。
1.1、历史
Model1
Model1优点:架构简单,比较适合小型项目开发;
Model1缺点:JSP职责不单一,职责过重,不便于维护;
Model2
职责分析:
Controller:控制器
- 取得表单数据
- 调用业务逻辑
- 转向指定的页面
Model:模型
- 业务逻辑
- 保存数据的状态
View:视图
- 显示页面
Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model 1模式的实现比较简单,适用于快速开发小规模项目,Model1中JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。Model2消除了Model1的缺点。
1.2、回顾javaweb 实现servlet
1.导入依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
2.建立一个Moudle:springmvc-01-servlet , 添加Web app的支持!
3.实现servlet,用来处理用户的请求
package com.lmq.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/6/25 13:44
*/
// 只要实现了servlet的接口的程序就叫servlet
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取前端参数
String merhod = req.getParameter("merhod");
if (merhod.equals("add")){
req.getSession().setAttribute("msg","执行了add方法");
}
if (merhod.equals("delet")){
req.getSession().setAttribute("msg","执行了delete方法");
}
// 调用业务层
//视图转发或者重定向
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
-
编写Hello.jsp,在WEB-INF目录下新建一个jsp的文件夹,新建hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>title</title> </head> <body> ${msg} </body> </html>
-
web.xml 中注册 servlet
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.lmq.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/user</url-pattern> </servlet-mapping> </web-app>
-
启动tomcat 测试
1.3、SpringMVC的流程
-
DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
http://localhost:8080服务器域名
SpringMVC部署在服务器上的web站点
hello表示控制器
通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
-
HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
-
HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
-
HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
-
HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
-
Handler让具体的Controller执行。
-
Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
-
HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
-
DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
-
视图解析器将解析的逻辑视图名传给DispatcherServlet。
-
DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
-
最终视图呈现给用户。
1.4、 为什么要学习
Spring MVC的特点:
- 轻量级,简单易学
- 高效 , 基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约定优于配置
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简洁灵活
Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
正因为SpringMVC好 , 简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于配置 . 能够进行简单的junit测试 . 支持Restful风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等......所以我们要学习 .
2、HelloMVC实现 原生实现
- 创建项目,添加web支持
- 导入依赖
- 配置web.xml 注册DispatcherServt
实现
目标 显示WEB-INF/jsp/test.jsp
-
新建一个Moudle , springmvc-02-hello , 添加web的支持!
-
配置DispatvhServlet: 这个是springMVC的核心 请求分发器, 前端控制器
- web.xml
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别-1--> <load-on-startup>1</load-on-startup> </servlet>
-
编写SpringMVC 的 配置文件 springmvc-servlet.xml
-
添加 处理映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
-
添加 处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
-
添加 视图解析器
<!--视图解析器:DispatcherServlet给他的ModelAndView--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--处理器映射--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!--处理器适配器--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> <bean id="/hello" class="com.lmq.controller.HelloController"/> </beans>
-
-
编写Controller 编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;
package com.lmq.controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author 羡鱼 * @version 1.0 * @date 2023/6/25 18:03 */ public class HelloController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { // modelAndView 模型和视图 ModelAndView mv = new ModelAndView(); // 封装对象,放在ModelAndView中。model mv.addObject("msg","HelloSpringMVC!"); // 封装要跳转的视图,放在modelAndView mv.setViewName("/hello"); // WEB-INF/jsp/hello.jsp return mv; } }
-
将自己的类交给SpringIOC容器,注册bean
<!--Handler 注意前面的 / --> <bean id="/hello" class="com.lmq.controller.HelloController"/>
-
写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面;
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>title</title> </head> <body> ${msg} </body> </html>
-
配置Tomcat 启动测试!
主要理解 怎么来的
3、注解实现
-
新建一个Moudle,springmvc-03-hello-annotation 。添加web支持!
-
由于Maven可能存在资源过滤的问题,我们将配置完善 引入相关的依赖
<?xml version="1.0" encoding="UTF-8"?> <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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lmq</groupId> <artifactId>springMVC</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>springMVC-01-servlet</module> <module>springMVC-02-hellomvc</module> <module>springMVC-03-annotation</module> </modules> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.2</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.9.RELEASE</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build> </project>
-
配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--1.注册DispatcherServlet--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别-1 越小级别越高--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
注意:/ 和 /* 的区别:< url-pattern > / </ url-pattern > 不会匹配到.jsp, 只针对我们编写的请求;即:.jsp 不会进入spring的 DispatcherServlet类 。< url-pattern > /* </ url-pattern > 会匹配 *.jsp,会出现返回 jsp视图 时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。
- 注意web.xml版本问题,要最新版!
- 注册DispatcherServlet
- 关联SpringMVC的配置文件
- 启动级别为1
- 映射路径为 / 【不要用/*,会404】
-
添加Spring MVC配置文件
<?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 --> <context:component-scan base-package="com.lmq.controller"/> <!-- 让springMVC 不处理静态资源 --> <mvc:default-servlet-handler/> <!--注解生效--> <!-- 支持mvc注解驱动 在spring中一般采用@RequestMapping注解来完成映射关系 要想向下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationMethodlerAdapter实例 这两个实例粉白在类级别和方法级别处理。 而annotation-driven配置帮助我们自动完成上面两个实例的注入。 --> <mvc:annotation-driven/> <!-- 视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀 目录的下一级--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> </beans>
注意:在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。
-
- 让IOC的注解生效
- 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 .....
- MVC的注解驱动
- 配置视图解析器
-
-
创建Controller 编写一个Java控制类:com.lmq.controller.HelloController , 注意编码规范
package com.lmq.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; /** * @author 羡鱼 * @version 1.0 * @date 2023/6/26 1:11 */ @Controller // @RequestMapping("/HelloController") public class HelloController { @RequestMapping("/hello") public String hello(Model model){ // 封装数据 向模型中添加属性msg与值,可以在JSP页面中取出并渲染 model.addAttribute("msg","hello,model"); //web-inf/jsp/hello.jsp return "hello"; // 会被视图解析器处理 } }
- @Controller是为了让Spring IOC容器初始化时自动扫描到;
- @RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
- 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
- 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
-
创建视图层 在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息;可以通过EL表示取出Model中存放的值,或者对象;
<%-- Created by IntelliJ IDEA. User: lmqqq Date: 2023/6/26 Time: 1:10 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html>
-
配置Tomcat运行
4、Controller详解 【控制器 原来的servlet】
4.1、Controller
- 控制器提供访问程序的行为,通常通过接口定义或者注解定义两种方式实现
- 负责解析用户的请求并将其转换为一个模型。
- 在springMVC 中控制器类可以包含很多个方法
- 在SpringMVC 中,对于一个controller的配置方式有很多种
4.1.1、接口实现
package com.lmq.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/6/26 12:09
*/
public class ControllerIntresoures implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","hello ControllerIntresoures");
mv.setViewName("hello");
return mv;
// 写完后注册到bean中
}
}
<bean class="com.lmq.controller.ControllerIntresoures" id="/hello"/>
注意: ID 的前面的 / 不能掉
4.1.2、 注解实现
使用注解要扫描包
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.lmq.controller"/>
package com.lmq.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/6/26 11:30
*/
@Controller //代表这个列会被spring接管,被这个注解的类的所有方法,返回值是String 且具有可以跳转的页面的就会被视图解析器解析
@RequestMapping("/123")
public class ControllerTest01 {
@RequestMapping("/hello")
public String test01(Model model){
model.addAttribute("msg","123123");
return "hello";
}
}
4.2、RequestMapping
可以放在类 和 方法上 先类后方法
4.2.1、 用 @RequestMapping 处理 HTTP 的各种方法
请求 组合注解 共享注解
GET @GetMapping @RequestMapping(method = RequestMethod.GET)
POST @PostMapping @RequestMapping(method = RequestMethod.POST)
PUT @PutMapping @RequestMapping(method = RequestMethod.PUT)
DELETE @DeleteMapping @RequestMapping(method = RequestMethod.DELETE)
PATCH @PatchMapping @RequestMapping(method = RequestMethod.PATCH)
4.2.2、@RequestMapping 来处理多个 URI
@Controller
@RequestMapping("/home")
public class IndexController {
@RequestMapping(value = {
"",
"/page",
"page*",
"view/*,**/msg"
})
String indexMultipleMapping() {
return "Hello";
}
}
4.2.3、带有 @RequestParam 的 @RequestMapping
4.3、风格Restful
简介 高效 安全
最大好处 安全
传统 get post
restful 不同请求方法 返回不同效果
@GetMapping
@PostMapping
@DeleteMapping
@PutMapping
@PatchMapping
package com.lmq.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/6/26 12:38
*/
@Controller
public class ControllerRestFul {
@RequestMapping("/restful/{a}/{b}")
public String lmq(@PathVariable int a,@PathVariable int b , Model model){
int res = a + b;
model.addAttribute("msg","结果"+res);
return "hello";
}
}
出现同样的路径 方法 程序会报错 不知道选择那一个执行
name
path
value
推荐使用value 和 path name部分情况无法使用
扩展:小黄鸭调试法
场景一:我们都有过向别人(甚至可能向完全不会编程的人)提问及解释编程问题的经历,但是很多时候就在我们解释的过程中自己却想到了问题的解决方案,然后对方却一脸茫然。
场景二:你的同行跑来问你一个问题,但是当他自己把问题说完,或说到一半的时候就想出答案走了,留下一脸茫然的你。
其实上面两种场景现象就是所谓的小黄鸭调试法(Rubber Duck Debuging),又称橡皮鸭调试法,它是我们软件工程中最常使用调试方法之一。
4.4、结果返回 重定向 转发
Servlet(req,resp) 请求 响应
简单理解 有视图解析器 【没有视图解析器路径就要写完整】
默认就是转发 地址栏不变化
地址栏变化就是重定向 return 加上 redirect:
1、通过HttpServletResponse进行输出
2、通过HttpServletResponse实现重定向
3、通过HttpServletResponse实现转发
@Controller
public class ResultSpringMVC {
@RequestMapping("/rsm/t1")
public String test1(){
//转发
return "/index";
}
@RequestMapping("/rsm/t2")
public String test2(){
//转发二
return "forward:/index";
}
@RequestMapping("/rsm/t3")
public String test3(){
//重定向
return "redirect:/index.jsp";
}
}
重定向
return "redirect:/hello";
return "redirect:hello";
带斜杠 与 不带斜杠 完全不一样
前面有两层 如 /inde/1
不带/
就会重定向到 /index/hello
带/
就会重定向到/hello
4.5、 乱码问题
自己写 或者 用别人的
package com.lmq.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/6/26 14:04
* 自己写的过滤器
*/
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
web.xml
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.lmq.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
他人的 java类
package com.lmq.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解决get和post请求 全部乱码的过滤器
*/
public class DFilterEncoding implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//处理response的字符编码
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
// 转型为与协议相关对象
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 对request包装增强
HttpServletRequest myrequest = new MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
//是否编码的标记
private boolean hasEncode;
//定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
public MyRequest(HttpServletRequest request) {
super(request);// super必须写
this.request = request;
}
// 对需要增强方法 进行覆盖
@Override
public Map getParameterMap() {
// 先获得请求方式
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
// post请求
try {
// 处理post乱码
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
// get请求
Map<String, String[]> parameterMap = request.getParameterMap();
if (!hasEncode) { // 确保get手动编码逻辑只运行一次
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
// 处理get乱码
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
//取一个值
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回参数的第一个值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
Spring MVC 的过滤器
web.xml
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.6、 数据Json
用json向前端传送数据
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
controller
package com.lmq.controller;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lmq.pojo.User;
import com.lmq.utils.JsonUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/6/26 15:01
*/
//@Controller
@RestController //直接诶全部不走视图解析器
public class UserController {
// @ResponseBody // 不走视图解析器 配合Controller 使用
@RequestMapping("/j1")
public String json1() {
User user = new User(1, "小王", "pwd");
return user.toString();
}
@RequestMapping("/j2")
public String json02() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<User> users = new ArrayList<User>();
for (int i = 0; i < 4; i++) {
users.add(new User(i, "小王妃" + i, "ppp" + i));
}
String s = mapper.writeValueAsString(users);
return s;
}
@RequestMapping("/j3")
public String json03() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
// java的解决方法
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return mapper.writeValueAsString(sdf.format(date));
}
@RequestMapping("/j4")
public String json04() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
// java的解决方法
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mapper.setDateFormat(sdf);
Date date = new Date();
return mapper.writeValueAsString(date);
}
@RequestMapping("/j5")
public String json05() {
ObjectMapper mapper = new ObjectMapper();
// java的解决方法
Date date = new Date();
return JsonUtils.getJson(date);
}
@RequestMapping("/j6")
public String json06() {
ArrayList<User> users = new ArrayList<>();
// java的解决方法
for (int i = 0; i < 4; i++) {
users.add(new User(i, "小王妃" + i, "ppp" + i));
}
String data = JSON.toJSONString(users);
System.out.println(data);
return data;
}
}
重点 两种不同的方法 对应两个不同的maven导入的包
@RequestMapping("/j2")
public String json02() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<User> users = new ArrayList<User>();
for (int i = 0; i < 4; i++) {
users.add(new User(i, "小王妃" + i, "ppp" + i));
}
String s = mapper.writeValueAsString(users);
return s;
}
@RequestMapping("/j6")
public String json06() {
ArrayList<User> users = new ArrayList<>();
// java的解决方法
for (int i = 0; i < 4; i++) {
users.add(new User(i, "小王妃" + i, "ppp" + i));
}
String data = JSON.toJSONString(users);
System.out.println(data);
return data;
}
5、拦截器
如何实现拦截器?
AOP 的具体实现 就是拦截器 过滤器
使用AOP去织入拦截
自定义拦截器
只要实现了HandlerInterceptor
接口 就是一个拦截器
package com.lmq.myljq;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author 羡鱼
* @version 1.0
* @date 2023/6/27 20:34
*/
public class MyHandler implements HandlerInterceptor {
@Override
// return true 放行 执行下一个拦截器
// return false 不放行 不让执行下一个拦截器
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// return HandlerInterceptor.super.preHandle(request, response, handler);
System.out.println("=========================前面==========================");
return false;
}
// 后面用来做拦截日志的
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
System.out.println("==========================执行后=========================");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
System.out.println("===========================清理========================");
}
}
属于spring执行,
<!-- 交给Sproing 执行 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 这个请求下的全部请求 -->
<mvc:mapping path="/**"/>
<bean class="com.lmq.myljq.MyHandler"/>
</mvc:interceptor>
</mvc:interceptors>
5、小项目实战 整合ssm框架初步体
- 环境:
- IDEA
- MySQL 5.7.*
- Tomcat 9.*
- Maven 3.6.3
整合mybatis spring springMVC
1、创建项目
2、导入依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12-beta-3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
</dependencies>
3、资源过滤问题解决
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
4、构建基本结构和培训框架
-
com.lmq.pojo
-
com.lmq.dao
-
com.lmq.service
-
com.lmq.controller
-
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> </configuration>
-
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
出现问题 加入spring事务出现问题 解决方案
[aop报错] Cannot resolve reference to bean 'txPointCut' while setting bean property 'pointcut'
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0': Cannot resolve reference to bean 'txPointCut' while setting bean property 'pointcut'
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txPointCut': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.AspectJExpressionPointcut]: No default constructor found
少了三个包(
aspectjrt,
aspectjweaver,
com.springsource.org.aopalliance
),导入依赖即可
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aopalliance/com.springsource.org.aopalliance -->
<dependency>
<groupId>org.aopalliance</groupId>
<artifactId>com.springsource.org.aopalliance</artifactId>
<version>1.0.0</version>
</dependency>