SpringMVC学习笔记

SpringMVC学习笔记

1、SpringMVC简介

1、什么是MVC

MVC 是一种软件架构的思想,将软件按照模型、视图、控制器来划分。

M:Model,模型层,指工程中的 JavaBean,作用是处理数据。

javaBean 分为两类:

  • 实体类 Bean:专门存储业务数据的,如 Student、User等;
  • 业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。

V:View,视图层指工程中的 html 或 jsp 页面,作用是与用户进行交互,展示数据。

C:Controller,控制层,指工程中的 servlet,作用是接收请求和响应浏览器。

MVC 的工作流程:

用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的 View 视图,渲染数据后最终响应到浏览器。

2、什么是SpringMVC

SpringMVC 是 Spring 的一个后续产品,是Spring 的一个子项目。

SpringMVC 目前作为 JavaEE 项目表述层开发的首选方案

注:三层架构分为表述层、业务逻辑层、数据访问层。表述层表示前台页面和后台servlet

3、SpringMVC的特点

  • 基于原生的Servlet,通过前端控制器 DispatcherServlet,对请求和响应式进行统一处理
  • 提供全面解决方案
  • 代码清新简洁
  • 内部组件化程度高,可插拔式组件即插即用
  • 性能卓著

2、HelloWorld

1、创建maven工程

  1. 添加web模块

  2. 打包方式:war

<?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.zwj.mvc</groupId>
    <artifactId>springMVC-demo1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <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和hymeleaf整合包-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
    </dependencies>
</project>

2、配置web.xml

注册SpringMVC 的前端控制器 DispatcherServlet

1、默认配置方式

此配置作用下,SpringMVC的配置文件默认位于WEB-INF下,默认名称为servlet.xml。

<!--配置SpringMVC的前端控制器,对浏览器发送的请求进行统一处理-->
<servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <!--
        设置SpringMVC的核心控制器所能处理的请求的请求路径
        /所匹配的请求可以使/login或.html或.js或.css方式的请求路径
        但是/不能匹配.jsp请求路径的请求
    -->
    <url-pattern>/</url-pattern>
</servlet-mapping>
2、扩展配置方式

可通过init-param标签设置SpringMVC配置文件的位置和名称。通过load-on-startup标签设置SpringMVC前端控制器DispatcherServlet的初始化时间。

<!--配置SpringMVC的前端控制器,对浏览器发送的请求进行统一处理-->
<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.xml</param-value>
    </init-param>
    <!--将前端控制器DispatcherServlet的初始化时间提前到服务器启动时-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

3、创建请求控制器

由于前端控制器对浏览器发送的请求进行了统一的处理,但是具体的请求有不同的处理过程,因此需要创建处理具体请求的类,即请求控制器。

请求控制器中每一个处理请求的方法称为控制器方法。

因为SpringMVC的控制器由一个POJO(普通的 java 类)担任,因此需要通过@Controller注解将其标识为一个控制层组件,交给Spring的IOC容器管理,此时SpringMVC才能够识别控制器的存在。

@Controller
public class HelloController {
}

4、创建SpringMVC的配置文件

<?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"
       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">

    <!--开启扫描组件-->
    <context:component-scan base-package="com.zwj.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>
</beans>

5、测试HelloWorld

1、实现对首页的访问

在请求控制器中创建处理请求的方法。

// "/"表示/WEB-INF/templates/index.html

@RequestMapping("/")
public String index(){
    //返回视图名称
    return "index";
}
2、访问目标页面

使用Thymeleaf帮助解析到目标文件。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>首页</h1>
<a th:href="@{/target}">访问目标页面</a>
</body>
</html>

在请求控制器中创建处理请求的方法

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

6、总结

  1. 浏览器发送请求,若请求地址符合前端控制器的url-pattern,该请求就会被前端控制器DispatcherServlet处理。

  2. 前端控制器会读取SpringMVC的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中 @RequestMapping 注解的 value 属性值进行匹配,若匹配成功,该注解所标识的控制器方法就是处理请求的方法。

  3. 处理请求的方法需要返回一个字符串类型的视图名称,该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径,通过Thymeleaf 对视图进行渲染,最终转发到视图所对应页面。

