1.过滤器
配置在web.xml中。依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等,最常用的过滤字符串的拦截器。
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
1.自定义过滤器
我们还可以自定义过滤器,以下一个登陆过滤器。
@RequestMapping(value="/login",method=RequestMethod.GET) public String login(HttpServletRequest request,HttpServletResponse response){ //获取Cookie Cookie[] cookies = request.getCookies(); for(Cookie cookie : cookies){ System.out.println("cookie>>"+cookie.getValue()); //从数据库获取保存的cookie Session session = iSessionDAO.getSession(cookie.getValue()); if(session!=null){ //如果存在,就跳转到首页 return "index"; } } return "login"; } @RequestMapping(value="/login",method=RequestMethod.POST) public String loginPOST(HttpServletRequest request, HttpServletResponse response,Model model){ //用户名 String username=request.getParameter("username"); System.out.println("username>>>"+username); //密码 String password=request.getParameter("password"); System.out.println("password>>>"+password); //先从数据库查找该账号信息 User user = null; try { user = iUserDAO.queryForUser(username); } catch (NullPointerException e) { e.printStackTrace(); model.addAttribute("message", "No account"); } if(user==null){ model.addAttribute("message", "No account"); }else{ // 匹配密码 if (user.getPassword().equals(password)) { //登录成功,保存session request.getSession().setAttribute("user", user); // 保存cookie Cookie[] cookies = request.getCookies(); Cookie cookie = cookies[0];//获得最新的那个cookie Session isSession = iSessionDAO.getSessionByUserId(user.getId()); //没有session,就添加 if(isSession==null){ Session session = new Session(); session.setId(UUID.randomUUID().toString()); session.setSession(cookie.getValue()); session.setUser_id(user.getId()); System.out.println("cookie>>" + cookie.getValue()); iSessionDAO.save(session); System.out.println("==添加session=="); }else{ //如果已经有session,就更新 isSession.setSession(cookie.getValue()); iSessionDAO.update(isSession); System.out.println("==更新session=="); } model.addAttribute("message", user.getUsername()); return "index"; }else{ model.addAttribute("message", "Wrong password"); } } return "login"; } @RequestMapping(value="/sessionTest",method=RequestMethod.GET) public String sessionTest(HttpServletRequest request,HttpServletResponse response,Model model){ System.out.println(">>>sessionTest"); model.addAttribute("message", "sessionTest"); return "index"; }
2.如何配置
在使用中,需要在web.xml中配置才生效。
<filter> <description>session过滤器</description> <filter-name>sessionFilter</filter-name> <filter-class>com.mocha.filter.SessionFilter</filter-class> </filter> <filter-mapping> <filter-name>sessionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2.拦截器
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
1.实现方式
- 通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义。
- 通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义。
以下是一个拦截器。
2.代码实现
@Component public class HandlerInterceptor extends HandlerInterceptorAdapter { public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("11111111"); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("222222222"); } public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("44444"); return true; } }
同时也需要在mvc的配置文件中加入配置。
<mvc:interceptors> <mvc:interceptor> <!--配置拦截器的作用路径 --> <mvc:mapping path="/**" /> <!--定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截 --> <bean class="com.HandlerInterceptor" /> </mvc:interceptor> </mvc:interceptors>
3.监听器
监听器是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或者属性改变,当被监听对象发生上述事件后,监听器某个方法将立即执行。
监听器用于监听web应用中某些对象、信息的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。常用于统计在线人数和在线用户,系统加载时进行信息初始化,统计网站的访问量等等。或者在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,那就是事件监听,事件监听也是设计模式中 发布-订阅模式、观察者模式的一种实现。
1.代码实现
监听事件
import org.springframework.context.ApplicationEvent; public class MyTestEvent extends ApplicationEvent{ /** * */ private static final long serialVersionUID = 1L; private String msg ; public MyTestEvent(Object source,String msg) { super(source); this.msg = msg; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
定义监听器
import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; import com.mu.event.MyTestEvent; @Component public class MyNoAnnotationListener implements ApplicationListener<MyTestEvent>{ @Override public void onApplicationEvent(MyTestEvent event) { System.out.println("非注解监听器:" + event.getMsg()); } }
事件发布
package com.mu.event; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @Component public class MyTestEventPubLisher { @Autowired private ApplicationContext applicationContext; // 事件发布方法 public void pushListener(String msg) { applicationContext.publishEvent(new MyTestEvent(this, msg)); } }
调用
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.mu.event.MyTestEventPubLisher; @Controller public class TestEventListenerController { @Autowired private MyTestEventPubLisher publisher; @RequestMapping(value = "/test/testPublishEvent1" ) public void testPublishEvent(){ publisher.pushListener("我来了!"); } }
也可以使用注解实现
import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import com.mu.event.MyTestEvent; @Component public class MyAnnotationListener { @EventListener public void listener1(MyTestEvent event) { System.out.println("注解监听器1:" + event.getMsg()); } }
4.过滤器与拦截器的区别
过滤器可以简单的理解为“取你所想取”,过滤器关注的是web请求;拦截器可以简单的理解为“拒你所想拒”,拦截器关注的是方法调用,比如拦截敏感词汇。
- 拦截器是基于java反射机制来实现的,而过滤器是基于函数回调来实现的。(有人说,拦截器是基于动态代理来实现的)
- 拦截器不依赖servlet容器,过滤器依赖于servlet容器。
- 拦截器只对Action起作用,过滤器可以对所有请求起作用。
- 拦截器可以访问Action上下文和值栈中的对象,过滤器不能。
- 在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时调用一次。
5.AOP与拦截器的区别
Filter过滤器:拦截web访问url地址。
Interceptor拦截器:拦截以 .action结尾的url,拦截Action的访问。
Spring AOP拦截器:只能拦截Spring管理Bean的访问(业务层Service)
拦截顺序:监听器>filter—>Interceptor—->@Aspect
aop与拦截器的实现方式都是动态代理实现的。