SpringMVC之JSR303和拦截器

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: SpringMVC之JSR303和拦截器

一、JSR303

1.1 什么是JSR303

JSR303是Java规范请求(Java Specification Request)的编号,它定义了Java Bean验证的标准。Java Bean验证是一种验证框架,可以验证Java Bean中的属性,以确保它们符合特定的规则和约束。该框架在Java EE 6中得到了官方支持,并在javax.validation包中实现。JSR303规范定义了验证注释,这些注释可以应用于Java Bean的属性上,以指示验证规则。这些验证规则可以检查属性是否为空、是否符合正则表达式、是否在指定范围内等等。通过使用JSR303,我们可以确保Java Bean的属性始终符合预期,并在出现错误时及时捕获并处理这些错误。

JSR303的定义:

JSR303是一种Java平台标准,也称为Bean Validation,用于验证JavaBean和其他Java对象的声明约束。JSR303使用注释标记属性的限制,并提供了一个验证引擎,该引擎可以在运行时执行验证以确保对象的有效性。它提供了一种轻松的方式来验证表单数据和其他用户输入,防止不良数据进入应用程序。JSR303旨在提供一致的验证机制,使Java应用程序更加健壮和可维护。

1.2 为什么要使用JSR303

JSR303是Java Validation API的规范,它提供了一种简单易用的验证框架,帮助我们在实体类属性上进行验证,对于确保数据的正确性和完整性非常有用。 使用JSR303可以带来以下好处:

1. 易于维护和扩展:将验证规则注解到属性上,代码易于维护和扩展,避免了繁琐的手工验证。

2. 提高代码可读性:验证规则注解到属性上,代码可读性大大提高。

3. 减少重复代码:使用JSR303可以减少编写检验代码的重复工作,提高生产效率。

4. 提高系统健壮性:通过JSR303验证规则的定义,可以确保数据的正确性和完整性,提高系统健壮性和稳定性。

1.3 常用注解

JSR303是Java中的Bean Validation规范,其中定义了许多注解用于对JavaBean中的属性进行验证。以下是常用的JSR303注解及其解释:

1. @NotNull:验证字段不为null。

2. @NotBlank:验证字段不为空,即长度大于0,去掉空格后长度大于0。

3. @NotEmpty:验证字段不为空,即长度大于0。

4. @Min:验证数字字段的最小值。

5. @Max:验证数字字段的最大值。

6. @Size:验证字段的大小范围。

7. @DecimalMin:验证十进制数字段的最小值。

8. @DecimalMax:验证十进制数字段的最大值。

9. @Pattern:验证字段匹配正则表达式。

10. @Email:验证字段为Email格式。

11. @Length:验证字段的长度。

12. @Range:验证字段的值在范围内。

13. @Valid:验证嵌套对象。

14. @AssertTrue:验证字段为true。

15. @AssertFalse:验证字段为false。

16. @Past:验证日期字段在当前时间之前。

17. @Future:验证日期字段在当前时间之后。

以上是常用的JSR303注解及其解释,开发者可以根据实际情况选择需要的注解。

@Validated与@Valid区别 ::

@Validated:

  • Spring提供的
  • 支持分组校验
  • 可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
  • 由于无法加在成员属性(字段)上,所以无法单独完成级联校验,需要配合@Valid

@Valid:

  • JDK提供的(标准JSR-303规范)
  • 不支持分组校验
  • 可以用在方法、构造函数、方法参数和成员属性(字段)上
  • 可以加在成员属性(字段)上,能够独自完成级联校验

1.4 快速入门

1.4.1 导入依赖

<!-- JSR303 -->
<hibernate.validator.version>6.0.7.Final</hibernate.validator.version>
<!-- JSR303 -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>${hibernate.validator.version}</version>
</dependency>

1.4.2 配置校验规则

校验属性是否为空:

@NotNull(message = "歌曲编号不能为空")
    private Integer mid;
    @NotBlank(message = "歌曲名称不能为空")
    private String mname;
    @NotBlank(message = "歌曲专辑不能为空")
    private String mtype;
    @NotBlank(message = "歌曲歌词不能为空")
    private String minfo;
    @NotBlank(message = "歌曲图片不能为空")
    private String mpic = "暂无图片";

