SpringMVC学习笔记

目录

SpringMVC简介

​ 创建项目流程

 总结(SpringMVC执行流程)

 注解

@RequestMapping功能

@RequestMapping中的属性

 1.value属性

2.method属性

SpringMVC支持ant风格路径

SpringMVC支持路径中的占位符

SpringMVC获取请求参数

1.通过ServletAPI获取(一般不用)

 2.通过控制器方法的形参获取请求参数

3.@RequestParam注解 

4.@RequestHeader

5.@CookieValue 

6.通过POJO获取请求参数

解决获取请求参数中的乱码问题: 

域对象共享数据 

1.使用ServletAPI向request域对象共享数据(一般不用)

2.使用ModelAndView向request域对象共享数据(*)

 3.使用Model向request域对象共享数据

4.使用map向request域对象共享数据

5.使用ModelMap向request域对象共享数据

6.向session域共享数据

7.向application域共享数据

8.域对象的选择 

SpringMVC中的视图

 1.Thymeleaf

 2.转发视图

3.重定向视图

4.视图控制器view-controller

RESTFul:

简介

 RESTFul的实现

关于thymeleaf中的参数解析

HttpMessageConverter(报文信息转换器)

1.@RequestBody

2.RequestEntity

3.@ResponseBody

4.SpringMVC处理Json

5.SpringMVC处理Ajax

6.@RestController

7.ResponseEntity

 文件上传

拦截器

1.拦截器的配置

 2.拦截器的三个抽象方法

​ 3.多个拦截器的执行顺序 

 异常处理

1.基于配置的异常处理

​ 2.基于注解的异常处理

 注解配置SpringMVC

1.创建初始类,代替web.xml

2、创建SpringConfig配置类,代替spring的配置文件

3、创建WebConfig配置类,代替SpringMVC的配置文件

SpringMVC执行流程

1.SpringMVC常用组件

 2.DisPatcherServlet初始化过程

3.SpringMVC执行流程


SpringMVC简介

 创建项目流程

1.创建maven工程,引入相关依赖

<dependencies>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.1</version>
        </dependency>

        <!-- 日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

        <!-- ServletAPI -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- Spring5和Thymeleaf整合包 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
    </dependencies>

 2.添加web模块和环境依赖,生成web.xml文件

Project Stucture->Moudules->+web->修改路径

3.配置web.xml

 /:jsp的本质就是servlst,需要经过当前服务器指定的servlst处理后,而不需要DispatcherServlet处理

<!--将前端控制器DispatcherServlet的初始化时间提前到服务器启动时-->
        <load-on-startup>1</load-on-startup>

扩展配置方式在其中配置了springMVC核心控制器(即springMVC.xml配置文件)的路径和名称 

4.创建请求控制器

controller层 

5.在springMVC核心控制器即springMVC.xml配置文件)中配置“扫描组件”和“Thymeleaf视图解析器”

<!--扫描组件-->
    <context:component-scan base-package="com.zc.mvc.controller"></context:component-scan>
    <!-- 配置Thymeleaf视图解析器 -->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <!--配置优先级-->
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

6.创建一个html页面

WEB-INF目录下的文件不能通过浏览器或重定向直接访问,只能通过转发来访问

7.在cotroller中写方法跳转到html页面

@Controller
public class HelloController {
     //当只有一个属性赋值时,可以省略(此处value)
    @RequestMapping(value = "/")
    public String index(){
        //返回视图名称
        return "index";
    }
}

当浏览器发送的请求为“/”时(也就是上下文路径时),就会执行注解标识的方法,视图解析器就会解析视图(加上前缀加上后缀),最后跳转html页面。

 //此处请求路径要与html中thymeleaf表达式中的路径相同
    @RequestMapping("/baidu")
    public String baidu(){
        return "baidu";
    }
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
hello world!
<a th:href="@{/baidu}">百度</a>
</body>
</html>

 总结(SpringMVC执行流程)

 注解

@RequestMapping功能

@Controller
@RequestMapping("/test")
public class RequestMappingController {
//此时请求映射所映射的请求的请求路径为:/test/testRequestMapping
@RequestMapping("/testRequestMapping")
public String testRequestMapping(){
return "success";
}
}

PS:便于模块化的管理不同模块中有相同路径(映射)的情况。例:order/list      user/list

刨析:

<a th:href="@{/hello/userController}">用户</a>
@Controller
@RequestMapping("/hello")
public class UserController {
    @RequestMapping("/userController")
    public String user(){
        return "user";
    }
}

 此处html中和带@RequestMapping中的路径都是映射路径(可以随意取名,但要保持一致),而return返回的才是实际路径(经过Thymeleaf视图解析器解析会加上前后缀),同时浏览器中的路径显示也是映射的路径。

