SpringMVC入门笔记

第十一章 SpringMVC

11.1 什么是SpringMVC

springmvc是 由spring框架加mvc 编程思想加吸收javaweb的思想结合的web框架。

11.2 快速入门

第一种 可以选择 java Enterprise 创建springmvc项目
在这里插入图片描述
第二种 选择maven 项目中的webapp模板
在这里插入图片描述
选择第一种创建好的项目目录如下
在这里插入图片描述
pom文件

<?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.example</groupId>
    <artifactId>Springmvc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>Springmvc</name>
<!--    打包方式war-->
    <packaging>war</packaging>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <junit.version>5.7.0</junit.version>
    </properties>

    <dependencies>
<!--        javaweb servlet 的核心依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
<!--        单元测试5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
</project>

该项目模板已配置好一个基础模板hello world,直接部署Tomcat启动
在这里插入图片描述
Tomcat启动成功之后,访问项目 出现如下页面代表部署成功
在这里插入图片描述

到此,javaweb项目已部署成功,接下来把javaweb改造成springmvc项目

11.2.1 javaweb转换为springmvc

加入依赖
1 加入springmvc依赖

<!--        springmvc 依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.20</version>
        </dependency>

spring-webmvc jar包包含了spring框架的jar包
在这里插入图片描述

2 在web.xml 文件中配置springmvc的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">


<!--    dispatcherServlet是springmvc的核心servlet,它负责接收客户端发送来的所有请求-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

上面的配置跟javaweb是一样的,是一个普通的servlet,还没有达到springmvc的配置。
继续改进如下

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


<!--    配置springmvc的监听器 用于监听spring容器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<!--    配置上下文-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-ioc.xml</param-value>
    </context-param>


<!--    dispatcherServlet是springmvc的核心servlet,它负责接收客户端发送来的所有请求-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        配置 dispatcherServlet 的初始化参数 contextConfigLocation 参数名称是固定的-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>


<!--        servlet 的加载级别,数字越小级别越大,0 为按需加载-->
        <load-on-startup>1</load-on-startup>
    </servlet>

<!--    dispatcherServlet的请求映射路径-->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--      /  拦截所有请求,不包括 .jsp 
          /* 拦截所有请求,包括 .jsp  使用 会报404错误-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

dispatcherServlet 有一个参数contextConfigLocation 该参数的名称是固定的,值是spring-mvc.xml 配置文件所在的路径,如果不配置参数,就需要把配置文件按指定的命名格式与位置放置。
格式 {servletName}-servlet.xml 如: spring-mvc-servlet.xml
放置位置:WEB-INF目录及子目录下。

spring-mvc.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns: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
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

<!--    配置springmvc 扫描路径,这里只扫描 控制器 controller的包-->
    <context:component-scan base-package="com.example.Springmvc.controller"/>
</beans>

spring-ioc.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns: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
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

</beans>

第一种方式,通过注解
创建一个controller包,并在该包下创建一个HelloController类

package com.example.Springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: lyf
 * @CreateTime: 2022-12-03
 * @description:
 */
@Controller // 标记为spring组件
public class HelloController {


    /**
     * @RequestMapping 表示请求映射注解 值为请求映射的值
     * @return
     */
    @RequestMapping("/hello")
    public String hello(){
        // 在控制台输出
        System.out.println("hello world ");
        // 返回到index.jsp 页面
        return "index.jsp";

    }
}

重启Tomcat服务器 访问 http://localhost:8080/Springmvc_war_exploded/hello
页面跳转到index首页
控制台输出
在这里插入图片描述
第二种方式
实现Controller接口 @Controller的类名小写加一个/ 符号代表访问路径

 @org.springframework.stereotype.Controller("/servlet")
public class ServletController  implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
         response.getWriter().write("<h1>hello world<h1>");
         return null;
    }
}

总结

到此,从javaweb转到springmvc配置已经结束,是不是特别简单,只需在web.xml文件中配置一个servlet,就可以使用javaweb中使用spring的ioc与aop了。

11.3 springmvc的工作流程

在这里插入图片描述
SpringMVC 的执行流程如下。

1 用户通过浏览器发起一个 HTTP 请求,该请求会被 DispatcherServlet(前端控制器)拦截;
2 DispatcherServlet 调用 HandlerMapping(处理器映射器)找到具体的处理器(Handler)及拦截器,最后以 HandlerExecutionChain 执行链的形式返回给 DispatcherServlet。
3 DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
4 HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(即 Controller 控制器)对请求进行处理;
5 Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC 的底层对象,包括 Model 数据模型和 View 视图信息);
6 HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
7 DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
8 ViewResolver 解析完成后,会将 View 视图并返回给 DispatcherServlet;
9 DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
10 视图负责将结果显示到浏览器(客户端)。

总结

以上的流程当中,我们只需要编写控制器 controller 与视图 view 即可,其他的spring框架已经提供了。

11.3 springmvc 控制器

11.3.1 什么是springmvc控制器

springmvc的控制器与servlet有着本质的区别,springmvc的控制器接收到的请求是靠dispatcherServlet对象拦截转发过来的。本质不是一个servlet对象。

