SpringMVC

ssm: mybatis+spring+springmvc MVC三层框架

spring:IOC 和 AOP

SpringMVC:SpringMVC执行过程

MVC:模型(dao service) 视图(jsp) 控制器(servlet)

servlet:转发,重定向

1.回顾servlet

springmvc-01-servlet

  • 导入依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!--依赖 -->
<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>
  • 建立一个子工程—–导入依赖
1
2
3
4
5
6
7
8
9
10
<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>
  • 配置web.xml
1
2
3
4
5
6
7
8
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.sise.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
  • 实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取前端参数
String method = req.getParameter("method");
if (method.equals("add")){
req.getSession().setAttribute("msg","执行了add方法");
}
if (method.equals("delete")){
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);
}
}
  • jsp
1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
  • 部署tomcat

mvc框架要做哪些事情

  1. 将url映射到Java类或Java类的方法
  2. 封装用户提交的数据
  3. 处理请求—调用相关的业务处理—-封装响应的数据
  4. 将响应的数据进行渲染,jsp/html等表示层数据

2.初识SpringMVC

springmvc-02-hellomvc

  • 概述:

SpringMVC是spring framework 的一部分,是基于Java实现MVC的轻量级Web框架

  • 官方文档

https://docs.spring.io/spring-framework/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web

  • 特点
    1. 轻量级,简单易学
    2. 高效,基于请求响应的MVC框架
    3. 与spring兼容好,无缝结合
    4. 约定优于配置
    5. 功能强大:restful、数据验证、格式化、本地化、主题等
  • springMVC的原理

当发送请求时被前置的控制器拦截到请求,根据请求参数生成额代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者

2.1配置第一个springMVC程序

1、新建一个maven项目,添加web支持

2、导入springmvc依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>

3、配置web.xml 注册DispatcherServle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--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>

<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

4、编写springMVC配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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"/>

<!--视图解析器:DispatcherServlet给他的ModelAndView
1、获取ModelAndView的数据
2、解析ModelAndView的视图名字
3、拼接视图名字,找到对应的视图/WEB-INF/jsp/hello.jsp
4、将数据渲染到这个视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>

<!--Handler-->
<bean id="/hello" class="com.sise.controller.HelloController"/>

</beans>

5、编写操作业务Controller 实现Controller接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//注意:这里我们先导入Controller接口
public class HelloController implements Controller {

public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();

//封装对象,放在ModelAndView中。Model
mv.addObject("msg","HelloSpringMVC!");
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
return mv;
}

}

6、再springMVC配置文件添加bean

7、编写jsp跳转页面

1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>

8、配置tomcat并启动

注意:404报错决解方案

  1. 查看控制台输出,看一下是不是缺少了什么jar包。
  2. 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!
  3. 重启Tomcat 即可解决!

2.2springMVC执行原理

image-20210718164549025

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

    我们假设请求的url为 : http://localhost:8080/SpringMVC/hello

    如上url拆分成三部分:

    http://localhost:8080服务器域名

    SpringMVC部署在服务器上的web站点

    hello表示控制器

    通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

  2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。

  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。

  6. Handler让具体的Controller执行。

  7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。

  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。

  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。

  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

  12. 最终视图呈现给用户。

3.使用注解开发springMVC

springmvc-03-annotation

1、由于maven存在资源过滤问题,需要导入相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<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>

2、配置web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--1.注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>

<!--所有请求都会被springmvc拦截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

3、配置springMVC核心文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.sise.controller"/>
<!-- 让Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler />
<!--
支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效
必须向上下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter实例
这两个实例分别在类级别和方法级别处理。
而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>

4、创建controller类(注意编码规范 com.sise.controller)