@RequestMapping中的属性

 1.value属性

 当有多个value属性值时,表示当前的@RequestMapping中的请求映射能够匹配多个html中的请求地址

<a th:href="@{/testRequestMapping}">测试@RequestMapping的value属性--
>/testRequestMapping</a><br>
<a th:href="@{/test}">测试@RequestMapping的value属性-->/test</a><br>
@RequestMapping(
value = {"/testRequestMapping", "/test"}
)
public String testRequestMapping(){
return "success";
}

2.method属性

当@RequestMapping不设置请求方式时,表示任何请求方式都能匹配;当设置时,表示只能匹配设置的请求方式。 

 get请求:请求参数会拼接到请求地址后面(以?进行拼接:请求参数名=请求参数值)

                 例:localhost:8080/SpringMVC/hello/userController?uname=1&password=xxx

post请求:请求参数会放在请求体中(故安全),传输速度慢,传输数据量大

1、对于处理指定请求方式的控制器方法,SpringMVC中提供了@RequestMapping的派生注解

处理get请求的映射-->@GetMapping

处理post请求的映射-->@PostMapping

处理put请求的映射-->@PutMapping

处理delete请求的映射-->@DeleteMapping

2、常用的请求方式有get,post,put,delete

但是目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符 串(put或delete),则按照默认的请求方式get处理 若要发送put和delete请求,则需要通过spring提供的过滤器HiddenHttpMethodFilter,在 RESTful部分会讲到

SpringMVC支持ant风格路径

在@RequestMapping的属性中,可填入以下符号,类似于模糊查询

@RequestMapping("/a?a/student")
    public String student(){
        return "user";
    }
<a th:href="@{/hello/aaa/student}">学生</a>

SpringMVC支持路径中的占位符

<a th:href="@{/hello/student/1}">测试SpringMVC路径中中的占位符</a>
//测试SpringMVC路径中中的占位符
    @RequestMapping("/student/{id}")
    public String testStu(@PathVariable("id") String id){
        return user();
    }

SpringMVC获取请求参数

1.通过ServletAPI获取(一般不用)

将HttpServletRequest作为控制器方法的形参,此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象。

<a th:href="@{/testParams(username='make',password=123)}">测试SpringMVC的API获取请求参数</a>
@Controller
public class ParamController {
    @RequestMapping("/testParams")
    public String test1(HttpServletRequest request){
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("uname="+username+"pass="+password);
        return "user";
    }
}

 2.通过控制器方法的形参获取请求参数

在控制器方法的形参位置,设置和请求参数同名的形参,当浏览器发送请求,匹配到请求映射时,在DispatcherServlet中就会将请求参数赋值给相应的形参。

@RequestMapping("/testParams2")
    public String test2(String username,String password){
        return "user";
    }

若请求所传输的请求参数中有多个同名的请求参数,此时可以在控制器方法的形参中设置字符串
数组或者字符串类型的形参接收此请求参数
若使用字符串数组类型的形参,此参数的数组中包含了每一个数据
若使用字符串类型的形参,此参数的值为每个数据中间使用逗号拼接的结果

3.@RequestParam注解 

与上述控制器方法搭配使用

<a th:href="@{/testParams2(user_name='make',password=123)}">测试@RequestParam与控制器方法的形参获取请求参数</a>
@RequestMapping("/testParams3")
    public String test3(@RequestParam(value = "user_name") String username, String password){
        return "user";
    }

4.@RequestHeader

@RequestHeader是将请求头信息和控制器方法的形参创建映射关系 @RequestHeader注解一共有三个属性:value、required、defaultValue,用法同@RequestParam

5.@CookieValue 

@CookieValue是将cookie数据和控制器方法的形参创建映射关系 @CookieValue注解一共有三个属性:value、required、defaultValue,用法同@RequestParam

 session依赖于cookie,cookie是客户端会话技术,session是服务器端会话技术

第一次执行getSession()方法时,Set-Cookie的JSESSIONID存在于响应报文中;之后就会存在于请求报文中。

6.通过POJO获取请求参数

当前从浏览器发送的请求所提交的请求参数跟当前实体类对象里的属性一一对应,那么我们可以直接在形参位置写一个实体类型的形参,这时只需要保证请求参数的名字和实体类对象的属性名保持一致,就可以自动通过实体类对象收集这些请求参数。(简而言之:html中的请求的形式参数与实体类中的属性要保持一致,然后在控制层中只需要传入对象,这样就能获取具体的请求的实际参数)