11.3.2 控制器案例

注解 @Controller 表示为控制器注解。
@ResponseBody 注解表示 返回的数据以json形式返回到客户端。
@RestController 是 由@ResponseBoby与@Controller注解的复合注解,表示当前处理完的数据由json格式发送到客户端,不需要视图解析器处理。

@Controller // 标记为spring组件
public class HelloController {

    /**
     * @RequestMapping 表示请求映射注解 值为请求映射的值
     * @return
     */
     @ResponseBody // 加载类上与方法上都可以,
    @RequestMapping("/hello")
    public String hello(){
        // 在控制台输出
        System.out.println("hello world ");
        // 返回到index.jsp 页面
        return "index.jsp";

    }
}

在hello方法上加入@ResponseBody注解,重启服务器,再次访问,没有跳转带index.jsp
在这里插入图片描述

11.4 springmvc请求映射

@RequestMapping 注解表示请求的映射路径,可以用在类上也可以用在方法上,用在类上表示是所有的方法映射的父映射,
请求路径为 /he/hello

package com.example.Springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: lyf
 * @CreateTime: 2022-12-03
 * @description:
 */
//@Controller // 标记为spring组件
@RestController
@RequestMapping("/he") // 父映射路径
public class HelloController {

    /**
     * @RequestMapping 表示请求映射注解 值为请求映射的值
     * @return
     */
   // @ResponseBody // 加载类上与方法上都可以,
    @RequestMapping("/hello") // 子映射路径
    public String hello(){
        // 在控制台输出
        System.out.println("hello world ");
        // 返回到index.jsp 页面
        return "index.jsp";

    }
}

@RequestMapping 注解属性
在这里插入图片描述

package com.example.Springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: lyf
 * @CreateTime: 2022-12-03
 * @description:
 */
//@Controller // 标记为spring组件
@RestController
@RequestMapping("/he") // 父映射路径
public class HelloController {

    /**
     * @RequestMapping 表示请求映射注解 值为请求映射的值
     * @return
     */
   // @ResponseBody // 加载类上与方法上都可以,
    @RequestMapping(
            value = {"/hello","hello1"} //支持多个路径匹配
            ,name = ""
       //     ,path = {"/hello","hello1"} 路径映射,不能跟value属性同时存在
            ,method = {RequestMethod.GET,RequestMethod.POST} //支持的方法
            , params = {"username","password"}// 请求参数,请求中有这个属性才接收请求
            , headers = {"Host: localhost:8080"} //请求头中含有指定的请求头才接受请求
            , consumes = {"Content-Type:text/html;charset=utf-8"}//指定处理请求的提交内容类型 (Content-Type),例如 application/json, text/html
            , produces = {"Content-Type:text/html;charset=utf-8"}
    ) // 子映射路径
    public String hello(){
        // 在控制台输出
        System.out.println("hello world ");
        // 返回到index.jsp 页面
        return "index.jsp";

    }
}



请求映射通配符

11.5 springmvc请求参数

在Tomcat中修改上下文路径
在这里插入图片描述

11.5.1 接收基本参数

 /**
     * 第一种,请求参数,与方法形参一致
     * @param username
     * 请求地址 http://localhost:8080/he/hello1?username=admin
     * @return
     */
    @RequestMapping("/hello1")
    public String hello1(String username){
        String name= username;
        return name;
    }

    /**
     * 第二种,请求参数,与方法形参不一致,请求参数 user  方法形参 username  通过注解@RequestParam 注解绑定
          * 请求地址 http://localhost:8080/he/hello2?user=admin

     * @param username
     * @return
     */
    @RequestMapping("/hello2")
    public String hello2(@RequestParam("user") String username){
        String name= username;
        return name;
    }

    /**
     * 第三种,请求参数,与方法形参不一致,请求参数 user  方法形参 username  通过注解@PathVariable 注解绑定
     * 保证请求路径中的user占位值与@PathVariable一致即可。
     * @param username
     *请求地址:http://localhost:8080/he/hello3/admin
     * @return
     */
    @RequestMapping("/hello3/{user}")
    public String hello3(@PathVariable("user") String username){
        String name= username;
        return name;
    }

11.5.2 接收对象参数

设置接收对象类型

package com.example.Springmvc.controller;

/**
 * @Author: lyf
 * @CreateTime: 2022-12-03
 * @description:
 */
public class User {
    
    private String username;
    
    private String password;
    
    private Integer age;
    