3、@RequestMapping注解

1、@RequestMapping注解的功能

@RequestMapping的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。

SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。

2、@RequestMapping注解的位置

@RequestMapping标识一个类:设置映射请求的请求路径的初始信息

@RequestMapping标识一个方法:设置映射请求的请求路径的具体信息。

@Controller
@RequestMapping("/hello")
public class HelloController {

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

加在类上,相当于访问的时候多一层目录。用于分模块。

<a th:href="@{/hello/target}">访问目标页面</a>

3、value属性

@RequestMapping的 value属性是一个字符串数组,可以匹配多个请求地址所对应的请求。

@RequestMapping(
        value = {"/target","/success"}
)
public String toTarget(){
    return "target";
}

4、method属性

@RequestMapping注解的method属性通过请求方式(get和post)匹配请求映射。

@RequestMapping注解的method属性是一个RequestMethod类型的数组,表示该请求映射能够匹配多种请求方式的请求。

若当前请求的请求地址满足请求映射的value属性,但是请求方式不满足method属性,则浏览器报错405:Request method ‘POST’ not supported

@RequestMapping(
        value = {"/testRequestMapping","/test"},
        method = {RequestMethod.GET}
)
public String success(){
    return "success";
}

注:

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

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

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

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

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

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

    但是目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符串(put或delete),则按照默认的请求方式get处理。

    若要发送put 和 delete 请求时,则需要通过spring提供的过滤器HiddenHttpMethodFilter。

5、params属性(了解)

@RequestMapping注解的params属性通过请求的请求参数匹配请求映射。

@RequestMapping注解的params属性是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系:

param:要求请求映射所匹配的请求必须携带param请求参数

!param:要求请求映射所匹配的请求必须不能携带param请求参数

param=value:要求请求映射所匹配的请求必须携带param请求参数且param=value

param!=value:要求请求映射所匹配的请求必须携带param请求参数但是param!=value

<a th:href="@{/testRequestMapping(username='admin',password=123456)}">params</a>

6、headers属性(了解)

@RequestMapping注解的headers属性通过请求的请求头信息匹配请求映射。

@RequestMapping注解的headers属性是一个字符串类型的数组,可以通过四种表达式:

header:要求必须携带header请求头信息;

!header:要求必须不能携带header请求头信息;

header=value:要求必须携带header请求头信息且header=value;

header!=value:要求必须携带header请求头信息且header!=value;

若当前请求满足@RequestMapping注解的value和method属性,但是不满足header属性,此时页面显示404错误,即资源未找到。

7、SpringMVC支持ant风格的路径

?:表示任意的单个字符;

*:表示任意的0个或多个字符;

**:表示任意的一层或多层目录;

注意:在使用**时,只能使用/**/xxx的方式

8、SpringMVC支持路径中的占位符(重点)

原始方式:/deleteUser?id=1

rest方式:/deleteUser/1

SpringMVC路径中的占位符常用语restful风格中,当请求路径中将某些数据通过路径的方式传输给服务器中,就可以在相应的 @RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据,在通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参。

<a th:href="@{/testRest/1/admin}">占位符</a>
@RequestMapping("/testRest/{id}/{username}")
public String testRest(@PathVariable("id") String id,@PathVariable("username")String username){
    System.out.println("id:"+id+",username:"+username);
    return "target";
}
//id:1,username:admin

4、SpringMVC获取请求参数

1、通过servletAPI获取

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

@RequestMapping("/testServletAPI")
//形参位置的request表示当前请求
public String testServletAPI(HttpServletRequest request){
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    System.out.println(username+password);
    return "target";
}

2、通过控制器方法的形参获取

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

@RequestMapping("/testParam")
public String testParam(String username, String password, String[] hobby) {
    //对于多个同名的请求参数
    //可以使用String接收,得到用逗号隔开的字符串
    //也可以使用String[]接收,得到字符串数组
    System.out.println(username + password + Arrays.toString(hobby));
    return "target";
}

3、@RequestParam

@RequestParam(value="user_name",required=false,defaultValue="hehe")String user

value:可以指定匹配哪个参数,不要默认的同名匹配;

required:是否必须要该参数,false的话可以接受null的情况;默认时true。

defaultValue:设置默认值,找不到时使用默认值。

4、@RequestHeader

@RequestHeader("Host") String host)