1
2
3
4
5
6
7
8
9
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
//封装数据
model.addAttribute("msg","Hello,SpringMVC");
return "hello";//会被视图解析器处理
}
}
  • @Controller 是为了让spring IOC容器初始话时自动扫描到
  • @RequestMapping(“/hello”) 是为了映射请求路径,因为这里只有方法才有映射到所以访问路径为/hello
  • 方法中声明model类型的参数是为了把action中数据带到视图中
  • 方法返回中的结果是视图名称hello,加上配置文件中前后缀变成了WEB-INF/jsp/hello.jsp

5、创建视图层

1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
  • 在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息;
  • 可以通过EL表示取出Model中存放的值,或者对象;

6、启动tomcat服务器并测试结果

小结:实现的步骤

  1. 新建一个web项目
  2. 导入相关jar包
  3. 编写web.xml 注册dispatcherServlet
  4. 编写springMVC配置文件
  5. 创建对应的控制类
  6. 完善前端视图和controller之间的对应
  7. 测试运行

使用springMVC必须配置的三大件

处理器映射器、处理器适配器、视图解析器

通常,我们只需要手动配置视图解析器即可,处理器映射器处理器适配器只需要开启注解就行了

4.控制器和RequestMapper

springmvc-04-controller

4.1实现controller接口

1、配置web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--配置dispatchServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

2、编写一个controller类

1
2
3
4
5
6
7
8
9
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个视图模型对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","helloController");
mv.setViewName("test");
return mv;
}
}

3、配置springMVC核心文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<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="/s" class="com.sise.controller.ControllerTest1"/>

</beans>

4、编写前端test.jsp

1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
  • 注意:要在WEB-INF/jsp目录下编写,对应我们的视图解析器

5、启动tomcat服务器,测试

说明:

  • 实现接口controller定义控制器是较老的方法
  • 缺点:一个控制器中只有一个方法,如果要多个方法则需要定义多个controller,比较麻烦

4.2使用注解@controller

  • 配置springMVC配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描指定包,下面所有注解类交给IOC容器管理-->
<context:component-scan base-package="com.sise.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>

</beans>
  • 编写一个controller类
1
2
3
4
5
6
7
8
9
10
11
12
//@Controller注解的类会自动添加到spring上下文中
@Controller
public class ControllerTest2{
//映射访问路径
@RequestMapping("/s2")
public String test(Model model){
//springMVC会自动实例化一个model对象向视图中传值
model.addAttribute("msg","hi");
//返回视图位置
return "test";
}
}
  • 启动tomcat服务器并测试

说明

  • 使用注解方式可以使得视图被重复利用,两个请求可以指定一个视图,而且结果不一样
  • 注解方式简单方便

4.3RequestMapper说明

  • @RequestMapper注解用于映射url到控制器类或者一个特定的方法上

注解在方法上

1
2
3
4
5
6
7
8
@Controller
public class ControllerTest3 {
@RequestMapping("/s2")
public String test(Model model){
model.addAttribute("msg","test3");
return "test";
}
}

访问路径:http://localhost:8080/工程名/s2

注解在类和方法上

1
2
3
4
5
6
7
8
9
@Controller
@RequestMapping("/t")
public class ControllerTest3 {
@RequestMapping("/s2")
public String test(Model model){
model.addAttribute("msg","test3");
return "test";
}
}

访问路径:http://localhost:8080/工程名/t/s2

5.RestFul 风格

概念

  • restful是一个资源定位及资源操作的风格,可以是使设计的软件更加简洁

功能

  1. 使用post、get、delete、put方法进行操作
  2. 使传统的传参更加简洁

测试传参

  • 使用的注解@PathVariable
1
2
3
4
5
6
7
8
9
10
11
@Controller
public class RestFul {
//原始:http://localhost:8080/d?a=1&b=2
//现在:http://localhost:8080/d/1/2
@RequestMapping("/d/{a}/{b}")
public String test(@PathVariable int a,@PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg","结果为:"+res);
return "test";
}
}

测试方法

  • 使用注解 @RequestMapping(method = {RequestMethod.POST})
