0


Java开发 - Spring MVC框架初体验

前言

上一篇Spring框架感觉写的偏向于理论知识,所以从这篇开始,转变此系列的写作思维,更多的将从实操的角度来讲解Spring MVC框架的使用和相关知识点,会尽量详细,但这一系列课程针对的还是有Java基础的小伙伴,精确到微小操作的部分还是会省略以节省篇幅,不至于太啰嗦,那么现在,我们就开始吧。

创建一个基于Maven的项目

选择骨架

首先是maven工程,骨架选择maven-archetype-webapp,不要选错了,接着next。

基础信息

next后,直接finish即可。

项目环境检查

新的项目中没有Java目录,需要自己创建,创建时选择Directory,会自动提示文件夹,下面两个都创建就行,分两次完成:

此时你还需要添加一个tomcat,自己下载一个吧,接着是添加topcat进来:

选择Tomcat Server,local版本,因为我们是在本地进行的。

啊,这个过程太细了,感觉没完没了,所以过程再省略,需要大家自己搞好Tomcat环境,然后我们继续。

运行项目

启动Tomcat,看看 能不能成功,成功后有两个表示:

第一,日志输出大致如下:

第二,会在你选定的浏览器上弹出一个html页面:

到这里,恭喜你,你的环境已经弄好了,接着我们可以来学习了解Spring MVC框架了。

什么是Spring MVC框架

Spring MVC框架是基于Spring框架的,所以我们在添加Spring MVC的依赖时,Spring框架的依赖也会被添加,将具备Spring的所有特点。

Spring框架主要解决了后端服务器接收客户端的请求,并给予一定的响应。

Spring MVC的MVC = Model + View + Controller:

  • Model:数据模型,由业务逻辑层和数据访问层共同构成
  • View:视图,我们刚刚看到弹出来的html就算是View
  • Controller:控制器,用来协调Model和View之间的数据传递

这样就划分了其职责。通常,我们不需要关心V和C层的交互,和M的关系我们认为没有关系,这么说,只是方便大家理解,后续还需要大家自行理解再思考。

框架目的

Spring MVC框架的目的是接收客户端请求,要完成这一过程,我们还需要将项目部署到Tomcat服务器上,在浏览器中输入指定的URL,可以得到简单的响应,这样,一个最简单的Spring MVC框架的工程就完成了,接下来看看具体该怎么做吧。

一个简单的Spring MVC框架项目

添加Spring MVC依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.14</version>
        </dependency>

添加好,记得拉一下依赖,如果后续运行时提示不可识别Servlet相关类,则补充添加以下依赖项:

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

关于依赖,你需要知道,<scope>provided</scope>表示此依赖不会参与测试或部署,因为当Web项目部署到Tomcat中后,Tomcat环境会包含此依赖项。但不排除有人会报不可识别Servlet相关类,所以建议大家都添加下。

添加Spring配置类

package cn.codingfire.springmvc.config;

import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
}

这个我们应该很熟悉了,上一篇也已经讲过了。

添加Spring MVC配置类

package cn.codingfire.springmvc.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@ComponentScan("cn.codingfire.springmvc")
public class SpringMvcConfig implements WebMvcConfigurer {
    
}

目的是扫描对应包下的文件,并引入了Spring MVC配置。

创建初始化类

此类需要继承自AbstractAnnotationConfigDispatcherServletInitializer,且必须重写父类三个抽象方法,其实在继承后,可以根据快捷键自动生成。

package cn.codingfire.springmvc;

import cn.codingfire.springmvc.config.SpringConfig;
import cn.codingfire.springmvc.config.SpringMvcConfig;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        //返回自己配置的Spring相关的配置类
        return new Class[] {SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        //返回自己配置的Spring MVC相关的配置类
        return new Class[] {SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        //返回由Spring MVC框架处理的路径
        return new String[] {"*.page"};
    }
}

