Spring MVC:轻量级MVC框架

一、Sping MVC的介绍

1. 使用Front(前端)设计模式

        Front(前端)设计模式就是有一个前端(不是前端专业那个前端,是最前面的意思)统一入口,在统一入口根据请求url调用自己的编写的普通方法。

这样带来的好处是:

  • 只需要在一个Servlet中编写获取容器Bean的代码,减少了代码冗余。

  • 不需要为每个控制器都创建一个类,而是可以在一个普通Java类中提供普通实例方法代表以前servlet中的service方法。

  • 因为可以自己编写普通Java类,这类可以放入到Spring容器中,注入Service更方便。

  • 同时因为是自己编写的Java,所以可以进行一些封装,对其他操作进行简化。

2. Spring MVC介绍

Spring MVC 虽然在平时认为是一个独立的框架。但其本质为Spring 框架的一个扩展 ,可以认为Spring MVC属于Spring Framework的二级子项目。Spring MVC是基于Front设计模式;EmpController在Spring MVC称为控制器类(Handler),里面的方法称为:控制单元(HandlerMethod)

M:在模型层包含:数据校验。

V:在视图层包含:国际化、标签库。

C:在控制层包含的功能就更多了:转发重定向、参数、拦截器、作用域等。

3. Spring中的父子容器问题

因为Spring MVC属于Spring的子框架,所以Spring MVC中可以使用Spring框架的全部内容。  

Spring MVC子容器可以调用Spring 父容器的全部内容。但是Spring父容器不能调用Spring MVC子容器内容。  

二、Spring MVC环境搭建

1. 创建项目并添加依赖

<?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</groupId>
    <artifactId>springmvc1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <!-- 依赖了Spring框架核心功能的5个依赖以及Spring整合Web的依赖spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.16</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <path>/bjsxt</path>
                    <port>8081</port>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. 创建Spring MVC配置文件

在src/main/resources中新建Spring MVC框架配置文件springmvc.xml。这个文件的名称是随意的,只要和web.xml中配置对应上就可以。  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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
        https://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">
    <!-- 扫描控制器类,千万不要把service等扫描进来,也千万不要在Spring配置文件扫描控制器类所在包 -->
    <context:component-scan base-package="com.bjsxt.controller"></context:component-scan>
    <!-- 让Spring MVC的注解生效 不要引错xsd-->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

3. 编写web.xml内容

web.xml的配置是为了让前端控制器DispatcherServlet生效。并且加载Spring MVC的配置文件。  

<?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">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- 参数名称必须叫做:contextConfigLocation。单词和大小写错误都导致配置文件无法正确加载 -->
            <param-name>contextConfigLocation</param-name>
			<!-- springmvc.xml 名称自定义,只要和后面创建的文件名称对应就可以了。 -->
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- Tomcat启动立即加载Servlet,而不是等到访问Servlet才去实例化DispatcherServlet -->
        <!-- 配置上的效果:Tomcat启动立即加载Spring MVC框架的配置文件-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- /表示除了.jsp结尾的uri,其他的uri都会触发DispatcherServlet。此处前往不要写成 /* -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

4. 创建控制器类

Spring MVC自定义控制器类都是以Controller结尾。

这些类都是放在controller的包中。

控制单元方法的访问权限修饰符没有强制要求,但是多写成public的。

控制单元的方法名没有要求,只要满足Java方法名定义要求就可以。

@Controller// 放入到Spring MVC容器中
public class FirstController {
    /*
     * 官方标准写法:
     *      返回值是ModelAndView,对象中存储跳转资源路径及作用域值
     */
    // 当前方法的映射路径
    @RequestMapping("/first")
    public ModelAndView test1(){
        ModelAndView modelAndView = new ModelAndView("first.jsp");
        return modelAndView;
    }
    /*
     * 简化写法(平时使用的方式)
     *      返回值是String,表示跳转的资源路径
     */
    @RequestMapping("/first2")
    public String test2(){
        return "first.jsp";
    }
}

三、@RequestMapping注解

@RequestMapping注解可以写在控制器类上,也可以写在控制单元方法上。  

如果写在类上,表示当前类所有控制单元的映射路径,都以指定路径开头。

如果写在方法上,表示当前方法的映射路径。最终访问这个控制单元的映射路径为:类上@RequestMapping映射路径+方法上@RequestMapping映射路径。

1. 所有属性总览

