The use of JSR303 and interceptors

1.JSR303

1. Understand JSR303

JSR is the abbreviation of Java Specification Requests, which means Java specification proposal. It is a formal request to JCP (Java Community Process) to add a standardized technical specification. Anyone can submit a JSR to add new APIs and services to the Java platform. JSR has become an important standard in the Java world. JSR-303 is a sub-specification in JAVA EE 6 called Bean Validation. Hibernate Validator is the reference implementation of Bean Validation. Hibernate Validator provides implementation of all built-in constraints in the JSR 303 specification, in addition to Some additional constraints.

 Validating data is a common task that occurs in all application layers from the presentation layer to the persistence layer. Often the same validation logic is implemented at every layer, which is time-consuming and error-prone. To avoid duplicating these validations, developers often bundle validation logic directly into the domain model, mixing domain classes with validation code that is actually metadata about the classes themselves.

2. Why use JSR303

Hasn’t the front end already verified the data? Why do we still need to do verification? Why don’t we just use it? It's sloppy. If the front-end code verification is not written well, or for people who know a little programming, they can directly bypass the front-end and send requests (make extraordinary data requests through testing tools like Postman) and pass some wrong parameters. Come here, isn't your back-end code in danger?

Therefore, we generally perform one set of verifications on the front end and one set of verifications on the back end, so that security can be greatly improved.

3.Commonly used annotations

annotation illustrate
@Null Used to verify that the object is null
@NotNull Used for objects that cannot be null and cannot check strings with a length of 0
@NotBlank Only used for String type, cannot be null and size after trim()>0
@NotEmpty Used for collection classes, String classes cannot be null, and size>0. But strings with spaces cannot be verified.
@Size Used to check whether the length of the object (Array, Collection, Map, String) is within the given range
@Length The size used for String objects must be within the specified range
@Pattern Rules for whether a String object conforms to a regular expression
@Email Used to determine whether the String object conforms to the mailbox format
@Min Used to determine whether Number and String objects are greater than or equal to the specified value.
@Max Used to determine whether Number and String objects are less than or equal to the specified value
@AssertTrue Whether the Boolean object is true
@AssertFalse Whether the Boolean object is false

 4. The difference between @Validated and @Valid

@Validated:

  • Provided by Spring

  • Support group verification

  • Can be used on types, methods and method parameters. But it cannot be used on member attributes (fields)

  • Since it cannot be added to member attributes (fields), cascade verification cannot be completed alone and needs to be coordinated with @Valid

@Valid:

  • Provided by JDK (standard JSR-303 specification)

  • Group verification is not supported

  • Can be used on methods, constructors, method parameters and member properties (fields)

  • Can be added to member attributes (fields) to complete cascade verification independently

5. Use JSR303

1. Import pom.xml dependencies 

<!-- 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>

2. Configuration verification

package com.xzs.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.NotBlank;

import javax.validation.constraints.NotNull;

@Data//相当于set get toString方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor 
public class Clazz {
    @NotNull(message = "班级编号不能为空")
//    @Size(max = 100,min = 10,message = "大小必须在10至100之间")
    protected Integer cid;

    @NotBlank(message = "班级名不能为空")
    protected String cname;

    @NotBlank(message = "班级教员老师不能为空")
    protected String cteacher;

    private String pic="暂无图片";


}

3.Verification method

   @RequestMapping("/valiAdd")
    public String valiAdd(@Validated Clazz clazz, 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.clazzBiz.insertSelective(clazz);
            return "redirect:list";
        }
        return "clz/edit";
    }
front end
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户编辑、新增公共页面</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/${empty c ? 'clz/valiAdd' : 'clz/edit'}" method="post">
    学生id:<input type="text" name="id" value="${c.cid }"><span STYLE="color: red">${errorMap.cid}</span><br>
    学生名:<input type="text" name="name" value="${c.cname }"><span STYLE="color: red">${errorMap.cname}</span><br>
    老师:<input type="text" name="loginname" value="${c.cteacher }"><span STYLE="color: red">${errorMap.cteacher}</span><br>


    <input type="submit">
</form>
</body>
</html>

result:

2.Interceptor

2.1.What is an interceptor?

SpringMVC's processor interceptor is similar to the filter in Servlet development and is used to pre-process and post-process the processor. It relies on the web framework and is based on Java's reflection mechanism in implementation, which is an application of aspect-oriented programming (AOP). Since the interceptor is based on the call of the web framework, Spring's dependency injection (DI) can be used to perform some business operations. At the same time, an interceptor instance can be called multiple times within a controller life cycle.

