过滤器(Filter)文件
MyFilter.java
package org.springboot.sample.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
/**
* 使用注解标注过滤器
* @WebFilter将一个实现了javax.servlet.Filter接口的类定义为过滤器
* 属性filterName声明过滤器的名称,可选
* 属性urlPatterns指定要过滤 的URL模式,也可使用属性value来声明.(指定要过滤的URL模式是必选属性)
*
* @author 单红宇(365384722)
* @myblog http://blog.csdn.net/catoop/
* @create 2016年1月6日
*/
@WebFilter(filterName="myFilter",urlPatterns="/*")
public class MyFilter implements Filter {
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("执行过滤操作");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("过滤器初始化");
}
}
ServletContext监听器(Listener)文件
MyServletContextListener.java
package org.springboot.sample.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* 使用@WebListener注解,实现ServletContextListener接口
*
* @author 单红宇(365384722)
* @myblog http://blog.csdn.net/catoop/
* @create 2016年1月6日
*/
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContex初始化");
System.out.println(sce.getServletContext().getServerInfo());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContex销毁");
}
}
ServletContext监听器(Listener)文件
MyHttpSessionListener.java
package org.springboot.sample.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* 监听Session的创建与销毁
*
* @author 单红宇(365384722)
* @myblog http://blog.csdn.net/catoop/
* @create 2016年1月6日
*/
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("Session 被创建");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("ServletContex初始化");
}
}
注意不要忘记在 SpringBootSampleApplication.java 上添加 @ServletComponentScan 注解。
在启动的过程中我们会看到输出:
ServletContex初始化
Apache Tomcat/8.0.30
过滤器初始化
服务启动后,随便访问一个页面,会看到输出:
执行过滤操作
Session 被创建
补充
很多人说HttpSessionListener没有不能执行 ,自己验证后springboot如果只是若原作者说的配置的话,确实没调用。
只有经过DispatcherServlet 的请求, 才会调用httpsessionlistener
用如下方法,session的创建,可以触发httpsessionlistener
@RequestMapping("/login")
public String loginHtml(HashMap<String,Object> map, HttpServletRequest request, HttpServletResponse response ){
request.getSession().setAttribute("name","XXX");
String text = request.getParameter("name");
map.put("hello",text);
// return new ModelAndView("redirect:/hello");
return"/hello";
}
页面请求后,会触发后台打印 “Session 被创建”
====补充=============================================
假设客户端在http请求中,已经加入了Header的认证信息,例如:
[java] view plain copy
HttpPost post = new HttpPost(“http://localhost:8990/sendMail“);
StringEntity entity = new StringEntity(json, “utf-8”);
entity.setContentType(“application/json”);
post.setEntity(entity);
// 设置验证头信息
post.addHeader(“token”, “WEFGYHJIKLTY4RE6DF29HNBCFD13ER87”);
那么服务端怎么通过Filter,来验证客户端的token是否有效了?请接着往下看。
一、实现自定义Filter
1、实现Filter接口
我们要自定义Filter,只需实现Filter接口即可
2、覆写doFilter方法
根据业务逻辑,来覆写doFilter方法
示例如下:
[java] view plain copy
@Slf4j
@Component
@WebFilter(urlPatterns={“/sendMail/*”}, filterName=”tokenAuthorFilter”)
public class TokenAuthorFilter implements Filter {
@Autowired
private AuthorizationRepository repository;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
String token = req.getHeader("token");
Response res = new Response();
boolean isFilter = false;
if (null == token || token.isEmpty()) {
res.setSuccess(false);
res.setErrorCode("403");
res.setErrorMessage("token没有认证通过!原因为:客户端请求参数中无token信息");
} else {
Authorization auth = repository.findByToken(token);
if (null == auth) {
res.setSuccess(false);
res.setErrorCode("403");
res.setErrorMessage("token没有认证通过!原因为:客户端请求中认证的token信息无效,请查看申请流程中的正确token信息");
}else if((auth.getStatus() == 0)){
res.setSuccess(false);
res.setErrorCode("401");
res.setErrorMessage("该token目前已处于停用状态,请联系邮件系统管理员确认!");
}else{
isFilter = true;
res.setSuccess(true);
}
}
if(!res.isSuccess()){
PrintWriter writer = null;
OutputStreamWriter osw = null;
try {
osw = new OutputStreamWriter(response.getOutputStream() , "UTF-8");
writer = new PrintWriter(osw, true);
String jsonStr = ObjectMapperInstance.getInstance().writeValueAsString(res);
writer.write(jsonStr);
writer.flush();
writer.close();
osw.close();
} catch (UnsupportedEncodingException e) {
log.error("过滤器返回信息失败:" + e.getMessage(), e);
} catch (IOException e) {
log.error("过滤器返回信息失败:" + e.getMessage(), e);
} finally {
if (null != writer) {
writer.close();
}
if(null != osw){
osw.close();
}
}
return;
}
if(isFilter){
log.info("token filter过滤ok!");
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
通过上面的几步,就实现了一个自定义的Filter。
3、注册Filter
接下来,需要注册这个过滤器,spring boot提供了以下两种注册方式。
3.1 是用注解注册
在Filter上添加如下注解即可
[java] view plain copy
@Slf4j
@Component
@WebFilter(urlPatterns={“/sendMail/*”}, filterName=”tokenAuthorFilter”)
public class TokenAuthorFilter implements Filter {
@WebFilter注解的作用就是用来注册Filter,通过这种方式注册的Filter,需要在启动类上加上@ServletComponentScan注解才能生效,如下:
[java] view plain copy
@ServletComponentScan
public class MailserviceApplication {
public static void main(String[] args) {
SpringApplication.run(MailserviceApplication.class, args);
}
}
3.2 手动配置Filter
[java] view plain copy
@Configuration
@Component
public class FilterConfig {
@Autowired
private TokenAuthorFilter filter;
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
List<String> urlPatterns = new ArrayList<String>();
urlPatterns.add("/sendMail/*");// 设置匹配的url
registrationBean.setUrlPatterns(urlPatterns);
return registrationBean;
}
}
上面两种方式虽然使用上有些不一样,但是本质都是一样的,都会调用FilterRegistrationBean来进行注册。
二、spring boot内置的Filter
为了方便我们的开发,spring boot内置了许多有用的Filter,我们可以根据业务的需求,选择适合业务的Filter。
三、拓展
通过前面的N篇博客,我们会发现spring boot处理Servlet,Listener,Filter的思路大致都是一样,对应的注解分别为@WebServlet 、@WebListener、@WebFilter,对应的注册Bean分别为ServletRegistrationBean,ServletListenerRegistrationBean,FilterRegistrationBean,无论哪种方式,都大大的简化了我们的开发