15.1 基本介绍
-
在 Spring Boot 项目中, 拦截器是开发中常用手段,要来做登陆验证、性能检查、日志记录等
-
基本步骤:
① 编写一个拦截器实现 HandlerInterceptor 接口
② 拦截器注册到配置类中(实现 WebMvcConfigurer 的 addInterceptors)
③ 指定拦截规则
④ 回顾 SpringMVC ==> 文章链接
15.2 拦截器应用实例
15.2.1 需求说明
- 使用拦截器防止用户非法登录
- 如图 - 使用拦截器就不需要在每个方法验证了
- 浏览器输入 http://localhost:8080/manage.html
- 如果用户没有登录,则返回登录界面
15.2.2 代码实现
- 创建 D:\xjs_springboot\springboot-usersys\src\main\java\com\xjs\springboot\interceptor\LoginInterceptor.java
package com.xjs.springboot.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
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;
/**
* @Author: 谢家升
* @Version: 1.0
*/
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 目标方法执行前被调用
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1. 获取访问的 URI
String uri = request.getRequestURI();
log.info("preHandle拦截到的请求的URI={}", uri);
//2. 进行登录校验
HttpSession session = request.getSession();
Object loginAdmin = session.getAttribute("loginAdmin");
if (null != loginAdmin) {//说明该用户已经成功登录过了
return true;
} else {//说明该用户还没成功登录过
//拦截,重新返回到登录页面
request.setAttribute("msg", "你没有登录/请登录~~");
request.getRequestDispatcher("/").forward(request, response);
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle() 执行了...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion() 执行了...");
}
}
- 创建 D:\xjs_springboot\springboot-usersys\src\main\java\com\xjs\springboot\config\WebConfig.java
package com.xjs.springboot.config;
import com.xjs.springboot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: 谢家升
* @Version: 1.0
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器LoginInterceptor
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //这里拦截所有的请求
.excludePathPatterns("/","/login","/images/**"); //指定要放行的,根据业务需要来添加放行的请求路径
}
}
- 修改 D:\xjs_springboot\springboot-usersys\src\main\java\com\xjs\springboot\controller\AdminController.java ,去掉 session 验证用户是否登录代码,并完成测试,注意看页面和后台日志
package com.xjs.springboot.controller;
import com.xjs.springboot.bean.Admin;
import com.xjs.springboot.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
/**
* @Author: 谢家升
* @Version: 1.0
*/
@Controller
@Slf4j
public class AdminController {
//响应用户的登录请求
@PostMapping("/login")
public String login(Admin admin, HttpSession session, Model model) {
//验证用户是否合法
if (StringUtils.hasText(admin.getName()) && "888".equals(admin.getPassword())) {
//将登录用户保存到session
session.setAttribute("loginAdmin", admin);
/**合法 重定向到 manage.html
* 1. 不使用请求转发是防止刷新页面会导致表单重复提交
* 2. 这里为什么写的是 manage.html 因为这样可以更加明确的表示到哪个页面
* 3. 这里的 manage.html 表示要去找 方法的映射路径为 manage.html
*/
return "redirect:/manage.html";
} else {
//不合法 重新登录!
model.addAttribute("msg", "账号/用户名错误");
return "adminLogin";
}
}
//处理用户请求 manage.html
@GetMapping("/manage.html")
public String mainPage(Model model, HttpSession session) {
这里暂时在方法中使用session验证,后面我们统一使用拦截器验证
//Object loginAdmin = session.getAttribute("loginAdmin");
//
//if (loginAdmin != null) { //说明成功登录过
// //这里集合-模拟用户数据,放入到request域中,并显示
// ArrayList<User> users = new ArrayList<>();
// users.add(new User(1, "关羽", "123456", 20, "gy@sohu.com"));
// users.add(new User(2, "张飞", "123456", 26, "zf@sohu.com"));
// users.add(new User(3, "赵云", "123456", 28, "zy@sohu.com"));
// users.add(new User(4, "马超", "123456", 22, "mc@sohu.com"));
// users.add(new User(5, "黄忠", "123456", 50, "hz@sohu.com"));
//
// //将数据放入到request域中
// model.addAttribute("users", users);
//
// return "manage"; //这里才是我们的视图解析到 /template/manage.html
//} else {
// //这里就返回登录页面,并给出提示
// model.addAttribute("msg", "你没有登录/请登录");
//
// return "adminLogin"; //请求转发到 adminLogin.html
//}
log.info("进入mainPage()");
//这里集合-模拟用户数据,放入到request域中,并显示
ArrayList<User> users = new ArrayList<>();
users.add(new User(1, "关羽", "123456", 20, "gy@sohu.com"));
users.add(new User(2, "张飞", "123456", 26, "zf@sohu.com"));
users.add(new User(3, "赵云", "123456", 28, "zy@sohu.com"));
users.add(new User(4, "马超", "123456", 22, "mc@sohu.com"));
users.add(new User(5, "黄忠", "123456", 50, "hz@sohu.com"));
//将数据放入到request域中
model.addAttribute("users", users);
return "manage"; //这里才是我们的视图解析到 /template/manage.html
}
}
15.2.3 注意事项和细节
- URI 和 URL 的区别
- URI = Universal Resource Identifier
- URL = Universal Resource Locator
- Identifier:标识符
- Locator:定位器
- 从字面上来看,URI 可以唯一标识一个资源,URL 可以提供找到该资源的路径
- 举例说明:
String requestURI = request.getRequestURI();
String requestURL = request.getRequestURL().toString();
- 注册拦截器,依然可以使用如下方式
package com.xjs.springboot.config;
import com.xjs.springboot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: 谢家升
* @Version: 1.0
*/
@Configuration
public class WebConfig /*implements WebMvcConfigurer*/ {
//@Override
//public void addInterceptors(InterceptorRegistry registry) {
//
// //注册自定义拦截器LoginInterceptor
// registry.addInterceptor(new LoginInterceptor())
// .addPathPatterns("/**") //这里拦截所有的请求
// .excludePathPatterns("/","/login","/images/**"); //指定要放行的,根据业务需要来添加放行的请求路径
//
//}
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/", "/login", "/images/**");
}
};
}
}