    private Integer sex;

    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 Integer getSex() {
        return sex;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

第一种通过属性名获取
http://localhost:8080/he/user?username=admin&password=123

 @RequestMapping( "/user")
    @ResponseBody
    public User getUser(User user){
        return user;
    }

第二种通过请求体方式

 @RequestMapping( "/user")
    @ResponseBody
    public User getUser(@RequestBody User user){
        return user;
    }

11.5.3 接收集合类型

  //属性名称获取
    @RequestMapping("/param")
    public void arrayParam(@RequestParam  Arrays arrays){

        System.out.println(arrays.toString());
    }

//        请求体获取
    @RequestMapping("/body")
    public void arrayBody(@RequestBody  Arrays arrays){

        System.out.println(arrays.toString());
    }

11.5.4 获取请求头参数

@RequestHeader 用于获取所有请求头,加参数获取指定请求头,不加,获取所有请求头

  /**
     * 获取请求头
     * @param header
     */
    @RequestMapping("/header")
    public void header(@RequestHeader("Cookie")String header){

        System.out.println(header);
    }

    /**
     * 获取所有请求头
     * @param header
     */
    @RequestMapping("/header")
    public void headerAll(@RequestHeader Map<String,String> header){

        System.out.println(header);
    }

11.5.5 获取cookie


    @RequestMapping("/cookie")
    public void getCookie(@CookieValue("cookieID") String cookieId){
        System.out.println(cookieId);
    }

11.5.6 获取HttpServletRequest

 
    @RequestMapping("/http")
    public void http(HttpServletRequest request){

        //获取指定参数
        String username = request.getParameter("username");
        Enumeration<String> parameterNames = request.getParameterNames();
        // 获取所有参数
        while (parameterNames.hasMoreElements()){
            String element = parameterNames.nextElement();
            String value = request.getParameter(element);

            System.out.println(element+":"+value);
            
        }
    }

11.5.7 @RequestMapping 子注解

@GetMapping
@PostMapping
@DeleteMapping
 @PutMapping
public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;

    private RequestMethod() {
    }
}

11.6 解决中文乱码

在web中加入编码过滤器,

  <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
       
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

点击CharacterEncodingFilter类查看它的属性,根据属性赋值
在这里插入图片描述
完整编码过滤器配置

<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>
        <!--强制Request使用字符集encoding-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--强制Response使用字符集encoding-->
        <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>

11.7 控制器的方法返回值

11.7.1 返回ModelAndView

ModelAndView 对象 表示返回模型与视图,如果一个请求需要返回数据与视图则就他作为返回值。

    @RequestMapping("/mv")
    public ModelAndView mv(){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("index.jsp");
        mv.addObject("username","admin");
        
        return  mv;
    }
    
}

11.7.2 返回String

 /**
     * 如果没有加@ResponseBody 或者@RestController注解,则返回的是视图名称,
     * 如果配置的有视图解析器,则返回的是逻辑视图,没有则返回物理地址视图
     * @return
     */
    @RequestMapping("/string")
    public String string(){
        return "String";
    }

    /**
     * 如果需要返回数据,则在参数中加入Model
     * @param model
     * @return
     */
    @RequestMapping("/string")
    public String stringModel(Model model){
        model.addAttribute("admin");
        return "String";
    }

11.7.3 返回void


/**
     * 先把对象转换为Json对象
     * 再通过Response对象通过流的方法把数据返回到客户端
     * @param response
     * @throws IOException
     */
    @RequestMapping("/void")
    public void aVoid(HttpServletResponse response) throws IOException {

        response.getWriter().write("void 对象返回");
    }

11.7.4 返回Object对象

返回Object对象,返回的数据是以json的形式返回的客户端,任何对象都是Object对象的子类,所以任何对象都可以返回。只需要加入@ResponseBody注解,或者使用复合注解@RestController

    @ResponseBody
    @RequestMapping("/string")
    public String stringModel(Model model){
        model.addAttribute("admin");
        return "String";
    }

11.8 springmvc域对象共享数据

在控制器处理完数据之后,需要将数据返回到共享的域当中,视图在从这个域中获取处理好的数据,渲染之后返回给客户端。

域对象是服务器在内存上创建的一块存储空间,主要用不同动态资源之间的数据传递和数据共享。在 Spring MVC 中,常用的域对象有 request 域对象、session 域对象、application 域对象等。

Spring MVC 提供了多种域对象共享数据的方式,其中最常用的方式如下:

使用 Servlet API 向 request 域对象中共享数据
使用 ModelAndView 向 request 域对象中共享数据
使用 Model 向 request 域对象中共享数据
使用 Map 向 request 域对象中共享数据
使用 ModelMap 向 request 域对象中共享数据
使用 Servlet API 向 session 域中共享数据
使用 Servlet API 向 application 域中共享数据

1 使用 Servlet API 向 request 域对象中共享数据

    @RequestMapping("req")
    public void request(HttpServletRequest request){
        request.setAttribute("username","admin");
    }

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

@RequestMapping("req1")
    public ModelAndView request1(){
     ModelAndView   modelAndView = new ModelAndView();
     modelAndView.addObject("username","admin");
     return modelAndView;
    }

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

 @RequestMapping("req2")
    public void request2(Model model){
        model.addAttribute("username","admin");
    }

4 使用 Map 向 request 域对象中共享数据

 @RequestMapping("req3")
    public void request3(Map<String ,String> map){
        map.put("username","password");
    }

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

@RequestMapping("req4")
    public void request4(ModelMap modelMap){
        modelMap.addAttribute("username","password");
    }

6 使用 Servlet API 向 session 域中共享数据

 @RequestMapping("/session")
    public void session(HttpSession session){
        session.setAttribute("username","admin");
    }

