English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Instance explanation of Spring Boot and custom interceptor

We have learned about filters before, but filters are for servlets, used in springmvc and spring boot. Functionally, they are not very convenient to use.

So let's learn about interceptors here.

I. The Execution Order of Interceptors

1. Table of Contents

2. Interceptor

In the interceptor, I added three (First, Two, Third), but the content is roughly the same.

package org.elvin.boot.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 FirstInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
    System.out.println("FirstInterceptor preHandle");
    return true;
  }
  @Override
  public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    System.out.println("FirstInterceptor postHandle");
  }
  @Override
  public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    System.out.println("FirstInterceptor afterCompletion");
  }
}

The preHandle method returns true to continue with the next execution.

Interceptor registration:

package org.elvin.boot.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class RegisterInterceptor extends WebMvcConfigurerAdapter {
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new FirstInterceptor());
    registry.addInterceptor(new TwoInterceptor());
    registry.addInterceptor(new ThirdInterceptor());
    super.addInterceptors(registry);
  }
}

To verify the execution order, thymeleaf was used here, and then the attributes passed from the background were accessed on the front end. When accessing, information would be printed to the console.

package org.elvin.boot.pojo;
public class Book {
  private String name ;
  public String getName() {
    System.out.println("view : Book's name is ") + name);
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

Controller:

package org.elvin.boot.Controller;
import org.elvin.boot.pojo.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("first")
public class FirstController {
  private String controllerPath = "first"/";
  @GetMapping("index")
  public String index(Model model){
    System.out.println("controller : FirstController index doing...");
    Book book = new Book();
    book.setName("spring boot");
    model.addAttribute("book", book);
    return controllerPath + "index";
  }
}

View:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">-8" />
  <title>Title</title>
</head>
<body>
  <h1 th:text="${book.name}"</h1>
</body>
</html>

At localhost:8080/first/When accessing the index, the response information will be output to the console.

Thus, you can see the execution order of a single interceptor.

1. The preHandle method executed before the controller method

2. Execute the controller's action method

3. Before parsing the view (if any), execute the interceptor's posthandle method after executing the action

4. Parse the view

5. After parsing, execute the afterCompletion method

When multiple interceptors are registered, the execution order is as shown in the figure above.

2. Implement interceptor to verify permissions

Similarly, first add the permission interceptor

package org.elvin.boot.interceptor;
import org.elvin.boot.annotation.NoLogin;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) throws Exception {
    HandlerMethod method = (HandlerMethod ) handle;
    Class<?> controllerType = method.getBeanType();
    if(method.getMethodAnnotation(NoLogin.class) != null || controllerType.getAnnotation(NoLogin.class) != null){
      return true;
    }
    HttpSession session = request.getSession();
    String token = (String)session.getAttribute("token");
    if(!StringUtils.isEmpty(token)){
      return true;
    }
    response.sendRedirect("/login/index");
    return false;
  }
  @Override
  public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  }
  @Override
  public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  }
}

Then register the permission interceptor

package org.elvin.boot.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class RegisterInterceptor extends WebMvcConfigurerAdapter {
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginInterceptor());
    super.addInterceptors(registry);
  }
}

Add the login controller to the controller, providing login page and logout method

package org.elvin.boot.Controller;
import org.elvin.boot.annotation.NoLogin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@NoLogin
@Controller
@RequestMapping("login")
public class LoginController {
  @Autowired
  private HttpServletRequest request;
  @Autowired
  private HttpServletResponse response;
  private String controllerPath = "login"/";
  //@NoLogin
  @GetMapping("index")
  public String index(){
    HttpSession session = request.getSession();
    session.setAttribute("token", "token");
    return controllerPath + "index";
  }
  //@NoLogin
  @PostMapping("checkOut")
  @ResponseBody
  public String checkOut(){
    HttpSession session = request.getSession();
    session.setAttribute("token", null);
    return "ok";
  }
}

I have created a NoLogin annotation here, which can be added to the Controller or action.

package org.elvin.boot.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoLogin {
}

There is no need for any content in the annotations.

Login Page (This login page is only used for logging out, so after visiting this page, it means that the login has been successful).

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">-8"/>
  <title>Title</title>
</head>
<body>
<div class="container">
  <input type="button" value="Log Out" id="checkOut"/>
</div>
<script th:src="@{/js/jquery}})-1.11.1.js}"></script>
<script th:inline="javascript">
  $(function () {
    $(".container").delegate("#checkOut", "click", function () {
      $.ajax({
        url: [[@{/login/checkOut}]],
        type: 'post',
        data: {},
        success: function (res) {
          if (res == "ok") {
            alert("Logout successful");
          }
        }
      });
    });
  });
</script>
</body>
</html>

Demonstration method of results:

First, open http: in the browser.//localhost:8080/login/the index page, and then visit http: in a new tab.//localhost:8080/first/the index page.

You will find that accessing first/when you are on the index, it is accessible.

At this time, in login/After clicking the logout button in the index page, refresh first/If you go to the index page, it will directly jump to the login page.

This is the full content shared by the editor about the example of string boot and custom interceptor, I hope it can be a reference for everyone, and I also hope everyone will support the呐喊 tutorial more.

Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to notice#w3Please send an email to codebox.com (replace # with @ when sending an email) to report any violations, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.

You May Also Like