这里解释下为什么这么做,俩字,规定!就像我们要按照语法写Java一样,这里就是要按照这样的方式来写。

*.page这里就是用了一个不正常的扩展名,因为怕冲突,我们可以随便配,只要不冲突就行。

创建控制器类

package cn.codingfire.springmvc.controller;

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

@Controller
public class UserController {
    //http://localhost:8080/springmvc_war_exploded/login.page
    @RequestMapping("/login.page")
    @ResponseBody
    public String login() {
        return "login page";
    }
}

@RequestMapping("/login.page")注解,通常添加在类上,用于配置请求路径的前缀部分,也使用produces属性配置此控制器类中所有处理请求的方法响应时的文档类型,例如在类上配置为@RequestMapping(value="xxxxx", produces="application/json; charset=utf-8")。

@ResponseBody 注解,用于响应正文,可添加在处理请求/处理异常的方法之前,将作用于对应的方法,或添加在类之前,将作用于类中所有处理请求/处理异常的方法。

@Controller注解,组件注解,添加在类的声明之前,表示此类是组件类,应该添加在控制器类上。

从这里开始,我们真正接触接口的开发了,只不错这里还不是我们传统意义的接口,只因为返回不是json格式,这个不急,我们后面会讲。

开始进行测试

以上几步做完之后,我们就可以在浏览器输入链接,看看页面请求服务器后能不能返回给我们一个显示login page的页面,经测试,完全无误。

这里又个很有意思的东西,如果返回中文,则会在浏览器中出现乱码,这是因为某些版本的Spring MVC默认的字符编码是ISO-8859-1,只支持ASCII字符,后续会解决这个问题,大家稍安勿躁。

Spring MVC框架的功能

@RequestMapping注解

上面已经简单对@RequestMapping注解做过说明,但@RequestMapping注解远不止此,在以后的开发生涯,你将无法甩开@RequestMapping注解,因为它真的很重要。下面,我们就来说说@RequestMapping注解可以做什么。

@RequestMapping注解的主要作用是配置请求路径和相应方法的映射关系,在上例中,大家已经看到了它的基础用法。除了配置在方法前,还可以配置在类之前,表示给当前路径额外增加一小段路径,举例说明:

@Controller
@RequestMapping("/user")
public class UserController {
    //http://localhost:8080/springmvc_war_exploded/login.page
    @RequestMapping("/login.page")
    @ResponseBody
    public String login() {
        return "login page";
    }
}

添加了“/user”后,我们的请求路径就要变了:

原来的路径:http://localhost:8080/springmvc_war_exploded/login.page

新的路径:http://localhost:8080/springmvc_war_exploded/login.pagehttp://localhost:8080/springmvc_war_exploded/user/login.pagehttp://localhost:8080/springmvc_war_exploded/login.page

"/user"你当然可以写的更长一些,比如"/user/header",只要有利于你的开发。“/”可以不加,系统会自动补上,但是有个“/”时,中间分隔的不能省略,若是写了“//”,只会有一个生效。

一般在项目中,我们会针对不同的模块给出不同的模块名字,以方便开发者区分接口的所属部分。

RequestMapping还可以设置其他的一些参数:

  • method:请求方式
@RequestMapping(value = "/login.page", method = RequestMethod.POST)

可以指定请求的方式是get?还是post?抑或是其他的类型,一般来说,实际开发中,我们很少在方法上直接使用@RequestMapping,再来指定请求的类型,因为有更简便的方式,比如@PostMapping等。只有同时允许多种请求方式,我们才会这么用,但开发者一般不会这么做,这种用法多年来我也见过,但确实不多。

关于请求方式,共有GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE几种。里面大多我们是不常用的。

一旦指定了类型,使用错误的请求方式,将会报405错误。

  • headers:请求头
  • params:请求参数
  • consumes:请求文档类型
  • produces:响应文档类型
@RequestMapping(value = "/login.page", produces="text/html; charset=utf-8")