7 使用 Servlet API 向 application 域中共享数据

@RequestMapping("/session")
    public void application(HttpSession session){
        ServletContext servletContext = session.getServletContext();
        servletContext.setAttribute("username","admin");
    }

11.9 视图与视图解析器

视图就是页面,控制器返回的都是视图的名称,是字符串类型,中间需要视图解析器去解析名称,才能获取到真正的视图,ModelAndView 对象是两个不同的对象组合到一起的,分别是Model与View,model代表数据模型,View代表视图,通过把他们两个进行解耦。

View
View 分为逻辑视图与非逻辑视图,逻辑视图代表的是字符串,需要视图解析器解析才能渲染数据并响应到客户端,非逻辑视图代表的是一个View对象,不需要视图解析器去解析,因为视图对象可以直接渲染数据。
常见的视图类
在这里插入图片描述


    @RequestMapping("req1")
    public ModelAndView request1(){
     ModelAndView   modelAndView = new ModelAndView();
     modelAndView.addObject("username","admin");
     // InternalResourceView对象
     modelAndView.setView(new InternalResourceView());
     return modelAndView;
    }

Model
Model代表数据模型,用来封装控制器处理好的数据,放在共享域中,视图从共享域中获取数据,并渲染,再返回给客户端。

视图解析器
视图解析器(ViewResolver)是 Spring MVC 的重要组成部分,它提供了逻辑视图名称与实际视图之间的映射,负责将逻辑视图名解析为一个具体的视图对象。
在这里插入图片描述
在spring-mvc.xml 中配置

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

<!--让springmvc 不处理静态资源-->
    <mvc:default-servlet-handler/>

<!--    开启mvc注解  使@RequestMapping 生效-->
        <mvc:annotation-driven/>

视图控制器
第一种 通过控制器方法返回视图

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

第二种 如果 Spring MVC 中设置了任意一个视图控制器(View-Controller),那么其他控制器中请求映射将全部失效,此时我们需要在 Spring MVC 的核心配置文件中开启 mvc 注解驱动标签。

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

<!--    注解驱动标签-->
<mvc:annotation-driven />

总结

在视图解析器当中,建议把所有的视图放在 /WEB-INF/ 目录下,这样能保证视图安全,因为在该目录下的所有文件,客户端不能直接访问,需要警告控制器才能访问。

11.10 请求转发与重定向

在 Spring MVC 中,我们可以在逻辑视图名中通过“forward:”和“redirect:”两个关键字来表示转发和重定向。有这两个关键词的视图不会被视图解析器解析。

转发


    @RequestMapping("forward")
    public ModelAndView mv1(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("forward:index");
        return modelAndView;
    }

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

重定向

@RequestMapping("redirect")
    public ModelAndView mv1(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("redirect:index");
        return modelAndView;
    }

    @RequestMapping("/red")
    public String forward(){

        return "redirect:index";
    }

11.11 RESTful风格

RESTful(REST 风格)是一种当前比较流行的互联网软件架构模式,它充分并正确地利用 HTTP 协议的特性,为我们规定了一套统一的资源获取方式,以实现不同终端之间(客户端与服务端)的数据访问与交互。
REST 实际上是 Resource Representational State Transfer 的缩写,翻译成中文就是“表现层资源表述状态转移”。

传统URLREST URL
http://localhost:8080/user /addhttp://localhost:8080/user/add
http://localhost:8080/user /delete?id=1http://localhost:8080/user/delete/1
http://localhost:8080/user /update?id=1http://localhost:8080/user/update/1
http://localhost:8080/user /getUserByid?id=1http://localhost:8080/user/getUserById/1
// user 与password参数被设置在了请求url当中,里面的值会在参数传递的时候替换掉。
  @RequestMapping("/hello3/{user}/{password}")
    public String hello3(@PathVariable("user") String username,@PathVariable String password){
        String name= username;
        return name;
    }

总结

传统的url请求路径,容易区分出请求类型,容易获取到参数,二REST风格的url,去掉了参数配置的格式,全部通过url路径的形式方式,把url中的?& = 这些符合去掉。使url路径更加简洁清晰。

11.12 springmvc 类型转换

通过springmvc的类型转换机制,使用注解,控制器方法就能获取到对应的参数类型。

内置基本数据转换类型

在这里插入图片描述
数组 集合 转换
在这里插入图片描述

自定义类型转换,实现其中一个接口,并配置到springmvc当中。
在这里插入图片描述

总结

Spring MVC 对于基本类型(例如 int、long、float、double、boolean 以及 char 等)已经做好了基本类型转换。因此,通常情况下 Spring MVC 提供的这些类型转换器可以满足开发人员大多数的类型转换需求的。

11.13 springmvc 格式化器

将时间或者数字类型按照指定的格式进行显示,就需要用到格式化器。
在 Spring MVC 的配置文件中配置一个 mvc:annotation-driven 标签,Spring MVC 在启动时就会自动初始化一个 FormattingConversionServiceFactoryBean 类型的实例:ConversionService。