1
2
3
4
5
6
7
8
9
10
11
@Controller
public class RestFul {
//原始:http://localhost:8080/d?a=1&b=2
//现在:http://localhost:8080/d/1/2
@RequestMapping(value = "/d/{a}/{b}",method = {RequestMethod.POST})
public String test(@PathVariable int a,@PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg","结果为:"+res);
return "test";
}
}
  • 因为默认的访问地址栏使get请求,所以会报405错误

5.数据的转发和跳转

5.1通过servletAPI,不需要视图解析器

  1. 通过HttpServletResponse进行输出
  2. 通过HttpServletResponse实现重定向
  3. 通过HttpServletResponse实现转发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Controller
public class ForwardTest1 {
@RequestMapping("/forward/f1")
public void test1(HttpServletRequest request, HttpServletResponse response) throws IOException {

response.getWriter().println("hello,forward");
}
@RequestMapping("/forward/f2")
public void test2(HttpServletRequest request,HttpServletResponse response) throws IOException {
response.sendRedirect("/index.jsp");
}
@RequestMapping("/forward/f3")
public void test3(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg","hahaha");
request.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(request,response);

}
}

5.2通过springMVC,不需要视图解析器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Controller
public class ForwardTest2 {
@RequestMapping("/forward2/t1")
public String test1(Model model){
model.addAttribute("msg","hello!");
//转发一
return "/WEB-INF/jsp/test.jsp";
}

@RequestMapping("/forward2/t2")
public String test2(Model model){
model.addAttribute("msg","hi!");
//转发二
return "forward:/WEB-INF/jsp/test.jsp";
}

@RequestMapping("/forward2/t3")
public String test3(){
//重定向
return "redirect:/index.jsp";
}

}

5.3通过springMVC,需要视图解析器

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class ForwardTest3 {
@RequestMapping("/forward3/f1")
public String test1(Model model){
model.addAttribute("msg","转发");
return "test";
}
@RequestMapping("/forward3/f2")
public String test2(){

return "redirect:/index.jsp";
}
}

5.4数据处理

1、提交的域名称和处理方法的参数名一致

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
@RequestMapping("/data")
public class DataSubmission {
@GetMapping("/d1")
public String test1(@RequestParam("username") String name, Model model){
//接收前端数据
System.out.println("接收前端的参数为:"+name);
//将返回的结果传递给前端,model
model.addAttribute("msg",name);
//视图跳转
return "test";
}
}

2、提交的是一个对象

  • 实体类
1
2
3
4
5
public class User {
private int id;
private String name;
private int age;
}
  • 方法
1
2
3
4
5
6
7
@GetMapping("/d2")
public String test2(User user, Model model){
System.out.println(user);
model.addAttribute("msg",user);

return "test";
}

5.5解决乱码问题

  • 在web目录下编写一个jsp
1
2
3
4
5
6
7
8
9
10
11
12
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/e" method="post">
<input type="text" name="name">
<input type="submit">
</form>
</body>
</html>
  • 编写encoding类
1
2
3
4
5
6
7
8
@Controller
public class Encoding {
@RequestMapping("/e")
public String test(Model model,String name){
model.addAttribute("msg",name);
return "test";
}
}
  • 测试结果:å¼ ä¸‰

解决方案

springMVC提供了解决乱码的配置文件,只需要在web.xml添加上即可

1
2
3
4
5
6
7
8
9
10
11
12
<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>

如果还不行的话,就需要在tomcat服务器上配置了

1
2
3
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

终极解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
* 解决get和post请求 全部乱码的过滤器
*/
public class GenericEncodingFilter 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;
}
}

然后再web.xml上配置过滤器

6.JSON数据交互处理

6.1什么是json

  1. 一种轻量级的数据交换格式
  2. 简洁和清晰的层次结构的数据交换语言
  3. 易于人阅读和编写,同时也易于机器解析和生成并有效地提升网络传输效率

6.2Jackson

Jackson是目前比较好的json解析工具

  • 使用Jackson,需要导入jar包
1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
  • 配置web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!--1.注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>