produces我们用来显示的指定响应文档的类型,它直接决定返回的数据是json类型?还是我们目前的字符串类型。值得一提的是,这个添加解决了我们上面返回中文乱码的问题,因为我们指定了utf-8格式。

@ResponseBody注解

@ResponseBody是响应正文,它响应的内容将直接展示在客户端,没有配置的时候,将直接显示为视图组件的名称,也就是我们常说的jsp文件,但这并不是前后端分离的思想,早起用的很多,如今jsp几乎已经没有公司在使用了。我们现在多采用前后端分离的做法。

@ResponseBody注解可以添加在方法上,也可以 添加在类上,在类上则作用于全部的方法。

前后端分离好处是,一个接口,多端使用,而不需要后端写好几套接口供给不同的端来使用,大家应该是比较熟悉的。所以,Spring MVC内置了转换器,将方法的返回值转换为响应到客户端的数据(并补充其它必要数据),返回值不同,则使用的转换器也不同。比如我们刚刚提到的中文乱码问题。

这里我们采用String类型作为返回值,实际开发中,我们绝对不会这么做,因为一个接口不仅仅是返回一个数据,还包括是否成功,成功失败的message,相应的数据,这时String类型已经无能为力,你说String可以吗?也可以,但是会出现后端转换String难,客户端String转换json难的问题,这就浪费了时间,完全没必要。

这里,我们推荐一个依赖来解决这个问题:

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>

添加到pom文件中,记得拉一下依赖,下载下来。

jackson-databind依赖项中有个转换器,当Spring MVC调用的处理请求的方法的返回值是Spring MVC没有匹配的默认转换器时,会自动使用jackson-databind的转换器,而jackson-databind转换器会解析方法的返回值,并将其处理为JSON格式的字符串,在响应头中将 Content-Type设置为application/json。这里用到了RequestMapping中的header属性。

注意啦,Spring MVC项目中,还需要在Spring MVC的配置类上添加 @EnableWebMvc注解,否则响应时将导致406错误。

Json格式的响应正文

我们创建一个数据类,根据阿里命名规范,我们也学习下,数据类型的命名有一定规范,数据我们统一放在POJO包下,然后再分为VO,DTO等等,后面有时间再给大家详细说说,也可自行查找了解,这里我们创建一个VO类,用于响应客户端:

package cn.codingfire.springmvc.vo;

public class UserVO {
    private String username;
    private String password;

    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;
    }
}

实现setter&getter方法,后面会有一个依赖帮我们来做,不需要我们显示的声明,后面再说。jackson-databind会自动调用属性的Setter / Getter方法。

在controller中添加一个新的方法:

package cn.codingfire.springmvc.controller;

import cn.codingfire.springmvc.vo.UserVO;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/user")
@ResponseBody
public class UserController {
    //http://localhost:8080/springmvc_war_exploded/user/login.page
    @RequestMapping("/login.page")
    public String login() {
        return "login page";
    }

    //http://localhost:8080/springmvc_war_exploded/user/info.page
    @GetMapping("/info.page")
    public UserVO userInfo() {
        UserVO userVO = new UserVO();
        userVO.setUsername("codingfire");
        userVO.setPassword("123456");
        return userVO;
    }
}

重启Tomcat,在浏览器输入新的路径,可以在浏览器看到json格式的数据:

到这里,正常的接口你已经会写了。但这还没完,我们还要去接受 客户端传递的参数,param属性即将登场。

接收请求的参数

我们新增一个注册方法:

    //http://localhost:8080/springmvc_war_exploded/user/register.page
    @GetMapping("/register.page")
    public UserVO register(String username, String password) {
        UserVO userVO = new UserVO();
        userVO.setUsername(username);
        userVO.setPassword(password);
        return userVO;
    }

重启Tomcat,然后在浏览器输入URL,这里要注意,有参数,get方法的参数你应该是了解的:

回车之后,发起请求,我们在浏览器看看返回的json数据是不是我们自己传入的:

非常好,达到了我们的预期。这里要注意 几点:

参数要声明为我们想要的类型,在整个过程中,Spring会尝试去转换参数类型为目标类型,如果转换失败,则会抛出异常。

参数名称也要和后端声明的一致,若是不一致,后端将无法得到请求中传入的参数,值将为null。这些值都由服务器决定,客户端需要严格遵守服务端定下的规则。

如果有必要,可在参数前声明@RequestParam注解,指定新的请求参数名,而不再使用声明的参数名。还可以在此注解中配置required属性,默认true,则客户端必传此参数,false时可不传。还可配置置defaultValue属性,设置默认值。

若是客户端提交参数较多,就需要将参数封装为对象的形式,如:

    @GetMapping("/register.page")
    public UserVO register(UserVO user) {
        UserVO userVO = new UserVO();
        userVO.setUsername(user.getUsername());
        userVO.setPassword(user.getPassword());
        return userVO;
    }

这样可以使代码更加简洁,我们在实际开发中也多会使用此模式。但并不是所有情况都需要封装为对象,如果参数较少,只有几个,则用显示的声明的形式更为直观和方便。可自行斟酌。

关于POJO和Model的命名

POJO即Plain Ordinary Java Object,是普通Java对象的意思,所有封装属性的对象的类统称POJO,所有POJO类都需要遵守一定的规则:

  • 实现Serializable接口
  • 属性私有
  • 实现setter&getter方法,由开发工具生成,后面我们可以通过依赖自动非显示的生成
  • 重写hashCode方法,equals方法,toString方法,这个也和前一条一样,由开发工具完成,不需要开发者操心

关于命名,后缀需要添加对应的业务领域的名字,如xxxVO,XXXDTO,且后缀需要大写。

了解RESTful

RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以 使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。

RESTful的设计风格表现为将某些唯一的请求参数的值放在 URL中,使之成为URL的一部分,比如:http://localhost:8080/springmvc_war_exploded/user/100021

URL后面的一串数字就是RESTful的表现,这里的数字可以根据用户ID,替换为其他的用户ID 。RESTful只是一种设计风格,并不是一种规定,所以没有明确的执行方式,实际开发中,我们多会这么设计:

http://localhost:8080/springmvc_war_exploded/user/100021 查询ID为100021的用户信息

http://localhost:8080/springmvc_war_exploded/user/100021/delete 删除ID为100021的用户信息

RESTful建议根据希望获取数据的方式来选择请求方式,比如增加用post,删除用delete,修改用put,查询用get。而在实际开发中,我们多数只使用get和post,以查询为目的的URL用get,否则都用post。

在服务端,当涉及这样的URL时,需要使用占位参数{参数},使用@PathVariable注解请求参数, 可以将占位符的实际值注入到请求参数中!

    @GetMapping("/{id}/info.page")
    public UserVO userInfo(@PathVariable Long id) {
        UserVO userVO = new UserVO();
        userVO.setUsername("codingfire");
        userVO.setPassword("123456");
        return userVO;
    }

有时候,我不想把id这个参数暴漏给客户端,那么我就可以通过此注解来指定一个名字给客户端用,而我这里还是使用id。

    @GetMapping("/{id}/info.page")
    public UserVO userInfo(@PathVariable("userID") Long id) {
        UserVO userVO = new UserVO();
        userVO.setUsername("codingfire");
        userVO.setPassword("123456");
        return userVO;
    }

上传id的时候,这个占位符我希望必须时数字,数字之外的我就不处理,这种时候,可以通过正则表达式来进行处理:

    @GetMapping("/{id:[0-9]+}/info.page")
    public UserVO userInfo(@PathVariable Long id) {
        UserVO userVO = new UserVO();
        userVO.setUsername("codingfire");
        userVO.setPassword("123456");
        return userVO;
    }