public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String sex;
    private String email;

    public User(){

    }

    public User(Integer id, String username, String password, Integer age, String sex, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
        this.sex = sex;
        this.email = email;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}
<!--html-->
<form th:action="@{/testpojo}" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    性别:<input type="radio" name="sex" value="男">男<input type="radio"
                                                        name="sex" value="女">女<br>
    年龄:<input type="text" name="age"><br>
    邮箱:<input type="text" name="email"><br>
    <input type="submit">
</form>
//controller控制器
@RequestMapping("/testpojo")
    public String testPOJO(User user){
        System.out.println(user);
        return "user";
    }

解决获取请求参数中的乱码问题: 

get请求方式乱码问题解决:在tomcat的setting.xml配置文件中加上URIencoding="UTF-8".

post请求方式乱码:因为DispatcherServlet已经获取了请求参数,我们需要在DispatcherServlet获取请求参数之前设置编码,已知加载时间:监听器早于过滤器早于Servlet,监听器只有监听功能(监听ServletContext的创建与销毁-都只执行一次),过滤器只要设置了过滤路径,只要我们当前所访问的请求地址满足过滤路径,都会被过滤器进行过滤,故应该通过滤器来设置编码。在web.xml中配置:

   <filter>
        <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

域对象共享数据 

三种域对象:request一次请求,session一次会话,ServlstContext;

前两种就是浏览器开启到关闭的过程,还有一种表示一个JSP页面的PageContext(application).

session的数据跟服务器是否关闭无关,只跟浏览器是否关闭有关,因为它存在钝化和活化

钝化:当服务器关闭,浏览器没关闭,会话仍然在继续,这是存储在session中的数据会经过序列化到磁盘上。

活化:当服务器关闭,浏览器没关闭,但是服务器这时又重新开启了,这时钝化后的文件内容又会重新读取到session中。

ServlstContext只跟服务器是否关闭有关系。Servlset上下文对象在服务器启动时创建,在服务器关闭时销毁。

1.使用ServletAPI向request域对象共享数据(一般不用)

@Controller
public class ScopeConterller {
    @RequestMapping("/testRequestServletAPI")
    public String testRequestServletAPI(HttpServletRequest request){
        request.setAttribute("username","张三");
        return "success";
    }
}
<p th:text="${username}"></p>

 目标页面是通过键来获取数据。

2.使用ModelAndView向request域对象共享数据(*)

SpringMVC提供的API

ModeAndView有Mode和View的功能
Mode:主要用于向谨求域共享数据
View:主要用于设置视图,实现页面跳转

@RequestMapping("/testModulAndView")
    public ModelAndView testModulAndView(){
        ModelAndView mav=new ModelAndView();
        //处理数据模型,即向请求域request共享数据
        mav.addObject("username","李四");
        //设置视图名,此处视图名还是要与要转发html页面名一致
        mav.setViewName("success");
        return mav;
    }

 3.使用Model向request域对象共享数据

@RequestMapping("/testModul")
    public String Model(Model model){
        model.addAttribute("username","王五");
        return "success";
    }

4.使用map向request域对象共享数据

@RequestMapping("/testMap")
    public String testMap(Map<String,Object> map){
        map.put("username","赵六");
        return "success";
    }

5.使用ModelMap向request域对象共享数据

@RequestMapping("/testModelMap")
    public String testModelMap(ModelMap modelMap){
        modelMap.addAttribute("username","小七");
        return "success";
    }

6.向session域共享数据

 此处建议使用Servlet原生API,在目标页面是通过session.键的方式获取数据

<p th:text="${session.username}"></p>
@RequestMapping("/testSession")
    public String testSssion(HttpSession session){
        session.setAttribute("username","老八");
        return "success";
    }

7.向application域共享数据

appliacation即是ServletContext,目标页面获取数据方式为application.键

<p th:text="${application.username}"></p>
@RequestMapping("/testApplication")
    public String testApplaication(HttpSession session){
        ServletContext application=session.getServletContext();
        application.setAttribute("username","归一");
        return "success";
    }

8.域对象的选择 

选择能实现功能的范围最小的域对象

SpringMVC中的视图

 1.Thymeleaf

特点:视图名称没有任何前缀

@RequestMapping("/testThymeleaf")
    public String testThymeleaf(){
        return "success";
    }

 2.转发视图

forward转发的视图是通过 InternalResourceView(网络资源视图)进行解析的.

