0%

SpringMVC注解式开发

  • SpringMVC注解式开发
    • @RequestMapping注解详解
    • 五种数据提交方式
    • 处理器方法的返回值
    • SpringMVC的四种跳转方式
    • ……

二、SpringMVC注解式开发

  • 所谓 SpringMVC 的注解式开发是指,在代码中通过对类与方法的注解,便可完成处理器在 SpringMVC 容器的注册。
    • 注解式开发是重点。

2.1 ★@RequestMapping注解详解

  • 通过 @RequestMapping 注解可以定义处理器对于请求的映射规则。

    value 属性值常以 “/” 开始,@RequestMappingvalue 属性用于对应匹配请求的 URI

    • 一个 @Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的 @RequestMappingvalue 属性中。

      但若这些请求具有相同的 URI 部分,则这些 URI 相同的部分可以被抽取到注解在类之上的 @RequestMappingvalue 属性中。此时这个 URI 表示模块(相当于包的作用)的名称。

    • 此注解就是用来映射服务器访问的路径的

  • @RequestMapping 注解可以注解在方法上,也可以注解在类上,但意义是不同的。

    • **用在方法上,是为此方法注册一个可以访问的名称(路径)**。

    • 用在类上,相当于是“包名”的作用,用于区分不同类中相同的 action 的名称。例如:

      • 有两个 ActionHelloActionHiAction

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        package com.f.springmvc.controller;

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

        /**
        * @author fzy
        * @date 2024/2/4 14:42
        */
        @Controller // 由Spring来创建该类的实例对象
        @RequestMapping("/hello")
        public class HelloAction {
        @RequestMapping("/demo.action")
        public String hello() {
        System.out.println("访问服务器hello成功!");
        return "main"; // 这样可以直接跳到 /admin/main.jsp 页面上
        }
        }
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        package com.f.springmvc.controller;

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

        /**
        * @author fzy
        * @date 2024/2/4 16:21
        */
        @Controller
        @RequestMapping("/hi")
        public class HiAction {
        @RequestMapping("/demo.action")
        public String hi() {
        System.out.println("访问服务器hi成功!");
        return "main";
        }
        }

        它们的方法的映射路径都是 /demo.action,为了区分访问的前者的 action 还是后者的 action,在这两个 Action 类上添加 @RequestMapping 注解,用以区分。

        • 相应的,index.jsp 文件也要进行一些修改:

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          <%--index.jsp文件--%>
          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <html>
          <head>
          <title>index</title>
          </head>
          <body>
          <a href="${pageContext.request.contextPath}/hello/demo.action">访问hello服务器</a>
          <br/>
          <a href="${pageContext.request.contextPath}/hi/demo.action">访问hi服务器</a>
          </body>
          </html>
  • 对于 @RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交方式进行限制,即只有满足该 method 属性指定的提交方式的请求,才会执行该被注解方法。

    • method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GETRequestMethod.POST,分别表示请求提交方式的匹配规则为 GET 请求与 POST 请求。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      package com.f.springmvc.controller;

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

      /**
      * @author fzy
      * @date 2024/2/4 16:55
      */
      @Controller
      public class ReqAction {
      @RequestMapping(value = "/req.action", method = RequestMethod.GET)
      public String doGet() {
      System.out.println("get请求处理");
      return "main";
      }

      @RequestMapping(value = "/req.action", method = RequestMethod.POST)
      public String doPost() {
      System.out.println("post请求处理");
      return "main";
      }
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      <%--index.jsp文件--%>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
      <title>index</title>
      </head>
      <body>
      <h1>get请求</h1>
      <form action="${pageContext.request.contextPath}/req.action" method="get">
      用户名:<input name="getUsername" value="">
      密 码:<input name="getPassword" value="">
      <input type="submit" value="get请求提交">
      </form>
      <br/>
      <h1>post请求</h1>
      <form action="${pageContext.request.contextPath}/req.action" method="post">
      用户名:<input name="postUsername" value="">
      密 码:<input name="postPassword" value="">
      <input type="submit" value="post请求提交">
      </form>
      </body>
      </html>
      • 可以发现,即使 get 请求和 post 请求的请求路径一样,@RequestMapping 也能根据不同的请求类型找到对应的方法,对请求进行处理。

2.2 五种数据提交方式

  • 这里对应 1.3 小节 SpringMVC优化的方向 中的 “数据提交的优化”。

2.2.1 单个提交数据

  • 在方法中声明一个和表单提交的参数名称相同的参数,由框架按照名称直接注入。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
    * <form action="${pageContext.request.contextPath}/one.action" method="post">
    * 姓名:<input name="name" value="">
    * 年龄:<input name="age" value="">
    * <input type="submit" value="提交">
    * </form>
    */
    @RequestMapping(value = "/one.action", method = RequestMethod.POST)
    public String one(String name, int age) { // 只需保证参数名和前端对应的名称一致即可
    System.out.println("姓名为:" + name);
    System.out.println("年龄为:" + age);
    return "main";
    }

2.2.2 ★对象封装提交数据

  • 在方法中声明一个自定义的实体类参数,框架调用实体类中相应的 setter 方法注入属性值,需要保证实体类中成员变量的名称与提交请求的 name 属性值一致。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    /**
    * <form action="${pageContext.request.contextPath}/two.action" method="post">
    * 姓名:<input name="uname" value="">
    * 年龄:<input name="uage" value="">
    * <input type="submit" value="提交">
    * </form>
    *
    * public class User {
    * private String uname;
    * private int uage;
    * ...
    * }
    */
    @RequestMapping(value = "/two.action", method = RequestMethod.POST)
    public String two(User user) { // 需要保证类中的字段名和前端对应的名称一致
    System.out.println(user);
    return "main";
    }
    • 在提交请求中,保证请求参数的名称与实体类中成员变量的名称一致,则可以自动创建对象,则可以自动提交数据,自动类型转换,自动封装数据到对象中。

2.2.3 动态占位符提交

  • 使用框架提供的一个注解 @PathVariable,将请求 url 中的值作为参数进行提取,只能是超链接。是 restful 风格下的数据提取方式。

    • restful 是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
    * <a href="${pageContext.request.contextPath}/three/张三/22.action">动态占位符提交</a>
    */
    @RequestMapping(value = "/three/{xxx}/{yyy}.action")
    public String three(
    @PathVariable("xxx")
    String aaa, // 类似于起别名
    @PathVariable("yyy")
    int bbb) { // 前端一杠一值,后端一杠一大括号
    System.out.println("姓名为:" + aaa);
    System.out.println("年龄为:" + bbb);
    return "main";
    }
    • 仅限于超链接或地址拦提交数据。它是“前端一杠一值,后端一杠一大括号”,使用注解 @PathVariable 来解析。

2.2.4 ★映射名称不一致

  • 提交请求参数与 action 方法的形参的名称不一致,可以使用注解 @RequestParam 来解析。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
    * <form action="${pageContext.request.contextPath}/four.action" method="post">
    * 姓名:<input name="uname" value="">
    * 年龄:<input name="uage" value="">
    * <input type="submit" value="提交">
    * </form>
    */
    @RequestMapping(value = "/four.action", method = RequestMethod.POST)
    public String four(
    @RequestParam("uname")
    String name,
    @RequestParam("uage")
    int age) {
    System.out.println("姓名为:" + name);
    System.out.println("年龄为:" + age);
    return "main";
    }
    • @RequestParam 专门用于解决前端请求参数和后端方法的形参名称不一致的问题。

2.2.5 手工提取数据

  • 在方法参数中声明一个 request 对象,使用 requestgetParameter() 获取表单提交的数据,这样得到的数据还要手工进行数据类型的转换。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
    * <form action="${pageContext.request.contextPath}/five.action" method="post">
    * 姓名:<input name="uname" value="">
    * 年龄:<input name="uage" value="">
    * <input type="submit" value="提交">
    * </form>
    */
    @RequestMapping(value = "/five.action", method = RequestMethod.POST)
    public String five(HttpServletRequest request) {
    System.out.println("姓名为:" + request.getParameter("uname"));
    System.out.println("年龄为:" + Integer.parseInt(request.getParameter("uage")));
    return "main";
    }

2.3 处理器方法的返回值

  • 这里对应 1.3 小节 SpringMVC优化的方向 中的 “携带数据优化” 之一。

2.3.1 String

  • 客户端资源的地址,可以自动拼接前缀和后缀,也可以屏蔽自动拼接字符串,指定返回的路径。
  • 处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址。

2.3.2 Object

  • 返回 json 格式的对象,自动将对象或集合转为 json
    • 使用 jackson 工具进行转换,必须要添加 jackson 依赖。一般用于 ajax 请求。
  • 处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,自定义对象,MapList 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。
    • 返回对象需要使用 @ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。
  • Ajax 请求多用于 Object 返回值类型。由于转换器底层使用了 Jackson 转换方式将对象转换为 JSON 数据,所以需要添加 Jackson 的相关依赖。

2.3.3 void

  • 无返回值,一般用于 ajax 请求。
  • 对于处理器方法返回 void 的应用场景,应用在 AJAX 响应处理。若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void

2.3.4 基本数据类型

  • 用于 ajax 请求。

2.3.5 ModelAndView

  • 若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中需要定义 ModelAndView 对象。
  • 在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适。
  • 较少使用。

2.4 ★SpringMVC的四种跳转方式

  • 默认的跳转是请求转发,直接跳转到 jsp 页面展示。
    • 还可以使用框架提供的关键字 redirect:,进行一个重定向操作,包括重定向页面和重定向 action
    • 还可以使用框架提供的关键字 forward:,进行服务器内部转发操作,包括转发页面和转发 action
      • 当使用 redirect:forward: 关键字时,视图解析器中前缀后缀的拼接就自动无效了

2.4.1 请求转发页面

2.4.2 请求转发action

2.4.3 重定向页面

2.4.4 重定向action

  • 本质还是两种跳转:请求转发和重定向,衍生出四种是:

    1. 请求转发页面

      1
      2
      3
      4
      5
      @RequestMapping("/one.action")
      public String one() {
      System.out.println("默认为请求转发页面...");
      return "main"; // 默认是请求转发,使用视图解析器拼接前缀后缀,然后进行页面跳转
      }
      • 也可以使用 "forward:/admin/main.jsp" 来请求转发页面。那就不局限于视图解析器中配置的前缀后缀,而是可以任意转发页面了。
    2. 请求转发 action

      1
      2
      3
      4
      5
      6
      @RequestMapping("/two.action")
      public String two() {
      System.out.println("请求转发action...");
      // 使用"forward:"可以屏蔽视图解析器前缀后缀的拼接
      return "forward:/other.action"; // 请求转发action
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      package com.f.springmvc.controller;

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

      /**
      * @author fzy
      * @date 2024/2/5 17:25
      */
      @Controller
      public class OtherAction {
      @RequestMapping("/other.action")
      public String other() {
      System.out.println("跳转到了/other.action");
      return "main";
      }
      }
    3. 重定向页面

      1
      2
      3
      4
      5
      6
      @RequestMapping("/three.action")
      public String three() {
      System.out.println("重定向页面...");
      // 使用"redirect:"可以屏蔽视图解析器前缀后缀的拼接
      return "redirect:/admin/main.jsp"; // 重定向页面
      }
    4. 重定向 action

      1
      2
      3
      4
      5
      6
      @RequestMapping("/four.action")
      public String four() {
      System.out.println("重定向action...");
      // 使用"redirect:"可以屏蔽视图解析器前缀后缀的拼接
      return "redirect:/other.action"; // 重定向action
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      package com.f.springmvc.controller;

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

      /**
      * @author fzy
      * @date 2024/2/5 17:25
      */
      @Controller
      public class OtherAction {
      @RequestMapping("/other.action")
      public String other() {
      System.out.println("跳转到了/other.action");
      return "main";
      }
      }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <%--index.jsp文件--%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>index</title>
    </head>
    <body>
    <h1>SpringMVC的四种跳转方式</h1>
    <a href="${pageContext.request.contextPath}/one.action">1.请求转发页面(默认)</a>
    <br/>
    <a href="${pageContext.request.contextPath}/two.action">2.请求转发action</a>
    <br/>
    <a href="${pageContext.request.contextPath}/three.action">3.重定向页面</a>
    <br/>
    <a href="${pageContext.request.contextPath}/four.action">4.重定向action</a>
    </body>
    </html>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <%--main.jsp文件--%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>main</title>
    </head>
    <body>
    <h1>main</h1>
    </body>
    </html>

2.5 SpringMVC支持的默认参数类型

  • 不需要去创建,直接拿来使用即可。

2.5.1 HttpServletRequest

2.5.2 HttpServletResponse

2.5.3 HttpSession

2.5.4 Model

2.5.5 Map

2.5.6 ModelMap

  • 注意MapModelModelMaprequest 一样,都使用请求作用域进行数据传递。所以服务器端的跳转必须是请求转发。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<%--index.jsp文件--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>index</title>
</head>
<body>
<h1>SpringMVC的四种跳转方式</h1>
<a href="${pageContext.request.contextPath}/one.action">1.请求转发页面(默认)</a>
<br/>
<a href="${pageContext.request.contextPath}/two.action">2.请求转发action</a>
<br/>
<a href="${pageContext.request.contextPath}/three.action">3.重定向页面</a>
<br/>
<a href="${pageContext.request.contextPath}/four.action">4.重定向action</a>
<br/>
<br/>
<br/>
<a href="${pageContext.request.contextPath}/data.action?name=lili">访问服务器,携带数据跳转</a>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.f.springmvc.controller;

import com.f.springmvc.pojo.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

/**
* @author fzy
* @date 2024/2/5 19:44
*/
@Controller
public class DataAction {
@RequestMapping("/data.action")
public String data(
// SpringMVC支持的默认参数类型
HttpServletRequest request,
HttpServletResponse response,
HttpSession session,
Model model,
Map map,
ModelMap modelMap) {
// 从服务器端携带的数据
User user = new User("张三", 22);
// 传递数据
request.setAttribute("requestUser", user);
session.setAttribute("sessionUser", user);
model.addAttribute("modelUser", user);
map.put("mapUser", user);
modelMap.addAttribute("modelMapUser", user);
return "main";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<%--main.jsp文件--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>main</title>
</head>
<body>
<h1>main</h1>
<%--
request.setAttribute("requestUser", user);
session.setAttribute("sessionUser", user);
model.addAttribute("modelUser", user);
map.put("mapUser", user);
modelMap.addAttribute("modelMapUser", user);
--%>
requestUser:${requestUser}<br/>
sessionUser:${sessionUser}<br/>
modelUser:${modelUser}<br/>
mapUser:${mapUser}<br/>
modelMapUser:${modelMapUser}<br/>
从index.jsp页面得到的数据:${param.name}<br/>
</body>
</html>

2.6 日期处理

2.6.1 日期的提交处理

单个日期处理
  • 要使用注解 @DateTimeFormat,此注解必须搭配 springmvc.xml 文件中的 <mvc:annotationdriven标签>,该标签用于启动注解驱动。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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">
    <context:component-scan base-package="com.f.springmvc.controller"/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/admin/"/>
    <property name="suffix" value=".jsp"/>
    </bean>
    <!--启用注解驱动-->
    <mvc:annotation-driven/>
    </beans>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <%--index.jsp文件--%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>index</title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath}/mydate.action">
    日期:<input type="date" name="mydate">
    <br/>
    <input type="submit" value="提交">
    </form>
    </body>
    </html>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.f.springmvc.controller;

    import org.springframework.format.annotation.DateTimeFormat;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;

    import java.util.Date;

    /**
    * @author fzy
    * @date 2024/2/5 20:22
    */
    @Controller
    public class MyDateAction {
    @RequestMapping("/mydate.action")
    public String myDate(
    @DateTimeFormat(pattern = "yyyy-MM-dd") // 使用DateTimeFormat注解
    @RequestParam("mydate")
    Date mydate) {
    System.out.println(mydate);
    return "main";
    }
    }
类中全局日期处理
  • 上面那种解决方案要在每个使用日期类型的地方都去添加 @DateTimeFormat 注解,比较麻烦,我们可以使用 @InitBinder 注解来进行类中统一日期类型的处理。

    • @InitBinder 注解注册日期类型,用来解析本类中所有的日期类型,自动转换。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      package com.f.springmvc.controller;

      import org.springframework.beans.propertyeditors.CustomDateEditor;
      import org.springframework.format.annotation.DateTimeFormat;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.WebDataBinder;
      import org.springframework.web.bind.annotation.InitBinder;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;

      import java.text.SimpleDateFormat;
      import java.util.Date;

      /**
      * @author fzy
      * @date 2024/2/5 20:22
      */
      @Controller
      public class MyDateAction {
      // 注册一个全局的日期处理注解
      @InitBinder
      public void initBinder(WebDataBinder binder) {
      // 注册一个自定义的转换器
      binder.registerCustomEditor(Date.class, new CustomDateEditor(
      new SimpleDateFormat("yyyy-MM-dd"), true
      ));
      }

      @RequestMapping("/mydate.action")
      public String myDate(
      @RequestParam("mydate")
      Date mydate) {
      System.out.println(mydate);
      return "main";
      }
      }
      • 用这种方法,甚至不需要 <mvc:annotation-driven/> 了。

2.6.2 日期的显示处理

  • 要在页面上显示好看的日期:

    • 如果是单个日期对象,可以在处理器中用 SimpleDateFormat 将日期直接转为好看的格式化的字符串,然后转发给前端进行显示。
    • 如果是实体类对象的成员变量,并且是日期类型,而且是将实体类对象转发给前端,则必须使用 JSTL 标签库才能显示好看的日期。
  • 具体代码看别人笔记吧,主要是前端来做。

    [记录学习]自学动力节点荣姐SpringMVC5笔记_动力节点springmvc笔记-CSDN博客

2.7 <mvc:annotation-driven/>标签的使用

  • <mvc:annotation-driven/> 会自动注册两个 bean,分别为 DefaultAnnotationHandlerMappingAnnotationMethodHandlerAdapter。是 SpringMVC 为 @Controller 分发请求所必须的。除了注册了这两个 bean以外,还提供了很多支持。
    1. 支持使用 ConversionService 实例对表单参数进行类型转换。
    2. 支持使用 @NumberFormat@DateTimeFormat 注解完成数据类型的格式化。
    3. 支持使用 @RequestBody@ResponseBody 注解。
    4. 静态资源的分流也使用这个标签。

2.8 ★访问WEB-INF目录下的资源

  • WEB-INF 目录下的动态资源,不能直接访问,只能通过请求转发的方式进行访问。

    • 重定向无法访问动态资源。
  • 很多企业会将动态资源放在 WEB-INF 目录下,这样可以保证资源的安全性。在 WEB-INF 目录下的动态资源不可以直接访问,必须要通过请求转发的方式进行访问。这样避免了通过地址栏直接对资源进行访问。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <%--index.jsp文件--%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>index</title>
    </head>
    <body>
    <a href="${pageContext.request.contextPath}/access.action">访问WEB-INF目录下的资源</a>
    </body>
    </html>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package com.f.springmvc.controller;

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

    /**
    * @author fzy
    * @date 2024/2/5 22:14
    */
    @Controller
    public class AccessAction {
    @RequestMapping("/access.action")
    public String access() {
    System.out.println("开始访问WEB-INF目录下的资源...");
    // 通过请求转发的方式访问WEB-INF目录下的资源
    return "forward:/WEB-INF/jsp/main.jsp";
    }
    }

2.9 去掉action后缀

  • 在对 DispatcherServlet<url-pattern> 进行配置时,如果是 / 的配置,则表示拦截所有请求,但放行静态资源。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
    version="6.0">
    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    </servlet>
    <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    </web-app>
    • 在将 *.action 更改为 / 以后,DispatcherServlet 会拦截所有请求(放行静态资源),而不仅仅只拦截 .action 结尾的请求。
      • 那以后请求可以不用再带 .action 后缀了。
  • 另:/*/ 的区别:

    • /* 拦截所有请求(包括 .jsp)。
    • / 拦截所有请求,但放行静态资源。
      • 如果发现是静态资源的请求,就将该请求转由 Web 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet 继续处理。
---------------The End---------------