@RequestHeader是将请求头信息和控制器方法的形参创建映射关系;

有三个属性:valuerequireddefaultValue,用法同@RequestParam

5、@CookieValue

@CookieValue是将cookie数据和控制器方法的形参创建映射关系。

有三个属性:valuerequireddefaultValue,用法同@RequestParam

6、通过POJO获取请求参数

可以在控制器方法的形参位置设置一个实体类类型的形参,此时若浏览器传输的请求参数的参数名和实体类中的属性名一致,那么请求参数就会为此属性赋值。

@RequestMapping("/testBean")
public String testBean(User user) {
    System.out.println(user);
    return "target";
}

7、解决获取请求参数的乱码问题

get乱码问题,可以在Tomcat的conf/server.xml里加上URIEncoding="UTF-8"

解决post和get乱码问题的一劳永逸方法:

在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>
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

5、域对象共享数据

1、使用servletAPI想request域对象

@RequestMapping("/testRequestByServletAPI")
public String testRequestByServletAPI(HttpServletRequest request){
    request.setAttribute("testRequestScope","hello,servletAPI");
    return "success";
}
<p th:text="${testRequestScope}"></p>

2、使用ModelAndView向request域对象共享数据

@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
    /**
     * ModelAndView有Model和View的功能
     * Model主要用于向请求域共享数据
     * View主要适用于设置视图,实现页面跳转
     */
    /
    ModelAndView mav = new ModelAndView();
    //处理模型数据,即向请求域request共享数据
    mav.addObject("testRequestScope","hello,ModelAndView");
    //设置视图,实现页面跳转
    mav.setViewName("success");
    return mav;
}

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

@RequestMapping("/testModel")
public String testModel(Model model){
    model.addAttribute("testRequestScope","hello,Model");
    return "success";
}

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

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

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

@RequestMapping("testModelMap")
public String testModelMap(ModelMap modelMap){
    modelMap.addAttribute("testRequestScope","hello,ModelMap");
    return "success";
}

6、Model、ModelMap、Map的关系

Model、ModelMap、Map类型的参数本质上都是 BindingAwareModelMap 类型的。

public interface Model{}
public class ModelMap extends LinkedHashMap<String,Object>{}
public class ExtendedModelMap extends ModelMap implements Model{}
public class BindingAwareModelMap extends ExtendedModelMap{}

7、向session域共享数据

@RequestMapping("/testSession")
public String testSession(HttpSession session){
    session.setAttribute("testRequestScope","hello,session");
    return "success";
}

8、向application域共享数据

@RequestMapping("/testApplication")
public String testApplication(HttpSession session){
    ServletContext application = session.getServletContext();
    application.setAttribute("testRequestScope","hello,application");
    return "success";
}

6、SpringMVC的视图

SpringMVC中的视图是View接口,视图的作用就是渲染数据,将模型Model中的数据展示给用户。

SpringMVC视图的种类很多,默认有转发视图和重定向视图。

当工程引入jstl的依赖,转发视图会自动转换为jstlView。

若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView。

1、ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转。

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

2、转发视图internalResourceView

SpringMVC中创建转发视图的情况:

当控制器方法种所设置的视图名称以"forward:"为前缀时,创建internalResourceView视图,此时的视图名称不会被视图解析器解析,而是会把前缀去掉,剩余部分作为最终路径通过转发的方式实现跳转。

@RequestMapping("/testBean")
public String testBean() {
    return "forward:/testHello";
}

3、重定向视图RedirectView

以"redirect:"为前缀时,创建RedirectView视图,不会被视图解析器解析,而是去掉前缀,剩余部分作为最终路径通过重定向的方式实现跳转。

@RequestMapping("/testBean")
public String testBean() {
    return "redirect:/testHello";
}