1.浏览器发送一次请求,第二次会发生服务器内部的跳转(地址栏还是会是第一次发送的请求的地址).

2.转发可以获取请求域中的对象(因为转发是一次请求,用到的request对象是同一个).

3.转发能访问WEN-INF下的资源.

4.转发不能跨域(转发发生在服务器内部,只能访问服务器内部资源).

@RequestMapping("/testForward")
    public String testForward(){
        return "forward:testThymeleaf";
    }

地址栏显示:http://localhost:8080/SpringMVC_Demo3/testForward 

页面:success.html

3.重定向视图

1. 浏览器发送两次请求,第一次访问Servlet,第二次访问重定向的地址。(地址栏中的地址就会是第二次重定向后的地址)。

2.重定向不可以获取请求域中的对象(有两次请求,用到的request对象是同两个).

3.重定向不能访问WEN-INF下的资源(因为WEN-INF下的资源具有安全性、隐藏性,只能通过服务器内部访问).

4.重定向可以跨域(发生在浏览器,可以通过浏览器访问任意资源).

@RequestMapping("/testRedirect")
    public String testRedirect(){
        return "redirect:/testThymeleaf";
    }

地址栏显示:http://localhost:8080/SpringMVC_Demo3/testThymeleaf

页面:success.html

4.视图控制器view-controller

 在SpringMVC配置文件中,配置视图控制器,来实现请求地址和映射直接的关系

<!--path:设置处理的请求地址
vi ew-name:设置请求地址所对应的视图名称
-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>

 相当于:

@RequestMapping("/")
    public String index(){
        return "index";
    }

 用处:在当前请求映射所对应的控制器方法中,没有其他请求过程的处理,仅仅只需要设置一个视图名称

PS:当我们在SpringMVC中配置了view-controller之后,控制器中所写的所有请求映射都会失效

      解决方法:在配置文件中开启mvc的注解驱动

<mvc:annotation-driven/>

RESTFul:

简介

Representational State Transfer,表现层资源状态转移,一种软件架构风格。

 RESTFul的实现

 SpringMVC配置文件过滤器的执行顺序:把设置编码的过滤器配置到获取请求参数的过滤器前,否则编码过滤器无效。

关于thymeleaf中的参数解析

@{}里的内容会被解析成路径,此时如果拼接参数成:@{/employee/${employee.id}}得不到数据。

解决方法:1.用加号拼接@{/employee/}+${employee.id}

                  2.可以放里面,但是请求地址上加上单引号,再加号:@{'/employee/'+${employee.id}}

HttpMessageConverter(报文信息转换器)

@RequestBody,RequestEntity 将请求报文数据转化为java数据

@ResponseBody,ResponseEntity将java数据转化为响应信息

1.@RequestBody

<form th:action="@{/testRequestBody}" method="post">
    <input type="text" name="username">
    <input type="text" name="password">
    <input type="submit" value="测试@RequestBody">
</form>
@RequestMapping("/testRequestBody")
    public String testRequestBody(@RequestBody String requestBody){
        System.out.println("RequestBody"+requestBody);
        return "success";
    }

2.RequestEntity

@RequestMapping("/testRequestEntity")
    public String testRequestEntity(RequestEntity<String> requestEntity){
        System.out.println("请求头:"+requestEntity.getHeaders());
        System.out.println("请求体"+requestEntity.getBody());
        return "success";
    }

3.@ResponseBody

@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器

1.用ServletAPI实现response对象响应浏览器数据

@RequestMapping("/testResponse")
    public String testResponse(HttpServletResponse response) throws IOException {
        response.getWriter().print("hello response");
        return "success";
    }

2.用SpringMVC实现response对象响应浏览器数据

 加上@ResponseBody注解,当前方法的返回值不是视图名,而是当前响应的响应体(即响应到页面的数据是success),如果要返回的数据是一个对象,就需要用到Json数据格式转换(直接用maven导入jackson的依赖即可)

4.SpringMVC处理Json

5.SpringMVC处理Ajax

<div id="app">
    <a @click="testAxios" th:href="@{/testAjax}">测试Ajax</a>
</div>
<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript" th:src="@{/static/js/axios.min.js}"></script>
<script type="text/javascript">
    new Vue({
       el:"#app",
        methods:{
           testAxios:function (event) {
               axios({
                   method: "post",
                   url:event.target.href,
                   params:{
                       username:"张三",
                       password:"123456"
                   }
               }).then(function (response) {
                   alert(response.data)
               });
               event.preventDefault();
           }
        }
    });