<!--所有请求都会被springmvc拦截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<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>
  • 配置springMVC核心文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
<context:component-scan base-package="com.sise.controller"/>

<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>

</beans>
  • 编写实体类
1
2
3
4
5
6
7
8
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private int age;
private String sex;
}
  • 测试类controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Controller
public class UserController {
@RequestMapping("/m1")
@ResponseBody
//@ResponseBody不会再走视图解析器,会返回一个json格式字符串

public String json1() throws JsonProcessingException {
//创建一个Jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
User user = new User("张三",18,"男");
//将对象解析成json格式
String s = mapper.writeValueAsString(user);

return s;
}
}
  • @ResponseBody @RestController//返回json字符串统一解决
  • 解析出来的json会出现乱码:{“name”:”??”,”age”:18,”sex”:”?”}

6.3json乱码解决方案

1、通过@RequestMapping的produces属性

1
2
//produces:指定响应体返回类型和编码
@RequestMapping(value = "/m",produces = "application/json;charset=utf-8")

2、统一解决 再springMVC中添加配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

6.4Jackson扩展

  • 测试集合输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RequestMapping("/m2")
@ResponseBody
public String json2() throws JsonProcessingException {
//创建一个Jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
List<User> userList = new ArrayList<User>();
User user1 = new User("张三",18,"男");
User user2 = new User("李四",18,"男");
User user3 = new User("王五",18,"男");
User user4 = new User("大刘",18,"男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
//将对象解析成json格式
String s = mapper.writeValueAsString(userList);

return s;
}
  • 输出时间
1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("/m3")
@ResponseBody
public String json3() throws JsonProcessingException {
//创建一个Jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();

Date date = new Date();

//将对象解析成json格式
String s = mapper.writeValueAsString(date);

return s;
}
  • 默认日期的格式是一个数字 1626682120262

解决方案

1、自定义时间格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping("/m3")
@ResponseBody
public String json3() throws JsonProcessingException {
//创建一个Jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();

Date date = new Date();
//自定义时间的格式
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

//将对象解析成json格式
String s = mapper.writeValueAsString(sd.format(date));

return s;
}
  • 输出结果:”2021-07-19 16:10:48”

2、json提供的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RequestMapping("/m3")
@ResponseBody
public String json3() throws JsonProcessingException {
//创建一个Jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();

Date date = new Date();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定义时间的格式
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mapper.setDateFormat(sd);

//将对象解析成json格式
String s = mapper.writeValueAsString(date);

return s;
}

6.5集成工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class JsonUtil {

public static String getJson(Object object){
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}

public static String getJson(Object object,String dateFormat) {
ObjectMapper mapper = new ObjectMapper();
SimpleDateFormat sd = new SimpleDateFormat(dateFormat);
mapper.setDateFormat(sd);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
  • 测试代码变得简便
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    public String json2() throws JsonProcessingException {
//创建一个Jackson的对象映射器,用来解析数据
// ObjectMapper mapper = new ObjectMapper();
List<User> userList = new ArrayList<User>();
User user1 = new User("张三",18,"男");
User user2 = new User("李四",18,"男");
User user3 = new User("王五",18,"男");
User user4 = new User("大刘",18,"男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
//将对象解析成json格式
// String s = mapper.writeValueAsString(userList);
return JsonUtil.getJson(userList);
}

@RequestMapping("/m3")
@ResponseBody
public String json3() throws JsonProcessingException {
Date date = new Date();
return JsonUtil.getJson(date,"yyyy-MM-dd HH:mm:ss");
}
}

6.6使用fastJson

  • 导jar包
1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping("/m4")
@ResponseBody
public String json4() {

List<User> userList = new ArrayList<User>();
User user1 = new User("张三",18,"男");
User user2 = new User("李四",18,"男");
User user3 = new User("王五",18,"男");
User user4 = new User("大刘",18,"男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
String s = JSON.toJSONString(userList);
return s ;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!