上篇我们讲了Spring Boot拦截器:https://blog.csdn.net/stronglyh/article/details/80980070,还有个大家容易混淆的概念,叫过滤器,有哪些区别呢
①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。拦截器可以获取ioc中的service bean实现业务逻辑,拦截器可以获取ioc中的service bean实现业务逻辑,拦截器可以获取ioc中的service bean实现业务逻辑,
1.过滤器和拦截器触发时机不一样:
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
1.过滤器和拦截器触发时间和地点不一样:
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
1.过滤器和拦截器触发时间和地点不一样:
过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
=================================实战代码==================================
举例:
定义一个过滤器,当用户访问一个页面时,判断用户是否是登录状态,如果是则跳转到对应的页面,如果不是则跳转到登录页
这个地方不使用数据库,直接硬编码,其中代码结构如下
TestFilterConfig.java
package com.example.smybatis.configurer;
import com.example.smybatis.filters.testFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestFilterConfig {
@Bean
public FilterRegistrationBean someFilterRegistration1() {
//新建过滤器注册类
FilterRegistrationBean registration = new FilterRegistrationBean();
// 添加我们写好的过滤器
registration.setFilter( new testFilter());
// 设置过滤器的URL模式
registration.addUrlPatterns("/*");
return registration;
}
}
testC.java
package com.example.smybatis.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
public class testC {
@GetMapping(value="/test")
public Integer test(){
return 111;
}
@RequestMapping("login")
public String login(String name,String pwd,HttpServletRequest request) {
HttpSession session = request.getSession();
if(name.equals("test")&&pwd.equals("test123")) {
session.setAttribute("user",name);
return "登录成功";
} else {
return "用户名或密码错误!";
}
}
}
testFilter.java
package com.example.smybatis.filters;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class testFilter implements Filter {
//标示符:表示当前用户未登录(可根据自己项目需要改为json样式)
String NO_LOGIN = "您还未登录";
//不需要登录就可以访问的路径(比如:注册登录等)
String[] includeUrls = new String[]{"/login","/register","/login.html"};
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession(false);
String uri = request.getRequestURI();
System.out.println("filter url:"+uri);
//是否需要过滤
boolean needFilter = isNeedFilter(uri);
if (!needFilter) { //不需要过滤直接传给下一个过滤器
filterChain.doFilter(servletRequest, servletResponse);
} else { //需要过滤器
// session中包含user对象,则是登录状态
if(session!=null&&session.getAttribute("user") != null){
// System.out.println("user:"+session.getAttribute("user"));
filterChain.doFilter(request, response);
}else{
String requestType = request.getHeader("X-Requested-With");
//判断是否是ajax请求(因为ajax页面不跳转,所以这块需要判断一下)
if(requestType!=null && "XMLHttpRequest".equals(requestType)){
response.getWriter().write(this.NO_LOGIN);
}else{
//重定向到登录页(需要在static文件夹下建立此html文件)
response.sendRedirect(request.getContextPath()+"/login.html");
}
return;
}
}
}
/**
* @Description: 是否需要过滤
*/
public boolean isNeedFilter(String uri) {
for (String includeUrl : includeUrls) {
if(includeUrl.equals(uri)) {
return false;
}
}
return true;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
ceshi.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<h1>这是测试页面</h1>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<h1>这是登录页面</h1>
</body>
</html>
下面我们做几个测试
首先在浏览器输入http://localhost:1234/ceshi.html
结果跳转到了http://localhost:1234/login.html
这是因为拦截器生效了,判断用户没有登录态,则默认跳转到登录页面
接下来,我们先登录
1)登录成功了,则有登录态了
我们再访问http://localhost:1234/ceshi.html
ok,可以
2)我们再次登录,估计输错密码
3)这个时候浏览器输入http://localhost:1234/ceshi.html,我们发现又跳转到了登录页,这是因为session中没有用户的情况
====================多个过滤器排序=================
需要在配置java类中加入排序即可:registration.setOrder(1);
TestFilterConfig.java
package com.example.smybatis.configurer;
import com.example.smybatis.filters.testFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestFilterConfig {
@Bean
public FilterRegistrationBean someFilterRegistration1() {
//新建过滤器注册类
FilterRegistrationBean registration = new FilterRegistrationBean();
// 添加我们写好的过滤器
registration.setFilter( new SessionFilter());
// 设置过滤器的URL模式
registration.addUrlPatterns("/*");
//设置过滤器顺序
registration.setOrder(1);
return registration;
}
}