</script>
@RequestMapping("/testAjax")
    @ResponseBody
    public String testAxios(String username,String password){
        System.out.println(username+password);
        return "耶耶耶";
    }

6.@RestController

7.ResponseEntity

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文

可用于实现文件下载功能

@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws
IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.jpg");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers,
statusCode);
//关闭输入流
is.close();
return responseEntity;
}

 文件上传

springMVC中的上传:SpringMVC将我们要上传的文件对象封装到了MultipartFile对象中,我们需要用到文件上传解析器将上传的文件封装成MultipartFile。(在SpringMVC配置文件中配置文件上传解析器)

<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    </bean>
                            <!--以二进制流的方式传输文件,这样我们才能接收到-->
<form th:action="@{/testUp}" method="post" enctype="multipart/form-data">
    头像:<input type="file" name="photo"><br>
    <input type="submit" value="上传">
</form>

 解决文件名重名的问题:使用uuid随机生成相同文件再次上传后的一个文件名

@RequestMapping("/testUp")
    public String testUp(MultipartFile photo, HttpSession session) throws IOException {
        String fileName=photo.getOriginalFilename();
        //获取上传文件的后缀名
        String suffixName=fileName.substring(fileName.lastIndexOf("."));
        //将UUID作为文件名
        String uuid= UUID.randomUUID().toString();
        //将uuid和后缀名拼接后的结果作为最终的文件名
        fileName=uuid+suffixName;
        ServletContext context=session.getServletContext();
        String photoPath = context.getRealPath("photo");
        File file=new File(photoPath);
        if(!file.exists()){
            file.mkdir();
        }
        String filePath=photoPath+File.separator+fileName;
        photo.transferTo(new File(filePath));
        return "success";
    }

拦截器

过滤器作用于浏览器和DispatcherServlet之间(过滤器在servlet之前拦截),拦截器作用于控制器执行前后(用来拦截控制器方法,在控制器之前拦截)

拦截与放行(doFilter方法完成后就放行)

HandlerInterceptor中preHandle的返回值为true则表示放行;反之,拦截。

1.拦截器的配置

 2.拦截器的三个抽象方法


 3.多个拦截器的执行顺序 

a>若每个拦截器的preHandle()都返回true 此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关: preHandle()会按照配置的顺序执行,而postHandle()和afterComplation()会按照配置的反序执行 b>若某个拦截器的preHandle()返回了false

preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false 的拦截器之前的拦截器的afterComplation()会执行

 异常处理

1.基于配置的异常处理

 2.基于注解的异常处理

 注解配置SpringMVC

使用配置类和注解代替web.xml和SpringMVC的功能

1.创建初始类,代替web.xml

public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {

    //指定spring的配置类
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }
    //指定SpringMVC的配置类
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    //指定DispatcherServlet的映射规则,即url-pattern
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //添加过滤器
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceResponseEncoding(true);
        HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
        return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
    }
}

2、创建SpringConfig配置类,代替spring的配置文件

@Configuration
public class SpringConfig {
//ssm整合之后,spring的配置信息写在此类中
}

3、创建WebConfig配置类,代替SpringMVC的配置文件

 

//此类代替SpringMVC的配置文件
@Configuration
//扫描组件
@ComponentScan("com.zc.mvc.controller")
//mvc注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    private Properties prop;

    //使用默认的servlet处理静态资源
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    //拦截器
    public void addInterceptors(InterceptorRegistry registry) {
        TestInterceptor testInterceptor=new TestInterceptor();
        registry.addInterceptor(testInterceptor).addPathPatterns("/**");
    }

    //配置视图控制
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }

    //配置文件上传解析器
    @Bean
    public CommonsMultipartResolver multipartResolver(){
        return new CommonsMultipartResolver();
    }

    //配置异常映射
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver exceptionResolver=new SimpleMappingExceptionResolver();
        Properties properties=new Properties();
        properties.setProperty("java.lang.ArithmeticException","error");
        exceptionResolver.setExceptionMappings(properties);
        exceptionResolver.setExceptionAttribute("exception");
        resolvers.add(exceptionResolver);
    }

    //配置视图解析器
    //配置生成模板解析器
    @Bean
    public ITemplateResolver templateResolver() {
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());
        templateResolver.setPrefix("/WEB-INF/html/");
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }
    //生成模板引擎并为模板引擎注入模板解析器
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }
    //生成视图解析器并未解析器注入模板引擎
    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }
}

SpringMVC执行流程

1.SpringMVC常用组件

 2.DisPatcherServlet初始化过程

3.SpringMVC执行流程

 

 


版权声明:本文为qq_55737371原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。