还有一种情况,多种不冲突的正则表达式用在同一个URL上也是允许的,只要参数不一致就可以,看下怎么做:

    @GetMapping("/{id:[0-9]+}/info.page")
    public UserVO userInfo(@PathVariable Long id) {
        UserVO userVO = new UserVO();
        userVO.setUsername("codingfire");
        userVO.setPassword("123456");
        return userVO;
    }

    @GetMapping("/{username:[a-zA-Z]+}/info.page")
    public UserVO userInfo(@PathVariable String username) {
        UserVO userVO = new UserVO();
        userVO.setUsername("codingfire");
        userVO.setPassword("123456");
        return userVO;
    }

以上,我们都是用了正则表达式,如果我不使用正则,会怎么样呢?先看看怎么写:

    @GetMapping("/list/info.page")
    public UserVO userList() {
        ...
    }

当我们使用这个URL:/list/info.page时,就不会因为匹配到了/{id:[0-9]+}/info.page而不执行这个URL,这里明确是没有使用正则的,所以使用正则并不会影响到精确的URL匹配。

关于响应正文

先前我们已经说过了,响应正文可以是String类型,也可以是json类型,但在实际开发中,我们看到的响应正文都是比较规范的,比如响应码,响应信息,响应数据,我们可以通过抓包来看其他应用的响应格式,会发现,不同的公司,他们的响应格式几乎是一样的,这就是行业内不成文的规定,大家默认的一种通用方式。

下面我们来写下这个通用数据格式的类:

package cn.codingfire.springmvc.web;

public class JsonResult<T> {
    //状态码
    private Integer state;
    //消息,包括成功信息和失败信息
    private String message;
    //返回数据,我们希望它可以转化为任何类型,所以一般会使用泛型
    private T data;

    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

通用返回的类写好后,我们来用一下:

    @GetMapping("/codingFireInfo.page")
    public JsonResult<UserVO> codingFireInfo() {
        UserVO userVO = new UserVO();
        userVO.setUsername("codingfire");
        userVO.setPassword("123456");

        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(200);
        jsonResult.setMessage("请求成功");
        jsonResult.setData(userVO);
        return jsonResult;
    }

接着直接重启Tomcat,在浏览器输入我们的URL,来来返回的结果,注意乱码问题,上面已经给出解决方案:

http://localhost:8080/springmvc_war_exploded/user/codingFireInfo.page

我们发现这么做是OK的。我们再来仔细看我们的代码,封装度其实并不高,我们希望状态码是枚举类型的,且我们可以直接使用成功失败的方法,不需要我们手写状态码和状态,因为这样很容易出错,这些值我们称之为魔法值,在阿里开发手册中,这种情况是严厉禁止的,因为会代码的可读性降低,所以还需要对这个类进行高度封装,这并不难,博主就不再给出封装部分的代码,大家可以自己手写一下,做个练习。

统一处理异常

异常在代码中还是比较经常出现的,基于面向对象语言的特点,我们希望异常可以统一处理,统一管理,Spring MVC恰好提供了这种方式,使我们在任何地方都可以直接抛出异常,交由统一的异常处理机制来处理,前提是你没有显示使用try...catch来捕获并处理异常。

处理异常有一种在当前类处理当前类异常的方式,直接添加方法如下:

    @ExceptionHandler
    public String handleException(NullPointerException e) {
        return "NullPointerException!";
    }

缺点是只能处理本类的异常,对于其他类的异常则鞭长莫及,这样就会造成重复写代码的情况,所以我们多会使用统一的异常处理机制,这种方式只做说明,知道就可以。

关于统一异常处理,需要自定义类来统一处理,我们来看看这个自定义类该怎么写:

package cn.codingfire.springmvc.exception;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler
    public String handleException(NullPointerException e) {
        return "NullPointerException";
    }

    @ExceptionHandler
    public String handleNumberFormatException(NumberFormatException e) {
        return "NumberFormatException";
    }