也就是说,我们只要在 Spring MVC 配置文件中配置了 mvc:annotation-driven 标签,就可以直接在 Spring MVC 项目中使用 @NumberFormat 注解和 @DateTimeFormat 注解,对 Number 类型和 Date 类型数据进行格式化转换。
在这里插入图片描述
日期格式化
@DateTimeFormat 注解可对 java.util.Date、java.util.Calendar、java.long.Long 等时间类型的数据进行标注,以实现对日期类型的数据进行格式化处理。

@DateTimeFormat 注解主要包含以下 3 个属性。

在这里插入图片描述
数值格式化

@NumberFormat 注解可以用来格式化任何数字基本类型(如 int、long 等)或 java.lang.Number 类型的实例(如 BigDecimal、Integer 等)。

@NumberFormat 注解拥有两个互斥的属性,如下表。
在这里插入图片描述

11.14 springmvc 转换Json格式

如果处理好的数据不需要视图,则直接使用json返回到客户端,比如 Ajax请求。

json
JSON 支持 2 种数据结构,它们分别是对象结构和数组结构。
其中,key 必须为 String 类型,value 可以是 String、Number、Object、Array 等数据类型。

对象结构

{
    key1:value1,
    key2:value2,
    ...
}

{
    "pname":"张三",
    "password":"123456",
    "page":40
}

数组
JSON 的数组结构以“[”开始、以“]”结束,中间部分由 0 个或多个以英文的逗号(即“,”)分隔的值列表组成。

[
    "c语言中文网",
    123456789,
    true,
    null
]

{
    "sno":"201802228888",
    "sname":"张三",
    "hobby":[
        "篮球",
        "足球"
    ],
    "college":{
        "cname":"清华大学",
        "city":"北京",
        "code":100000
    }
}

JSON 数据转换

为了实现浏览器与控制器类之间的 JSON 数据交互,Spring MVC 提供了一个默认的 MappingJackson2HttpMessageConverter 类,来处理 JSON 格式请求和响应。通过它,我们既可以将 Java 对象转换为 JSON 数据,也可以将 JSON 数据转换为 Java 对象。

引入依赖包

        <!--导入JSON处理工具包-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
<!--            数据绑定-->
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.0</version>
        </dependency>
<!--        注解包-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.12.0</version>
        </dependency>

JSON 转换注解

注解位置说明
@ResponseBody方法上 ,或者类上该注解用于将控制器方法的返回值,直接作为响应报文的响应体响应到浏览器上。
@RequestBody方法的形参上该注解用于将请求体中的数据绑定到控制器方法的形参上。

在 Spring MVC 的配置文件中,除了配置了组件扫描和视图解析器外,我们还配置如下两个元素:
<mvc:annotation-driven /> :Spring MVC 的注解驱动,配置会自动注册 RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 两个组件,为读写 JSON 数据提供支持。
<mvc:resources /> :静态资源访问映射,用于配置静态资源的访问路径。

<mvc:resources /> 中包含两个重要的属性:location 和 mapping,关于这两个属性的说明如下表。