4、视图控制器view-controller

当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示。

<mvc:view-controller path="/" view-name="index"></mvc:view-controller>

<!--开放静态资源访问-->
<mvc:default-servlet-handler />

<!--开启MVC的注解驱动-->
<mvc:annotation-driven/>

注:当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要在SpringMVC的核心配置文件中开启MVC的注解驱动:

<mvc:annotation-driven/>


7、RESTFul

1、RESTFul简介

REST:Representational State Transfer,表现层资源状态转移。

1、资源

字面意思。。。。

2、资源的表述

资源表述的多种格式:HTML/XML/JSON/纯文本/图片/视频/音频等。

3、状态转移

操作资源。

2、RESTFul的实现

GET、POST、PUT、DELETE

获取资源、新建资源、更新资源、删除资源。

REST风格提倡 URL 地址,不使用问号键值对方式携带请求参数,而是通过斜杠分隔开。

3、HiddenHttpMethodFilter

由于浏览器只支持GET和POST,SpringMVC 提供了 HiddenHttpMethodFilter 帮助我们将 POST 请求转换为 DELETE 或 PUT 请求

@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
public String getUserById(){
    sout("查询用户信息");
    return "success";
}
<!--配置HiddenHttpMethodFilter-->
<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

8、HttpMessageConverter

HttpMessageConverter,报文信息转换器,将报文变成Java对象,把Java对象变成报文。

HttpMessageConverter提供了两个注解和两个类型:@RequestBody, @ResponseBody, RequestEntity, ResponseEntity

1、@RequestBody

@RequestBody可以获取请求体。

public String test(@RequestBody String requestBody){
}

2、RequestEntity

RequestEntity封装请求报文的一种类型。

可以通过getHeaders()获取请求头信息,通过getBody()获取请求体信息。

public String test(RequestEntity<String> requestBody){
}

3、@ResponseBody

可以将该方法的返回值直接作为响应报文的响应体响应到浏览器。

@RequestMapping("/test")
@ResponseBody
public String testResponseBody(){
    return "success";
}

4、SpringMVC处理json

@ResponseBody处理json的步骤:

  1. 导入jackson的依赖:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.12.1</version>
    </dependency>
    
  2. 开启mvc的注解驱动,此时在HandlerAdaptor中会自动装配一个消息转换器:Mappingjackson2HttpMessageConverter,可以将响应到浏览器的java对象转换为json字符串。

    <mvc:annotation-driven/>

  3. 在处理器方法上使用@ResponseBody注解进行标识;

  4. 将java对象直接作为控制器方法的返回值返回,就会自动转换为json字符串。

5、SpringMVC处理ajax

@RequestMapping("/testAjax")
@ResponseBody
public String testAjax(String username,String password){
    return "success";
}

6、@RestController注解

@RestController注解是一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解。

7、ResponseEntity

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


9、文件上传与下载

public String testFileLoad(MultipartFile multipartFile){
    return "";
}
<!--配置文件上传解析器,将上传的文件封装为MultipartFile-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

10、拦截器

1、拦截器的配置

  1. 创建拦截器类implements HandlerInterceptor
@Component
public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
  1. 配置拦截器

和方式的拦截器,会拦截所有请求。

<mvc:mapping设置需要拦截的请求。

<mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求。

<!--配置拦截器-->
<mvc:interceptors>
    <bean class="com.zwj.mvc.interceptors.FirstInterceptor"></bean>
</mvc:interceptors>
<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/"/>
        <ref bean="firstInterceptor"></ref>
    </mvc:interceptor>
</mvc:interceptors>

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

preHandle控制器前、返回true为放行,即调用控制器方法;false表示拦截,不调用控制器方法。

postHandle控制器后执行

afterCompletion处理完视图和模型数据,渲染视图完毕后执行

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

  1. 若每个拦截器的preHandle都返回true

    此时preHandle会按照配置的顺序执行,postHandle和afterCompletion会按配置的倒序执行。

  2. 若某个拦截器的preHandle返回false

    返回false的preHandle和之前的preHandle都会执行,postHandle都不执行,返回false之前的拦截器的afterCompletion会执行。