    @ExceptionHandler
    public String handleThrowable(Throwable e) {
        e.printStackTrace();
        return "Throwable";
    }
}

这样,处理异常的代码就可以放在专门的类中,在类上添加@ControllerAdvice注解,由于目前主流的响应方式都是“响应正文”的,所以可将@ControllerAdvice替换为 @RestControllerAdvice 。

不同的异常类型,可以使用不同的方法来单独处理,就像上面写的方式那样。一般我们会将异常的相关信息进行输出,这样可以方便开发者观察和分析问题。

了解这部分内容的同学会知道,@ExceptionHandler注解指定的异常类型优先级高于通过参数指定的异常类型的方式,而且此注解指定异常类型时,同一个方法也可以处理多种异常的情况,所以我们处理如下:

package cn.codingfire.springmvc.exception;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler({NullPointerException.class, NullPointerException.class})
    public String handleException(Throwable e) {
        return "Throwable";
    }

    @ExceptionHandler(NumberFormatException.class)
    public String handleNumberFormatException(Throwable e) {
        return "NumberFormatException";
    }

    @ExceptionHandler(Throwable.class)
    public String handleThrowable(Throwable e) {
        return "Throwable";
    }
}

Interceptor(拦截器)

Interceptor是拦截器,在Spring MVC框架中,拦截器可以在请求处理前后执行一些额外的代码,比如在请求用户信息之前判断用户登录状态来决定是否拒绝访问或者放行。虽然可以这么做,但拦截器的目的并不是拦截并阻止运行,其目的是处理多种不同请求的处理过程。多发生在不同的请求需要执行高度相似的代码,比如验证用户的登录状态。

使用拦截器和使用统一异常处理一样,需要使用自定义的类,并实现HandlerInterceptor接口,重写里面的三个方法,我们来看看这个类怎么写:

package cn.codingfire.springmvc.Interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //根据用户登录状态选择是否放行,不放行选择false
        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 {
        //在请求执行结束后再统一执行某些操作
    }
}

拦截器写好了,但是却不能自动生效,因为拦截器都需要被注册才能生效,注册过程通过重写 WebMvcConfigure接口中的addInterceptors()方法即可,我们会到Spring MVC的配置类中看看该怎么注册:

package cn.codingfire.springmvc.config;

import cn.codingfire.springmvc.Interceptor.LoginInterceptor;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@ComponentScan("cn.codingfire.springmvc")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/codingFireInfo.page");
    }
}

以上是匹配单个接口,但一般不会这么用,前面讲过,匹配的是某一类接口。

匹配用户模块所有接口:

//匹配user下所有接口
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/*");

通配符的运用,可以匹配user下所有接口,addPathPatterns的参数也可以传数组,可以把要添加的URL放在数组中。

匹配多层级

//匹配user下所有接口
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**");

匹配多层级需要两个通配符。

不能匹配的情况

//匹配user下所有接口
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/10021/info.page");

是不是刚刚讲过的RESTful风格?这里的数字是变化的,所以没法匹配。

能匹配路径,也能排除某些路径

registry.addInterceptor(new LoginInterceptor())
        .addPathPatterns("/user/codingFireInfo.page")
        .excludePathPatterns("/user/register.page", "/user/login.page");

通过excludePathPatterns方法排除路径,路径可以是多个,也可以使用通配符,也可以给数组,和添加路径的用法一样。

结语

写到这里,Spring MVC框架就跟大家分享完了,看到这里没你已经可以写一个简单的Spring MVC框架的项目了。甚至一些小的项目,使用这个框架也完全够了,只要有一台服务器,它就可以正常工作,给客户端提供服务。下一篇,咱们SSM框架见。觉得不错就点个赞再走吧!

标签: java spring mvc

本文转载自: https://blog.csdn.net/CodingFire/article/details/128607379
版权归原作者 CodingFire 所有, 如有侵权,请联系我们删除。

“Java开发 - Spring MVC框架初体验”的评论:

还没有评论