属性说明
location该属性用于设置需要访问的本地静态资源文件的路径。
mapping匹配静态资源全路径,其中“/**”表示文件夹及其子文文件夹下的某个具体文件。

静态资源过滤选择
这两个标签配置都可以实现静态资源的映射,我们可以根据自身的需求自行选择。

<mvc:resources /> 
 <mvc:default-servlet-handler />

11.15 springmvc拦截器

拦截器(Interceptor)是 Spring MVC 提供的一种强大的功能组件。它可以对用户请求进行拦截,并在请求进入控制器(Controller)之前,servlet之后、控制器处理完请求后、甚至是渲染视图后,执行一些指定的操作。

在 Spring MVC 中,拦截器的作用与 Servlet 中的过滤器类似,它主要用于拦截用户请求并做相应的处理,例如通过拦截器,我们可以执行权限验证、记录请求信息日志、判断用户是否已登录等操作。

Spring MVC 拦截器使用的是可插拔式的设计,如果我们需要某一拦截器,只需在配置文件中启用该拦截器即可;如果不需要这个拦截器,则只要在配置文件中取消应用该拦截器即可。

拦截器只会拦截控制器的方法,如果访问的是 jsp HTML css image js 等不会拦截。

自定义拦截器

Spring MVC 在 org.springframework.web.servlet 包中提供了一个 HandlerInterceptor 接口,该接口包含 3 个方法,如下表。
在这里插入图片描述

public class MyHandlerInterceptor implements HandlerInterceptor {

    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    @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 {

    }
}

配置拦截器

   <!--配置拦截器-->
    <mvc:interceptors>

    <!--拦截器 1-->
    <mvc:interceptor>
        <!--配置拦截器拦截的请求路径-->
        <mvc:mapping path="/**"/>
        <!--配置拦截器不需要拦截的请求路径-->
        <mvc:exclude-mapping path="/login"/>
        <mvc:exclude-mapping path="/"/>
        <!--定义在 <mvc:interceptors> 下,表示拦截器只对指定路径的请求进行拦截-->
        <bean class="com.example.Springmvc.controller.MyHandlerInterceptor"/>
    </mvc:interceptor>

    
    </mvc:interceptors>

执行流程
在这里插入图片描述
拦截器处理流程的步骤如下:
1当请求的路径与拦截器拦截的路径相匹配时,程序会先执行拦截器类(MyInterceptor)的 preHandl() 方法。若该方法返回值为 true,则继续向下执行 Controller(控制器)中的方法,否则将不再向下执行;
2 控制器方法对请求进行处理;
3 调用拦截器的 postHandl() 方法,此时我们可以对请求域中的模型(Model)数据和视图做出进一步的修改;
4 通过 DispatcherServlet 的 render() 方法对视图进行渲染;
5 调用拦截器的 afterCompletion () 方法,完成资源清理、日志记录等工作。

多个拦截器的执行流程

在程序运行期间,拦截器的执行是有一定的顺序的,该顺序与拦截器在配置文件中定义的顺序有关。
假设一个项目中包含两个不同的拦截器:Interceptor1 和 Interceptor2,它们在配置文件中定义的顺序为:Interceptor1 → Interceptor2。下面我们就通过一个拦截器流程图来描述下多个拦截器的执行流程。
在这里插入图片描述

11.16 异常处理

Spring MVC 提供了一个名为 HandlerExceptionResolver 的异常处理器接口,它可以对控制器方法执行过程中出现的各种异常进行处理。
Srping MVC 为 HandlerExceptionResolver 接口提供了多个不同的实现类,其中最常用的实现类如下。
DefaultHandlerExceptionResolver
ResponseStatusExceptionResolver
ExceptionHandlerExceptionResolver
SimpleMappingExceptionResolver

DefaultHandlerExceptionResolver

DefaultHandlerExceptionResolver 是 HandlerExceptionResolver 接口的常用实现类之一,更是 Spring MVC 提供的默认异常处理器之一,Spring MVC 默认通过它对控制器处理请求时出现的异常进行处理。
下表中列举了 Spring MVC 中一些常见异常的默认状态码。
在这里插入图片描述

ExceptionHandlerExceptionResolver

ExceptionHandlerExceptionResolver 是 HandlerExceptionResolver 接口的实现类之一,它也是 Spring MVC 提供的默认异常处理器之一。

ExceptionHandlerExceptionResolver 可以在控制器方法出现异常时,调用相应的 @ExceptionHandler 方法(即使用了 @ExceptionHandler 注解的方法)对异常进行处理。

@ExceptionHandler 注解

@ExceptionHandler 注解中包含了一个 value 属性,我们可以通过该属性来声明一个指定的异常。如果在程序运行过程中,这个 Controller 类中的方法发生了这个指定的异常,那么 ExceptionHandlerExceptionResolver 就会调用这个 @ExceptionHandler 方法对异常进行处理。

案例


    @RequestMapping("/exception")
    public String exception(){

        System.out.println(1/0);
        return "form";
    }



    @ExceptionHandler(ArithmeticException.class)
    public String error(ArithmeticException e, Model model){

        model.addAttribute("ex",e);
        return "error";

    }
<%--
 Created by IntelliJ IDEA.
 User: Administrator
 Date: 2022-12-4 0004
 Time: 20:32
 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>
出错信息:
${ex}
</body>
</html>

@ExceptionHandler 方法的优先级

根据异常的继承关系,调用继承深度最浅的异常处理方法对异常进行处理。

    @ExceptionHandler(ArithmeticException.class)  // 3
    @ExceptionHandler(RuntimeException.class)  //2
    @ExceptionHandler(Exception.class)   //1

注意 定义在某个控制器类中的 @ExceptionHandler 方法只在当前的控制器中有效,它只能处理其所在控制器类中发生的异常。

全局异常处理
我们还可以将 @ExceptionHandler 方法定义在一个使用了 @ControllerAdvice 注解的类中。使用 @ControllerAdvice 注解的类可以包含多个不同的带有 @ExceptionHandler 注解的方法,这些方法可以应用在不同控制器 中所有带有 @RequestMapping 注解的控制器方法中,实现全局异常处理。




@ControllerAdvice  //控制器增强,给控制器增加异常处理功能
public class ExceptionController {

    @ExceptionHandler  //没有属性值,表示处理所有的异常
    public String exception(Exception e, Model model){
        model.addAttribute("ex",e);
        return "error";
    }

    @ExceptionHandler(Exception.class) // 有值 表示处理指定类型的异常
    public String exception1(Exception e, Model model){
        model.addAttribute("ex",e);
        return "error";
    }
}

11.17 文件上传

编写 form 表单
当 form 表单的 enctype 属性为 multipart/form-data 时,浏览器会以二进制流的方式对表单数据进行处理,由服务端

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="photo" multiple="multiple"/>
    <input type="submit" value="上传">
</form>

标签中还增加一个 multiple 属性。该属性可以选择对个文件进行上传,即实现多文件上传功能。

<!--文件上传相关依赖-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>


文件上传的方法
MultipartFile 对象的方法
在这里插入图片描述



@Controller
public class FIleController {

    @RequestMapping(value = "/toUpload", method = RequestMethod.POST)
    @ResponseBody
    public String uploadPhoto(MultipartFile photo, HttpServletRequest request) {
        if (!photo.isEmpty()) {
            // 文件存放目录
            String catalog = "/fileUpload/";
            System.out.println(catalog);
            // 文件存放路径
            String path = request.getServletContext().getRealPath(catalog);
            // 文件存放名称
            String name = String.valueOf(new Date().getTime() + "_" + photo.getOriginalFilename());
            File destFile = new File(path, name);
            // 文件保存操作
            try {
                photo.transferTo(destFile);
            } catch (IllegalStateException | IOException e) {
                e.printStackTrace();
            }
            // 文件访问地址
            String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + catalog + name;
            // 返回文件地址
            return "success, the file url is : " + url;
        } else {
            return "error!";
        }
    }
}

11.18 注解配置

  1. 使用初始化类代替 web.xml

Spring 提供了一个 DispatcherServelt 的快速配置类 org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer,它就是 WebApplicationInitializer 的实现类之一 ,其常用方法如下表。

在这里插入图片描述

  1. 使用配置类代替 Spring 的配置文件

使用 @Configuration与@Bean 注解的 Java 类(通常被称为“配置类”),来代替 Spring 的配置文件。

  1. 使用配置类代替 Spring MVC 的配置文件

我们知道,Spring MVC 的配置项繁多,例如组件扫描、视图解析器、拦截器、类型转换器、异常解析器、文件上传解析器等。它们在配置类中的配置方式也不尽相同,大致可以被分为 3 种方式:
实现 WebMvcConfigurer 接口
使用 @EnableWebMvc、@ComponentScan 等注解
使用 @Bean 注解

WebMvcConfigurer 是一个基于 Java 8 的接口,该接口定义了许多与 Spring MVC 相关的方法,其中大部分方法都是 default 类型的且都是空实现。因此我们只需要定义一个配置类实现 WebMvcConfigurer 接口,并重写相应的方法便可以实现对 Spring MVC 的配置。

在这里插入图片描述

示例

springioc 配置类

@Configuration
public class SpringIOC {


    
    @Bean
    public HelloController helloController(){
        return  new HelloController();
    }
}

springmvc 配置类

@Configuration
@ComponentScan
@EnableWebMvc // 开启spring注解支持  等同  <mvc:annotation-driven/>
public class WebMVC implements WebMvcConfigurer {

    /**
     * 开启静态资源过滤
     * 等同     <mvc:default-servlet-handler/>
     * @param configurer
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /**
     * 添加拦截器
     * 等同      <mvc:interceptors/> 标签
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new MyHandlerInterceptor()).addPathPatterns("/he").excludePathPatterns("/hello");
    }

    /**
     * 视图控制器
     * 等同     <mvc:view-controller path="/upload" view-name="file"/>
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

        registry.addViewController("/upload").setViewName("file");
    }

    /**
     * 视图解析器
     *
     * @return
     */
    @Bean
    public InternalResourceViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