2.2.Interceptors and filters

What is a filter?

Depends on servlet container. Based on function callbacks in implementation, almost all requests can be filtered, but the disadvantage is that a filter instance can only be called once when the container is initialized. The purpose of using filters is to perform some filtering operations, such as: modifying the character encoding in the filter; modifying some parameters of HttpServletRequest in the filter, including: filtering vulgar text, dangerous characters, etc.

 In short, an interceptor is a component that intercepts and processes requests during request processing. It can be used to implement some pre-processing, post-processing, request interception and filtering functions. It provides a flexible mechanism for unified processing and control of requests.

The difference between interceptors and filters

  • filter

    1. Filter belongs to Servlet technology and can be used in any web project.

    2.filter is mainly due to filtering all requests

    3.The execution time of filter is earlier than Interceptor

  • interceptor

    1.interceptor belongs to SpringMVC technology and must have a SpringMVC environment before it can be used.

    2.interceptor usually intercepts the processor Controller

    3.interceptor can only intercept requests processed by dispatcherServlet

2.3 Application scenarios and functions of interceptors
Permission verification: Interceptors can be used to verify user permissions, such as checking whether the user is logged in, whether he has permission to access a resource, etc. By intercepting requests and performing permission verification, the security of the system and the integrity of the data can be protected.

Logging: Interceptors can be used to record request and response log information, including requested URL, request parameters, processing time, response results, etc. By recording logs, system monitoring, troubleshooting, and performance optimization can be easily performed.

Parameter preprocessing: The interceptor can preprocess request parameters, such as verifying, converting, modifying, etc. parameters. This ensures the validity and consistency of request parameters and reduces the occurrence of errors and exceptions.

Exception handling: Interceptors can be used to uniformly handle exceptions that occur during the request process. By intercepting exceptions and handling them uniformly, you can provide a friendly error prompt page or return specific error information, improving the system's fault tolerance and user experience.

Cache control: Interceptors can be used to control the use of cache, such as determining whether to use cache based on the requested URL, parameters and other conditions, as well as the cache expiration time, etc. By intercepting requests and performing cache control, you can improve system performance and response speed.

Request redirection: The interceptor can redirect the request according to certain conditions and forward the request to other URLs or processors for processing. By intercepting requests and redirecting them, request forwarding, routing and process control can be achieved.

Unified processing: Interceptors can be used to implement some unified processing logic, such as unified encoding conversion, character set settings, response header settings, etc. for requests. By intercepting requests and processing them uniformly, the consistency and maintainability of the system can be improved.

        Interceptors are widely used in web development. They can intercept, process and modify requests, and implement functions such as permission verification, logging, parameter preprocessing, exception handling, cache control, request redirection and unified processing. By using interceptors, the security, stability, performance, and maintainability of the system can be improved.

 Create and use interceptors

Interceptor workflow

as the picture shows

package com.xzs.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...");
    }
}

 Configure interceptor

<mvc:interceptors>
        <bean class="com.xzs.interceptor.OneInterceptor"></bean>
</mvc:interceptors>

test 

 In sending the request, you can see the results obtained

The above is how to intercept if the interception is not successful.

 Change the true value of this code to false and the interception will be successful.

After the interception is successful, the following code will no longer be executed.

multiple interceptors

package com.xzs.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...");
    }
}

 Configuration

   <mvc:interceptors>
        <!--2) 多拦截器(拦截器链)-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.xzs.interceptor.OneInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/clz/**"/>
            <bean class="com.xzs.interceptor.TwoInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

 As can be seen multiple interceptions were made when I tested again

 Login interception case

Login blocker

package com.xzs.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 uname = (String) request.getSession().getAttribute("uname");
        if (uname == null || "".equals(uname)){
            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 {

    }
}

Front-end writing

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录界面</title>
</head>
<body>
<h1>登录界面</h1>
<form action="/login" method="post">
    账号:<input name="uname">
    <input type="submit">
</form>
</body>
</html>

 Login to the operation control layer

package com.xzs.web;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(HttpServletRequest req){
        String uname = req.getParameter("uname");
        HttpSession session = req.getSession();
        if ("zs".equals(uname)){
            session.setAttribute("uname",uname);
        }
        return "redirect:/clz/list";
    }

    @RequestMapping("/logout")
    public String logout(HttpServletRequest req){
        req.getSession().invalidate();
        return "redirect:/clz/list";
    }
}

test

Do not enter zs

Enter Zhang San 

 

 quit

Guess you like

Origin blog.csdn.net/weixin_72997875/article/details/132844260