经实验发现,当访问拦截器拦截的地址的时候都会经过拦截器。在拦截器中,返回true则放行,允许访问该地址;返回false,则拦截,不允许访问该地址,但可以在return前去设置要跳转的地址。
拦截器可以拦截请求和资源(就是一个访问静态资源的请求)!
17.1 在config包中创建拦截器对象LoginHandleInterceptor
该类继承了HandleInterceptor,并重写了里面的preHandle方法。拦截器通过判断session中的转发数据loginUser的值是否为空来判断是否对该请求进行拦截。如果为空,则说明需要拦截该请求,设置转发消息,并跳转和转发到其他地址。如果不为空,则放行。
package jiang.com.springbootstudy.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginHandleInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录成功后应该有用户的session
Object loginUser = request.getSession().getAttribute("loginUser");// 从request中拿session,从session中拿到名为loginUser的值
if (loginUser==null){ // 如果loginUser被赋予的值为空
request.setAttribute("msg","没有权限,请先登录"); // 在request中设置转发数据
request.getRequestDispatcher("/index.html").forward(request,response); //跳转到index.html。并转发request的数据到response
return false; // 拦截此请求
}else{
return true; // 放行此请求
}
}
}
17.2 修改LoginController类
当登录成功时,将loginUser传到session中,17.1的拦截器依据session的loginUser的值是否为空来判断是否拦截某个请求。
package jiang.com.springbootstudy.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model,
HttpSession session){
if (!StringUtils.isEmpty(username)&&"123456".equals(password)){
session.setAttribute("loginUser",username); //如果登录成功把loginUser放到session中,对应的值是username
return "redirect:/main.html"; // 每次要跳转到其他地址之前,先经过拦截器看看是否拦截该请求
}else {
model.addAttribute("msg","用户名或密码错误!");
return "index"; // 每次要跳转到其他地址之前,先经过拦截器,看看是否拦截该请求
}
}
}
17.3 修改config包中的MyMvcConfig配置类
重写WebMvcConfigurer的addInterceptor方法。该方法可以设置需要拦截的请求以及放行的请求。通过调用registry的addInterceptor方法新建一个17.1的拦截器作为入参传入,然后调用addPathPatterns方法填入需要拦截的请求,最后调用excludePathPatterns方法填入运行放行的请求,请求之间用逗号隔开。
package jiang.com.springbootstudy.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index"); //setViewName后面不用加html
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard"); // 前面的main.html是假的,只是一种请求,后面才是真的,输入请求后会跳转的地方是后面的html
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandleInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/user/login","/","/css/**","/img/**","/js/**"); // 拦截所有请求,放行index.html、user/login请求、/请求以及静态资源(看成是请求就行)
}
}
17.4 拦截器使用
访问一个拦截的地址:local:8080/main.html:
访问一个放行地址:正常放行。
当输入错误的密码,点击sign in会跳转到local:8080/user/login,由于local:8080/user/login地址是运行通行的,在登录成功时,会跳转到local:8080/main.html页面,在登录失败的时候会跳转到local:8080/index页面,这两个跳转的页面都是运行通行的,不会经过拦截器。