web.xml 配置类

//初始化类,代替 web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {

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

    //设置 Spring MVC 的配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebMVC.class};
    }

    //为 DispatcherServlet 指定映射规则,相当于 web.xml 中配置的 url-pattern
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    //添加过滤器
    @Override
    protected Filter[] getServletFilters() {

        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        encodingFilter.setForceRequestEncoding(true);
        encodingFilter.setForceResponseEncoding(true);

        HiddenHttpMethodFilter httpMethodFilter = new HiddenHttpMethodFilter();
        return  new Filter[] {encodingFilter,httpMethodFilter};
    }
}


测试

注释掉 web.xml 文件代码,重启Tomcat访问,访问路径成功。

11.19 springmvc配置文件

11.19.1 xml配置

pom依赖

<?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.example</groupId>
    <artifactId>Springmvc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>Springmvc</name>
<!--    打包方式war-->
    <packaging>war</packaging>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <junit.version>5.7.0</junit.version>
    </properties>

    <dependencies>
<!--        javaweb servlet 的核心依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
<!--        单元测试5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

<!--        springmvc 依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.20</version>
        </dependency>

        <!--导入JSON处理工具包  给springmvc提供返回json格式支持-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
<!--            数据绑定-->
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.0</version>
        </dependency>
<!--        注解包-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.12.0</version>
        </dependency>

        <!--文件上传相关依赖-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

    </dependencies>

    <build>
        <!--资源拷贝-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.conf</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.conf</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">


<!--    配置springmvc的监听器 用于监听spring容器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<!--    配置上下文-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-ioc.xml</param-value>
    </context-param>


<!--    dispatcherServlet是springmvc的核心servlet,它负责接收客户端发送来的所有请求-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        配置 dispatcherServlet 的初始化参数 contextConfigLocation 参数名称是固定的-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>


<!--        servlet 的加载级别,数字越小级别越大,0 为按需加载-->
        <load-on-startup>1</load-on-startup>
    </servlet>