1.4.3 入门案例

在MusicController类中添加以下方法:

//    给数据添加服务端校验
    @RequestMapping("/valiAdd")
    public String valiAdd(@Validated Music music, BindingResult result, HttpServletRequest req){
//        如果服务端验证不通过,有错误
        if(result.hasErrors()){
//            服务端验证了实体类的多个属性,多个属性都没有验证通过
            List<FieldError> fieldErrors = result.getFieldErrors();
            Map<String,Object> map = new HashMap<>();
            for (FieldError fieldError : fieldErrors) {
//                将多个属性的验证失败信息输送到控制台
                System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
                map.put(fieldError.getField(),fieldError.getDefaultMessage());
            }
            req.setAttribute("errorMap",map);
        }else {
            this.musicBiz.insertSelective(music);
            return "redirect:list";
        }
        return "mic/edit";
    }

在服务端中进行校验,校验的模型的属性中出现错误,则将错误信息的属性进行遍历添加到map集合中并保存起来回显到前端,需要注意的是,注解@validated保存的是校验时的参数,最终校验的结果保存在BindingResult中.

1.4.4 结果测试

在没有进行后端效验前应该会报空指针异常。

但是在进行后端效验之后,就会将我们的错误信息反馈到前端的展示界面,如下:

控制台效果:

二、Java三大器之拦截器

2.1 什么是拦截器

2.1.1 定义

在Java编程中,拦截器(Interceptor)是一种常见的机制,它可以拦截方法的调用或者HTTP请求的处理过程,并在处理前后执行一些特定的操作或者逻辑。拦截器通常用于实现各种不同的功能,如权限控制、日志记录、事务管理等。

2.1.2 作用领域

在Java Web开发中,拦截器常用于拦截HTTP请求并进行处理,例如进行身份验证、拦截非法的请求、记录日志等。在Spring框架中,拦截器是一个非常重要的组件,可以通过实现HandlerInterceptor接口来定义拦截器,然后在配置文件中配置拦截器的拦截规则和执行顺序。在Struts2、Spring MVC等Web框架中也都有拦截器的支持。

2.2 Java三大器之过滤器

2.2.1 定义

Java中的过滤器(Filter)是一种用于拦截HTTP请求和响应的组件,它在请求到达Servlet之前拦截并验证HTTP请求,或在Servlet响应到达客户端前对响应进行处理。在Java Web应用中,过滤器是一个可配置的组件,它需要在web.xml文件中注册并配置相应的属性才能生效。可以通过编写实现javax.servlet.Filter接口的Java类来定义过滤器的功能。

2.2.2 作用领域

过滤器通常用于实现一些通用的处理逻辑,比如认证、日志记录、统计信息等,以提高代码复用性和可维护性。过滤器还可以用于跨站点脚本攻击(XSS)和跨站点请求伪造(CSRF)等安全机制的实现。

2.3 拦截器与过滤器的区别

图解如下:

拦截器和过滤器都是在Java Web开发中对请求进行拦截处理的一种工具,但是它们有以下区别:

1. 执行顺序: 过滤器是在Servlet容器调用servlet之前或之后执行的,而拦截器是在servlet处理请求之前或之后执行的。

2. 作用范围: 过滤器作用于所有的请求和响应,包括静态资源,而拦截器只拦截配置的路径及其子路径的请求。

3. 功能范围: 过滤器可以在过滤器链中做一些额外的功能,如字符编码、请求转发和重定向等,而拦截器可以更好地控制业务流程,如权限控制、日志记录等。

4. API不同: 过滤器是使用Servlet API实现的,而拦截器是使用Spring MVC框架自身的接口实现的。

总的来说,过滤器更加通用,可以实现一些基本的请求过滤和处理操作,而拦截器则更加灵活,可以根据业务需求实现更加复杂的操作。在实际应用中,需要根据具体的需求选择使用过滤器还是拦截器。

2.4 应用场景

  • 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
  • 权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;
  • 性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);
  • 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。

2.5 拦截器工作原理

2.6 用户登录权限控制

基本拦截器配置(在Java目录下新建一个interceptor包,创建拦截器类):

OneInterceptor:

package com.Kissship.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 OneInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【OneInterceptor】:preHandle...");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("【OneInterceptor】:postHandle...");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("【OneInterceptor】:afterCompletion...");
    }
}

TwoInterceptor:

package com.Kissship.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 TwoInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【TwoInterceptor】:preHandle...");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("【TwoInterceptor】:postHandle...");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("【TwoInterceptor】:afterCompletion...");
    }
}

然后在Spring-mvc.xml中配置多拦截器,添加代码如下:

<!--&lt;!&ndash;    用户权限的请求拦截&ndash;&gt;-->
    <mvc:interceptors>
        <bean class="com.Kissship.interceptor.LoginInterceptor"></bean>
    </mvc:interceptors>
    <mvc:interceptors>
        <!--2) 多拦截器(拦截器链)-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.Kissship.interceptor.OneInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/mic/**"/>
            <bean class="com.Kissship.interceptor.TwoInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

然后接下来创建一个名为LoginInterceptor的拦截器,如下:

package com.Kissship.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 {
        System.out.println("【implements】:preHandle...");
        StringBuffer url = request.getRequestURL();
        if (url.indexOf("/login") > 0 || url.indexOf("/logout") > 0){
            //        如果是 登录、退出 中的一种
            return true;
        }
//            代表不是登录,也不是退出
//            除了登录、退出,其他操作都需要判断是否 session 登录成功过
        String mname = (String) request.getSession().getAttribute("mname");
        if (mname == null || "".equals(mname)){
            response.sendRedirect("/page/login");
            return 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 {
    }
}

接着创建一个新的jsp页面用来充当登录界面进行效果测试,login.jsp代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登入</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/login" method="post" enctype="multipart/form-data">
    <label>用户名称:</label><br/>
    <input type="text" name="mname"/><br/>
    <input type="submit" value="登入"/>
</form>
</body>
</html>

最后进行测试,效果如下:


最后SpringMVC之JSR303和拦截器就到这里,祝大家在敲代码的路上一路通畅!

感谢大家的观看 !


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
6月前
SpringMVC之拦截器和异常处理器
【1月更文挑战第20天】SpringMVC之拦截器和异常处理器
71 0
|
缓存 前端开发 Java
SpringMVC之JSR303和拦截器
SpringMVC之JSR303和拦截器
74 0
|
前端开发 Java 数据库连接
SpringMVC系列(五)之JSR303和拦截器
SpringMVC系列(五)之JSR303和拦截器
|
12月前
|
监控 前端开发 Java
SpringMVC之JSR303使用及拦截器使用(带你探索SpringMVC的新领域)
SpringMVC之JSR303使用及拦截器使用(带你探索SpringMVC的新领域)
78 0
|
6月前
|
前端开发 Java Apache
JAVAEE框架技术之6-springMVC拦截器和文件上传功能
JAVAEE框架技术之6-springMVC拦截器和文件上传功能
102 0
JAVAEE框架技术之6-springMVC拦截器和文件上传功能
|
6月前
SpringMVC拦截器的介绍,拦截器的基本实现,拦截器链配置
SpringMVC拦截器的介绍,拦截器的基本实现,拦截器链配置
53 2
|
缓存 前端开发 Java
【SpringMVC】JSR 303与拦截器注解使用
【SpringMVC】JSR 303与拦截器注解使用
72 0
|
开发框架 监控 Java
SpringMVC之JSR303和拦截器
SpringMVC之JSR303和拦截器
61 0
|
6月前
|
前端开发 Java 应用服务中间件
SpringMvc拦截器和手写模拟SpringMvc工作流程源码详解
MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分。 M: Model,模型层,指工程中的JavaBean,作用是处理数据。 JavaBean分为两类: 1.实体类Bean:专门存储业务数据的,如Student User等 2.业务处理Bean:指Service或Dao对象,专门用于处理业务逻辑和数据访问。
|
6月前
|
前端开发 JavaScript Java
Spring Boot中Spring MVC的基本配置讲解与实战(包括静态资源配置,拦截器配置,文件上传配置及实战 附源码)
Spring Boot中Spring MVC的基本配置讲解与实战(包括静态资源配置,拦截器配置,文件上传配置及实战 附源码)
216 1