拦截器在项目中经常用到,可以用来拦截一些非法 Action 请求或是对 Action 请求进行一些预处理或后处理等,使得业务更符合实际需求,也可以在一定程度上保证系统的安全性。
下面以登录功能为例,演示拦截器的基本用法
登录页绑定登录地址
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="favicon.ico">
<title>Signin Template</title>
<!-- Bootstrap core CSS -->
<link href="dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/signin.css" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" th:action="@{/login}" method="post">
<img class="mb-4" src="dist/brand/bootstrap-solid.svg" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.top}">Please sign in</h1>
<p style="color:red;" th:text="${failMsg}" th:if="${not #strings.isEmpty(failMsg)}"></p>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" name="username" id="inputEmail" class="form-control" th:placeholder="#{login.username}" placeholder="Username" required autofocus>
<label for="inputPassword" class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" th:placeholder="#{login.password}" placeholder="Password" required>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> [[#{login.remember}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<a class="btn btn-sm" th:href="@{/index.html(lan='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(lan='en_US')}">English</a>
</form>
</body>
</html>
controller 层
为了防止重复提交,用了转发请求,并且做了视图映射
@PostMapping(value="/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Map<String, Object>map, HttpSession session) {
if(!StringUtils.isEmpty(username) && "xiao".equals(password)) {
session.setAttribute("username", username);
// 防止表单重复提交,重定向
return "redirect:/home.html";
}else {
map.put("failMsg", "用户名密码错误");
return "index";
}
}
视图映射,把 /home.html 请求映射到 dashboard 页面
另外,在 springboot2.1.4 的 WebMvcConfigurationSupport 中,会拦截静态资源,所以要有放行静态资源的操作。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import com.xiao.component.DefineLocalResolver;
import com.xiao.component.LoginInterceptor;
@Configuration
public class MyConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
// 绑定静态资源
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/","classpath:/public/");
super.addResourceHandlers(registry);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) { // 请求映射
// 浏览器发送 /pass 请求,来到 success 页面
registry.addViewController("/pass").setViewName("success");
registry.addViewController("/home.html").setViewName("dashboard");
}
@Bean
public LocaleResolver localeResolver() { // 注入自定义组件
return new DefineLocalResolver();
}
@Override
protected void addInterceptors(InterceptorRegistry registry) { // 添加拦截器
// 定义要拦截和放行的请求、资源
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/","/index","/css/**","/dist/**");
super.addInterceptors(registry);
}
}
定义一个登录页面的拦截器,上面的配置类已经添加到容器中了。
HandlerInterceptor 接口的方法都是 default 类型的,是默认实现的方法,(java8 开始的新特性)需要实现的方法可以自己去接口中找。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* 登录检查
* @author Xiaogf
*/
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
Object username = request.getSession().getAttribute("username");
if(username == null) {
//未登录,转发到登录页
request.setAttribute("failMsg", "未登录或登录过时,请登录");
request.getRequestDispatcher("/index").forward(request, response);
return false;
}else {
return true;
}
}
}
以上就实现了登录功能的请求拦截。
直接输入 /home.html 请求是不能访问主页的,未登录就不能访问主页。
输入用户名和正确的密码后,登录就可以访问主页了
版权声明:本文为Alias_fa原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。