2. value属性

 value:定义映射路径。URL中出现指定映射路径时会执行当前控制单元。支持一个方法多个映射路径。value属性名可以省略不写,且Java的注解中,如果属性是数组类型,且取值只有一个时,{}可以省略不写。所以一共有四种写法。

取值前面的/表示映射到项目根目录,可以省略不写,但是从规范上建议写上。  

@RequestMapping("/first3")
public String first3(){
    return "first.jsp";
}
@RequestMapping({"/first4","first5"})
public String first4(){
    return "first.jsp";
}

3. name属性

name:给控制单元定义一个名称。可以理解name是控制单元的注释。  

@RequestMapping(value = "/testName",name = "测试下name属性,给程序员看的")
public String testName(){
    return "first.jsp";
}

4. path属性

path属性和value属性使用方式是相同的,都是设置控制单元的映射路径。  

@RequestMapping(path = "/testPath")
public String testPath(){
    return "first.jsp";
}

5. method属性

method属性类型是RequestMethod[],RequestMethod是枚举类型,支持HTTP协议中绝大多数请求类型。  

 

 当设置了method属性后,表示只有指定类型请求方式才能访问这个控制单元方法,其他的请求方式访问时,响应会出现405状态码。

// 请求方式只能是DELETE和POST类型。
@RequestMapping(value = "/testMethod",method = {RequestMethod.DELETE,RequestMethod.POST})
public String testMethod(){
    return "first.jsp";
}

 简写:

@PostMapping("/first")

等效于 @RequestMapping(value = "/first",method = RequestMethod.POST)

@GetMapping("/first")

等效于 @RequestMapping(value = "/first",method = RequestMethod.GET)

@DeleteMapping("/first")

等效于 @RequestMapping(value = "/first",method = RequestMethod.DELETE)

@PutMapping("/first")

等效于 @RequestMapping(value = "/first",method = RequestMethod.PUT)

@PatchMapping("/first")

等效于 @RequestMapping(value = "/first",method = RequestMethod.PATCH)

6. params属性

 params属性类型是String[],表示请求中必须包含指定名称的请求参数。

@RequestMapping(value="/testParam",params = {"name"})
public String testParam(){
    return "first.jsp";
}

 请求中没有包含指定类型参数,响应会出现400状态码。并且明确提示在实际的请求参数中没有明确设置name属性。

7. headers属性

@RequestMapping(value="/testHeaders",headers = "aa")
public String testHeaders(){
    return "first.jsp";
}

 如果请求头中没有指定的请求头参数,浏览器会报404。

8. consumes属性

consumers表示处理请求内容(Content-Type)的类型,平时多不设置,由Spring MVC自动判断。  

9. produces属性

 produces类型是String[],作用是设置@ResponseBody注解的响应内容类型。且仅当请求头中Accept中包含的值才生效。

 produces = "text/html;charset=utf-8"解决中文乱码问题

四、映射路径

1. 映射路径介绍

 映射路径无论是在Servlet中还是在Spring MVC中,都表示:当URL中出现指定路径时会执行Servlet的方法或执行Spring MVC的控制单元。

2. 多级路径

 在Spring MVC 的映射路径也支持多层写法

3.1 多层路径中最优写法

只需要在返回值中使用绝对路径就可以减少出错的情况。

跳转时 / 表示项目根目录,也就是webapp目录的根目录。

@RequestMapping("/test/test2")
public String test2(){
    return "/first.jsp";
}

4. Ant风格的映射路径

在Spring MVC中支持Ant风格的映射路径写法。所谓的Ant风格就是支持三种特殊的符号。  

符号解释
?匹配任意单字符
*匹配0或者任意数量的字符
**匹配0或者更多数量的目录

 

使用Ant的特殊符号时,表示模糊匹配。可能出现客户端发送过来的URL能匹配上多个映射路径,这时的优先级为:

固aa1) > ?形式(aa?) > 一个*号(/*) > (/**)形式

// 优先级最高
@RequestMapping("/aa1")
public String testAnt1(){
    System.out.println("bjsxt");
    return "/first.jsp";
}
// 优先级低于bjsxt1。总长度为6,bjsxt开头,后面跟个任意内容符号
@RequestMapping("/aa?")
public String testAnt2(){
    System.out.println("bjsxt");
    return "/first.jsp";
}
// 优先级低于?。一层路径,任意内容
@RequestMapping("/*")
public String testAnt3(){
    System.out.println("11111");
    return "/first.jsp";
}
// 优先级低于*。任意层路径
@RequestMapping("/**")
public String testAnt4(){
    System.out.println("22222");
    return "/first.jsp";
}

五、Spring MVC 中的转发和重定向

1. 转发和重定向复习

 转发和重定向 都是出现在资源之间相互跳转的。

两者区别:

(1)转发为一次请求,tomcat内部跳转。重定向为多次请求,不是tomcat内部跳转。

(2)转发是一次请求,无论服务器内部转发多少次,请求对象都不变。所以转发可以共享请求域的值。同时对于客户端浏览器URL是不变的。

重定向后需要客户端重新发起请求,和重定向之前不是一个请求。所以重定向后不能获取到之前设置在请求域的值。同时客户端浏览器URL是改变的。

(3)转发只能跳转到当前项目内部资源。重定向可以跳转到外部资源。例如:从自己的项目中跳转到百度应该使用重定向。

(4)转发时资源路径如果是绝对路径,第一个 / 表示当前项目根目录。

重定向时资源路径时绝对路径,第一个 / 表示 Tomcat 的 webapps目录,即:当前项目的上层目录。

2. Spring MVC中的转发和重定向

在Spring MVC框架中,默认情况下都使用转发进行寻找资源。  

@RequestMapping("/test/test2")
public String test2(){
    return "/first.jsp";
}

 在资源路径前面添加forward: 表示转发。因为写不写forward:都是转发,所以为了代码写起来简单一些,多省略forward:

@RequestMapping("/test/test2")
public String test2(){
    return "forward:/first.jsp";
}

如果希望使用重定向跳转到其他资源,只能在资源路径最前面明确添加redirect:

3. Spring MVC转发和重定向时绝对路径

 在Spring MVC中无论是转发还是重定向,使用绝对路径时/都表示项目根目录。

六、WEB-INF目录资源

        可以把资源放入到WEB-INF目录中。因为在Java Web项目中规定:WEB-INF中资源是不允许被客户端直接访问,需要先访问控制器,通过控制器的转发来访问这些资源。这种目录结构也更加负责MVC开发模式,更能体现出控制器的作用。

 

需要提供一个控制单元方法,转发到JSP页面中。  

@RequestMapping("/showSuiyi")
public String showSuiyi(){
    return "/WEB-INF/page/suiyi.jsp";
}

分析:

        项目中所有的JSP、CSS、JavaScript、图片都放入到WEB-INF中,那所有的资源都必须先执行控制器。实现起来更加复杂了。但是从项目角度上却是更加安全了 。

七、视图解析器

1. 视图解析器和视图

         Spring MVC的控制单元 支持 ModelAndView、String 等多种类型的返回值,但无论控单元的返回值是哪种类型,Spring MVC 内部最终都会将它们封装成一个 ModelAndView 对象,它由 model(模型数据)和 view(逻辑视图名)两部分组成,所以 Spring MVC 需要借助 ViewResolver(视图解析器)将 逻辑视图名解析为真正的 View 视图对象,然后才能响应给客户端展示。     

Spring MVC 定义了ViewResolverView接口:

  1. ViewResolver 视图解析器

    视图解析器用来解析逻辑视图,将其解析成真正的视图对象。

    SpringMVC 提供了一个视图解析器的接口 ViewResolver,所有具体的视图解析器必须实现该接口。

 2.View解决数据在移交给特定视图技术之前的准备工作。视图技术不有Jsp,还有Thymeleaf,freemaker等,当我们使用不同的视图技术的时候,需要我们编写不同的视图代码来实现将数据显示给用户,SpringMVC为了解决这个问题,由ViewResolver来解析单元方法的处理结果,创建对应的View的对象,然后再调用View的实现对象来完成相关的操作。

 

2. 自定义视图解析器

@RequestMapping("/showSuiyi")
public String showSuiyi(){
    return "/WEB-INF/page/suiyi.jsp";
}

         对于这种,项目结构比较固定,页面按照一定规则放在特定位置,且返回值内容比较长时,就可以配置视图解析器。在springmvc.xml进行配置

<!--配置自定义试图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 前缀 -->
    <property name="prefix" value="/WEB-INF/page/"></property>
    <!-- 后缀 -->
    <property name="suffix" value=".jsp"></property>
</bean>

 当配置了视图解析器后,控制单元返回值就不需要写前缀和后缀的内容了,写起来更加简单。

@RequestMapping("/showSuiyi")
public String showSuiyi(){
    return "suiyi";// 由视图解析器拼接:prefix + suiyi + suffix。具体:/WEB-INF/page/ + suiyi + .jsp
}

3. 自定义视图解析器下跳转到其他控制器

如果控制单元执行完,并不希望跳转到视图,而是跳转到控制器,这时需要在返回值前面明确添加forward:或redirect: ,这样就不走视图解析器了。  

@RequestMapping("/showSuiyi3")
public String showSuiyi3(){
    return "suiyi3";// 跳转到 /WEB-INF/page/suiyi3.jsp
}
@RequestMapping("/demo")
public String demo(){
    return "forward:/showSuiyi3"; // 不走视图解析器了。跳转到/showSuiyi3控制器单元
}

八、静态资源放行

1. 静态资源放行

 Spring MVC 支持静态资源配置,当URL满足指定路径要求时不再去找控制单元,而是直接转发到特定路径中静态资源。

需要在springmvc.xml中配置静态资源放行

 

<!--配置静态资源放行-->
	<!--mapping:当URI是什么样格式时,不再执行控制器,而是寻找静态资源。 ** 是通配符,表示任意层路径 -->
	<!--location:去哪个目录中寻找静态资源。mapping中**的值是什么,就去location目录中找对应资源-->
	<!--例如URL是http://localhost:8080/js/jquery.js 其中mapping的**就是jquery.js,就会去location的/js/目录中寻找jquery.js -->
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
<mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
<mvc:resources mapping="/images/**" location="/images/"></mvc:resources>

九、控制单元的方法参数(接收请求参数)

1. 控制单元方法参数写法

控制单元方法参数一共有两种写法:

(1)紧耦方式。获取原生Servlet API,通过原生Servlet API获取请求参数、设置响应内容、设置作用域的值。

(2)解耦方式。使用Spring MVC提供的方式获取请求参数、设置响应内容、设置作用域的值。

2. 紧耦方式

在Spring MVC中,可以直接在控制单元的方法参数中按需注入HttpServletRequest、HttpServletResponse、HttpSession对象。

使用的是原生Servlet API,和原生Servlet API紧耦。  

@RequestMapping("/demo")
public String demoServlet(HttpServletRequest req){
    String name = req.getParameter("name");
    return "index";
}

@RequestMapping("/out")
public void testOut(HttpServletResponse resp) throws IOException {
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter out = resp.getWriter();
    out.print("aa");
}

作用域传值也是和之前Servlet中学习的一样,只需要在参数中注入作用域对象就可以了。但是需要注意ServletContext不能直接注入,需要通过其他对象获取。HttpServletRequest和HttpSession可以注入。

@RequestMapping("/scope")
public String testScope(HttpServletRequest req, HttpSession session){
    ServletContext servletContext = req.getServletContext();
    req.setAttribute("name1","value1");
    session.setAttribute("name2","value2");
    servletContext.setAttribute("name3","value3");
    return "first";
}

3. 解耦方式

解耦方式是Spring MVC独有方式。是Spring MVC给开发者提供的:

(1)获取请求中内容

(2)设置作用域值

(3)设置响应内容

3.1.1 获取普通表单参数

 获取普通表单参数,只需要包含在控制单元中提供与请求参数同名的方法参数即可。

@RequestMapping("/testParam")
public String testParam(String name,int age){
    System.out.println(name+","+age);
    return "suiyi";
}
3.1.2 @RequestParam 注解

@RequestParam是方法参数级注解。每个控制单元方法参数前面都能写这个注解。在@RequestParam注解里面提供了四个属性,分别:

(1)name:当请求参数名和控制单元参数名不对应时,可以使用name指定请求参数名。这样方法参数就可以不与请求参数对应了。  

@RequestMapping("/testParam")
public String testParam(@RequestParam(name="name") String name123, Integer age){
    System.out.println(name123+","+age);
    return "suiyi";
}

 (2)value:是name属性的别名。功能和name属性相同。

(3)defaultValue:默认值。表示当请求参数中没有这个参数时给与的默认值。defaultValue类型是String类型,Spring MVC会对值进行类型转换,转换成参数类型。  

@RequestMapping("/testParam")
public String testParam(@RequestParam("name") String name123,@RequestParam(defaultValue = "16") Integer age){
    System.out.println(name123+","+age);
    return "suiyi";
}

 (4)required:boolean类型,表示请求中是否必须包含参数。

@RequestMapping("/testParam")
public String testParam(@RequestParam("name") String name123,@RequestParam(required = true) Integer age){
    System.out.println(name123+","+age);
    return "suiyi";
}

如果设置为true,且请求中没有这个参数,响应时出现400状态码。

3.1.3 使用JavaBean作为参数(使用类对象作为控制单元参数)

JavaBean:就是具体(非抽象)公共(public)的类,一个包含私有属性,getter/setter方法和无参构造方法Java类。是不是感觉和实体类特别像。其实写法上和实体类相同。唯一区别是实体类是数据库层面的概念,类型中属性要和数据库字段对应。而JavaBean的属性是灵活的,不是必须和哪里对应的。

@RequestMapping("/testBean")
public String testBean(People peo){
    System.out.println(peo);
    return "suiyi";
}

当JavaBean中属性特别多时,原本希望使用普通属性类型接收参数,但是JavaBean中还存在个同名属性,且这个属性的类型和参数类型不一样。Spring MVC会进行类型转换,如果能够转换没有问题。如果无法转换会出现400。

3.1.5 接收多个同名表单参数

 在提交表单数据时,可能在里面包含复选框。当选中多个复选框时会出现多个同名参数。在Spring MVC中可以使用数组和List接收多个同名参数。

@RequestMapping("/testHover")
public String testHovers(String [] hovers){
    System.out.println(Arrays.toString(hovers));
    return "suiyi";
}

@RequestMapping("/testHover")
public String testHovers(@RequestParam("hovers") List<String> hovers){
    System.out.println(hovers);
    return "suiyi";
}
3.1.6 接收日期类型参数

如果希望使用Date类型接收客户端传递过来的数据,默认情况下必须保证客户端参数格式和服务器日期格式一致。  

所以只要保证客户端传递过来的日期是yyyy/MM/dd hh:mm:ss的格式,Spring MVC会自动进行类型转换。其中小时分钟秒可以省略不写。  

@RequestMapping("/testDate")
public String testDate(Date date){
    System.out.println(date.toLocaleString());
    return "suiyi";
}

 如果觉得默认的格式无法满足要求,可以使用@DateTimeFormat自定义时间格式。@DateTimeFormat可以写在控制单元Date类型参数之前,也可以写在JavaBean的属性上面。

@RequestMapping("/testDate")
public String testDate(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){
    System.out.println(date.toLocaleString());
    return "suiyi";
}
3.1.7 接收请求头数据

在HTTP协议中,请求头参数会有很多。如果希望接收请求头数据可以使用@RequestHeader进行接收。

@RequestMapping("/testHeader")
public String testHeader(@RequestHeader String Accept){
    System.out.println(Accept);
    return "suiyi";
}
3.2 设置作用域的值

Spring MVC 中 提供了request作用域的解耦写法。没有提供Session作用域和Application作用域的解耦写法。也就是说当像给Request作用域设置内容时有两种写法,给Session和Application作用域设置值只有紧耦方式。

3.2.1 使用Model设置请求域的值
@RequestMapping("/testScope1")
public String testScope1(Model model){
    // 设置一个作用域值
    model.addAttribute("name","value");
    // 设置多个作用域值
    Map<String,Object> map = new HashMap<>();
    map.put("name2","value2");
    model.addAllAttributes(map);
    return "suiyi";
}
3.2.2 使用Map设置请求域的值

直接在控制单元方法上添加一个Map,然后向Map对象中put值就可以了。  

@RequestMapping("/testScope2")
public String testScope2(Map<String,Object> map){
    map.put("name","value");
    return "suiyi";
}

十、Spring MVC 中文乱码问题

1. 中文乱码解决方案

 需要根据请求的方式的类型去选择对应的中文乱码解决方案。 常见的两种请求方式就是GET和POST。

2. GET方式中文乱码解决

Tomcat8及之后的版本已经将Get请求乱码进行了处理,不需要额外处理。

Tomcat7默认的接收请求GET方式的是IOS-8859-1,如果希望正确的显示中文,还需要手动把内容转换为UTF-8编码。

@RequestMapping("/testEncoding")
public String testEncoding(String name) throws UnsupportedEncodingException {
    System.out.println("接收到name:"+name);
    String newName = new String(name.getBytes("iso-8859-1"),"utf-8");
    System.out.println("转换后的name:"+newName);
    return "suiyi";
}

3. POST方式中文乱码解决

在Spring MVC提供了一个类CharacterEncodingFilter,里面直接写好了POST方式中文乱码解决代码。  

所以想让CharacterEncodingFilter生效,就需要在web.xml文件中配置下面内容。

表示所有的请求编码都设置为UTF-8编码。

<!--配置字符编码过滤器-->
<filter>
    <filter-name>code</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>code</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值