11、异常处理器

1、基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:

<!--配置异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <!--设置要跳转到的错误页面-->
            <prop key="java.lang.ArithmeticException">error</prop>
        </props>
    </property>
    <!--存储异常信息共享在请求域中的键-->
    <property name="exceptionAttribute" value="ex"></property>
</bean>

2、基于注解的异常配置

@ControllerAdvice
public class ExceptionController {

    //设置异常类型数组
    @ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
    public String testException(Exception ex, Model model){
        //共享在请求域中的异常信息
        model.addAttribute("ex",ex);
        return "error";
    }
}

12、注解配置SpringMVC

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

//web工程的初始化类,用来代替web.xml
public class Webinit extends AbstractAnnotationConfigDispatcherServletInitializer{

    /**
     * 指定Spring的配置类
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

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

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

    /**
     * 注册过滤器
     * @return
     */
    @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 {
}

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

/**
 * 代替SpringMVC的配置文件:
 * 扫描组件
 * 视图解析器
 * view-controller
 * default-servlet-handler
 * mvc注解驱动
 * 文件上传解析器
 * 异常处理
 * 拦截器
 */
//将当前类标识为一个配置类
@Configuration
//扫描组件
@ComponentScan("com.zwj.mvc.controller")
//mvc注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    //default-servlet-handler
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    //拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        FirstInterceptor firstInterceptor = new FirstInterceptor();
        registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
    }

    //view-controller
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }

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

    //异常处理
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
        Properties prop = new Properties();
        prop.setProperty("java.lang.ArithmeticException","erroe");
        exceptionResolver.setExceptionMappings(prop);
        exceptionResolver.setExceptionAttribute("exception");
        resolvers.add(exceptionResolver);
    }

    //配置生成模板解析器
    @Bean
    public ITemplateResolver templateResolver(){
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
                webApplicationContext.getServletContext());
        templateResolver.setPrefix("/WEB-INF/templates/");
        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;
    }

}

4、测试功能


13、SpringMVC执行流程

1、SpringMVC常用组件

springMVC组件

2、DispatcherServlet初始化过程

DispatcherServlet本质上是Servlet,所以遵循Servlet的生命周期。

1、初始化WebApplicationContext

创建WebApplicationContext;

刷新WebApplicationContext;

将IOC容器在应用域共享。

2、创建WebApplicationContext

所在类:org.springframework.web.servlet.FrameworkServlet

通过反射创建 IOC 容器对象。

设置父容器。

3、DispatcherServlet初始化策略

FrameworkServlet创建WebApplicationContext后,刷新容器,调用onRefresh(wac),此方法在DispatcherServlet中进行了重写,调用了initStrategies(context)方法,初始化策略,即初始化DispatcherServlet的各个组件。

所在类:org.springframework.web.servlet.DispatcherServlet。


3、DispatcherServlet调用组件处理请求

1、processRequest()

FrameworkServlet重写HttpServlet中的servlet()和doXxx(),这些方法中调用了processRequest(request,response)

所在类:org.springframework.web.servlet.FrameworkServlet

2、doService()

所在类:org.springframework.web.servlet.DispatcherServlet。

3、doDispatch()

所在类:org.springframework.web.servlet.DispatcherServlet。

mappedHandler:调用链

包含handler、interceptorList、interceptorIndex

handler:浏览器发送的请求所匹配的控制器方法

interceptorList:处理控制器方法的所有拦截器集合

interceptorIndex:拦截器索引,控制拦截器afterCompletion()的执行。


通过控制器方法创建相应的处理器适配器,调用所对应的控制器方法。


调用拦截器的preHandle()


由处理器适配器调用具体的控制器方法,最终获得ModelAndView对象。


调用拦截器的postHandle()


后续处理:处理模型数据和渲染视图

4、processDispatchResult()

处理模型数据和渲染视图。


调用拦截器的afterCompletion()。

4、SpringMVC的执行流程

SpringMVC执行流程1

SpringMVC执行流程2
SpringMVC流程3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值