<!--    dispatcherServlet的请求映射路径-->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
<!--      /  拦截所有请求,不包括 .jsp
          /* 拦截所有请求,包括 .jsp  使用 会报404错误
-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    <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>
        <!--强制Request使用字符集encoding-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--强制Response使用字符集encoding-->
        <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>
</web-app>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns: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">

<!--    配置springmvc 扫描路径,这里只扫描 控制器 controller的包-->
    <context:component-scan base-package="com.example.Springmvc.controller"/>

<!--    开启mvc注解  使@RequestMapping 生效-->
        <mvc:annotation-driven/>

<!--让springmvc 过滤静态资源-->
    <mvc:default-servlet-handler/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="1"/>

        <property name="prefix" value="/WEB-INF/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--配置拦截器-->
    <mvc:interceptors>

    <!--拦截器 1-->
    <mvc:interceptor>
        <!--配置拦截器拦截的请求路径-->
        <mvc:mapping path="/**"/>
        <!--配置拦截器不需要拦截的请求路径-->
        <mvc:exclude-mapping path="/login"/>
        <mvc:exclude-mapping path="/"/>
        <!--定义在 <mvc:interceptors> 下,表示拦截器只对指定路径的请求进行拦截-->
        <bean class="com.example.Springmvc.controller.MyHandlerInterceptor"/>
    </mvc:interceptor>


    </mvc:interceptors>

<!--    视图标签-->
    <mvc:view-controller path="/form" view-name="form"/>
    <mvc:view-controller path="/upload" view-name="file"/>

    <!--配置文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="maxUploadSize" value="1024000"/>
    </bean>

</beans>

spring-ioc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns: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
        ">

<!--    如果不开启注解方式配置ioc,则在该文件定义bean对象-->

<!--    开启组件扫描-->
    <context:component-scan base-package="com.example.Springmvc">
<!--        排除控制器@Controller组件不扫描-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

</beans>

11.19.2 注解配置

pom

<?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.example</groupId>
    <artifactId>Springmvc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>Springmvc</name>
<!--    打包方式war-->
    <packaging>war</packaging>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <junit.version>5.7.0</junit.version>
    </properties>

    <dependencies>
<!--        javaweb servlet 的核心依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
<!--        单元测试5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

<!--        springmvc 依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.20</version>
        </dependency>

        <!--导入JSON处理工具包  给springmvc提供返回json格式支持-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
<!--            数据绑定-->
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.0</version>
        </dependency>
<!--        注解包-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.12.0</version>
        </dependency>

        <!--文件上传相关依赖-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

    </dependencies>


    <build>
        <!--资源拷贝-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.conf</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.conf</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

</project>

配置类 替换 web.xml


//初始化类,代替 web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {

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

    //设置 Spring MVC 的配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebMVC.class};
    }

    //为 DispatcherServlet 指定映射规则,相当于 web.xml 中配置的 url-pattern
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};
    }

    //添加过滤器
    @Override
    protected Filter[] getServletFilters() {

        CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
        encodingFilter.setEncoding("UTF-8");
        encodingFilter.setForceRequestEncoding(true);
        encodingFilter.setForceResponseEncoding(true);

        HiddenHttpMethodFilter httpMethodFilter = new HiddenHttpMethodFilter();
        return  new Filter[] {encodingFilter,httpMethodFilter};
    }
}

配置类 替换 springmvc.xml


@Configuration
@ComponentScan
@EnableWebMvc // 开启spring注解支持  等同  <mvc:annotation-driven/>
public class WebMVC implements WebMvcConfigurer {

    /**
     * 开启静态资源过滤
     * 等同     <mvc:default-servlet-handler/>
     * @param configurer
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /**
     * 添加拦截器
     * 等同      <mvc:interceptors/> 标签
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new MyHandlerInterceptor()).addPathPatterns("/he").excludePathPatterns("/hello");
    }

    /**
     * 视图控制器
     * 等同     <mvc:view-controller path="/upload" view-name="file"/>
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

        registry.addViewController("/upload").setViewName("file");
    }

    /**
     * 视图解析器
     *
     * @return
     */
    @Bean
    public InternalResourceViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

配置类 替换 springioc.xml


@Configuration
public class SpringIOC {



    @Bean
    public HelloController helloController(){
        return  new HelloController();
    }
}


11.20 总结

springmvc的由来是吸收了javaee中的servlet的技术,并把它与自身的技术框架相融合。
springmvc最核心的是DispatcherServlet这个类,它负责springmvc项目的所有请求,所有的请求都会经过它,并通过它调用相应的处理器进行处理。

springmvc的优点

** 与javaweb的servlet相比**

1 springmvc的一个控制器类,能处理多个请求(增删改查);
2 与ioc、aop无缝融合,脱离复杂类关系的管理烦恼;
3 支持RESTful风格的URL路径;
4 支持不同类型的数据格式返回,如 返回json格式;
5 视图与模型解耦;
6 支持自定义异常处理;
7 提供请求参数类型自动转换并绑定到控制器方法参数上;
8 内部拦截器对控制器方法进行预处理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值