案例
过滤器
过滤器filter是servlet技术中心最实用的技术。过滤器是处于客户端与服务器资源文件之间的一道过滤网,过滤一些不符合要求的请求。通常他被用作Session校验,判断用户权限,如果不符合设定条件,就会被拦截到特殊的地址或者给予特殊的响应。
使用过滤器只需要实现Filter类
init方法:在容器中创建当前过滤器的时候自动调用这个方法。
destroy方法:在容器中销毁当前过滤器的时候自动调用这个方法
doFilter方法:这个方法有3个参数,分别是ServletRequest、ServletResponse和FilterChain。可以从参数中获取HttpServletRequest和HttpServletResponse对象进行相应的处理操作。
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("MyFilter被调用");
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponseWrapper httpServletResponseWrapper = new HttpServletResponseWrapper((HttpServletResponse) response);
//只有符合条件的可以直接请求,不符合的跳转到/online请求中
String requestURI = httpServletRequest.getRequestURI();
System.out.println("请求的地址是:"+requestURI);
if(requestURI.indexOf("/addSession")!=-1
|| requestURI.indexOf("/removeSession")!=-1
|| requestURI.indexOf("/online")!=-1
|| requestURI.indexOf("favicon.ico")!=-1) {
chain.doFilter(request, response);
}else {
httpServletResponseWrapper.sendRedirect("/online");
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
//服务关闭时销毁
System.out.println("销毁拦截器");
Filter.super.destroy();
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
//服务启动时初始化
System.out.println("初始化拦截器");
Filter.super.init(filterConfig);
}
}
拦截器
java中的拦截器是动态拦截action调用的对象,然后提供了可以在action执行前后增加一些操作,也可以在action执行前停止操作。
登录认证:在一些简单的应用中,可能会通过拦截器来验证用户的登录状态,如果没有登录或者登录失效,就会给用户一个友好的提示或者返回登录页面。
记录系统日志:在web应用中,通常需要记录用户的请求信息,比如请求的IP、方法执行时常等,通过这些记录可以监控系统的状况,以便于对系统进行信息监控、信息统计、计算PV(page view)和性能调优等。
通用处理:在应用程序中可能存在所有方法都要返回的信息,这时可以使用拦截器来实现,省去每个方法冗余重复的代码实现。
这里以使用Spring拦截器为例,在类上需要实现HandlerInterceptor类,并且重写类中的3个方法,分别是:
preHandle:在业务处理器处理请求之前被调用,返回值是boolean值,如果返回true,就进行下一步操作;若返回false,则证明不符合拦截条件。在失败的时候不会包含任何响应,此时需要调用对应的response返回对应响应。
postHandle:在业务处理器处理请求执行完成后、生成视图前执行。这个方法可以通过方法参数ModelAndView对视图进行处理,当然ModelAndView也可以设置为null。
afterCompletion:在DispatcherServlet完全处理请求后被调用,通常用于记录消耗时间,也可以进行一些资源处理操作。
@Component
public class MyIntercepter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
System.out.println("preHandle被调用");
request.setAttribute("startTime", System.currentTimeMillis());
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("postHandle被调用");
HttpSession session = request.getSession();
String name = (String) session.getAttribute("name");
if ("test".equals(name)) {
System.out.println("------------------------------当前浏览器存在session");
}
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("afterCompletion被调用");
long startTime = (long) request.getAttribute("startTime");
System.out.println("------------------------------请求耗时:"+(System.currentTimeMillis() - startTime));
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
监听器
监听器通常用于监听web应用中对象的创建、销毁等动作的发生,同时对监听的情况作出相应的处理,最常用于统计网站的在线人数、访问量等信息。
监听器大致分为以下几种:
ServletContextListerner:用来监听ServletContext属性的操作,比如新增、修改、删除
HttpSessionListerner:用来监听web应用中的Session对象,通常用于统计在线情况
ServletRequestListerner:用来监听Request对象的属性操作
使用监听器的话,只需要在类中实现对应功能的监听器对象。下面以Session信息为例统计在线人数。新建一个MyHttpSessionListener类,实现HttpSessionListener类,在类中定义一个全局变量online。当创建Session时,online的数量加1;当销毁Session时,online的数量减1.
package com.example.chapter10_4.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MyHttpSessionListener implements HttpSessionListener {
public static int online = 0;
@Override
public void sessionCreated(HttpSessionEvent se) {
// TODO Auto-generated method stub
System.out.println("sessiononCreated被调用");
online++;
HttpSessionListener.super.sessionCreated(se);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// TODO Auto-generated method stub
System.out.println("sessionDestroyed被调用");
online--;
HttpSessionListener.super.sessionDestroyed(se);
}
}
SpringBoot引用三器
package com.example.chapter10_4.main;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.example.chapter10_4.filter.MyFilter;
import com.example.chapter10_4.intercepter.MyIntercepter;
import com.example.chapter10_4.listener.MyHttpSessionListener;
@SpringBootApplication(scanBasePackages = "com.example.chapter10_4")
@ComponentScan(basePackages = "com.example.chapter10_4")
public class Chapter114Application implements WebMvcConfigurer{
public static void main(String[] args) {
SpringApplication.run(Chapter114Application.class, args);
}
@Autowired
public MyIntercepter myIntercepter;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// TODO Auto-generated method stub
registry.addInterceptor(myIntercepter);
WebMvcConfigurer.super.addInterceptors(registry);
}
@Bean
public FilterRegistrationBean<MyFilter> filterRegist() {
FilterRegistrationBean<MyFilter> frBean = new FilterRegistrationBean<MyFilter>();
frBean.setFilter(new MyFilter());
frBean.addUrlPatterns("/*");
return frBean;
}
@Bean
public ServletListenerRegistrationBean<MyHttpSessionListener> listRegist() {
ServletListenerRegistrationBean<MyHttpSessionListener> srb = new ServletListenerRegistrationBean<MyHttpSessionListener>();
srb.setListener(new MyHttpSessionListener());
return srb;
}
}
测试
package com.example.chapter10_4.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.chapter10_4.listener.MyHttpSessionListener;
@RestController
public class TestController {
@GetMapping("/addSession")
public String addSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute("name", "test");
return "当前在线人数"+MyHttpSessionListener.online;
}
@GetMapping("/removeSession")
public String removeSession(HttpServletRequest request) {
HttpSession session = request.getSession();
session.invalidate();
return "当前在线人数"+MyHttpSessionListener.online;
}
@GetMapping("/online")
public String online() {
return "当前在线人数"+MyHttpSessionListener.online+"人";
}
}
启动项目,测试步骤如下:
- 使用浏览器访问http://localhost:8080/online,可以看到浏览器提示“当前在线人数0人”(拦截器成功)
- 多次使用浏览器访问http://localhost:8080/addSession,可以看到浏览器提示“当前在线人数1人”(监听器成功)
- 更换浏览器,访问http://localhost:8080/addSession,可以看到浏览器提示“当前在线人数2人”
- 多次使用浏览器访问http:localhost:8080/removeSession,可以看到浏览器提示“当前在线人数1人”
- 使用浏览器访问不存在的地址,会自动跳转到http://localhost:8080/online(过滤器成功)