Listener监听器和Filter过滤器
Listener监听器
WEB中的监听器
WEB 中的 Listener 和 Filter 是属于 Servlet 规范中的高级的技术.
WEB中的监听器共有三类八种(监听三个域对象)
* 事件源:Servlet 中的三个域对象.ServletContext,HttpSession,ServletRequest.
* 监听器:自定义类实现8个接口.
* 事件源和监听器的绑定:配置.
监听器的分类
三类八种:
* 一类:监听三个域对象的创建和销毁的监听器
* ServletContextListener
* HttpSessionListener
* ServletRequestListener
* 二类:监听三个域对象的属性变更的监听器(属性添加,移除,替换)
* ServletContextAttributeListener
* HttpSessionAttributeListener
* ServletRequestAttributeListener
* 三类:监听HttpSession中的 JavaBean 的状态改变(绑定,解除绑定,钝化,活化)
* HttpSessionBindingListener
* HttpSessionActivationListener
WEB中的监听器的使用
编写一个类实现监听器的接口;
通过配置文件配置监听器;
一类:监听三个域对象的创建和销毁的监听器
ServletContextListener:监听ServletContext对象的创建和销毁
方法
void contextDestroyed(ServletContextEvent sce)
Notification that the servlet context is about to be shut down.
void contextInitialized(ServletContextEvent sce)
Notification that the web application initialization process is starting.
ServletContext 对象的创建和销毁
创建:服务器启动的时候,服务器为每个WEB应用创建一个属于该web项目的对象ServletContext.
销毁:服务器关闭或者项目从服务器中移除的时候.
应用
public class MyServletContextListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象被创建了...");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象被销毁了...");
}
}
配置:
<!-- 配置监听器 -->
<listener>
<listener-class>com.boomoom.weblistener.MyServletContextListener</listener-class>
</listener>
企业中的应用
1、加载框架的配置文件: Spring框架 ContextLoaderListener
2、定时任务调度:java.util.Timer,java.util.TimerTask
Timer的方法
void schedule(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定延迟执行。
void schedule(TimerTask task, long delay)
安排在指定延迟后执行指定的任务。
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定速率执行。
void scheduleAtFixedRate(TimerTask task, long delay, long period)
安排指定的任务在指定的延迟后开始进行重复的固定速率执行。
ServletContextListener执行任务调度
public class MyServletContextListener implements ServletContextListener{ @Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象被创建了...");
Timer timer = new Timer();
/*Calendar calendar = Calendar.getInstance();
calendar.set(2016,3,11,10,18,00);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("发送邮件:");
}
}, calendar.getTime(), 5000);*/
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("发送邮件:");
}
}, 10000, 2000);
} @Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象被销毁了...");
}
}
HttpSessionListener:监听HttpSession的创建和销毁的监听器
方法
void sessionCreated(HttpSessionEvent se)
Notification that a session was created.
void sessionDestroyed(HttpSessionEvent se)
Notification that a session is about to be invalidated.
HttpSession何时创建和销毁
* 创建:服务器端第一次调用getSession();
* 销毁:
* 非正常关闭服务器(正常关闭session会序列化):
* session过期了默认30分钟.
* 手动调用session.invalidate();
HttpSession的问题
* 访问Servlet会不会创建Session : 不会
* 访问JSP会不会创建Session :会. (Session作为JSP的内置对象,调用了getSession)
* 访问html会不会创建Session :不会
应用
public class MyHttpSessionListener implements HttpSessionListener{ @Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("HttpSession被创建了...");
} @Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("HttpSession被销毁了...");
} }
配置:
<listener>
<listener-class>com.cnblogs.weblistener.MyHttpSessionListener</listener-class>
</listener>
企业中的应用:统计在线人数
public class SessionLinstener implements HttpSessionLinstener {
public void sessionCreated(HttpSessionEvent se) {
ServletContext sc = se.getSession().getServletContext();
Integer num = (Integer) sc.getAttribute("peopleOnline");
if (null == num) {
sc.setAttribute("peopleOnline",1);
} else {
num++;
sc.setAttribute("peopleOnline",num);
}
} public void sessionCreated(HttpSessionEvent se) {
try {
ServletContext sc = se.getSession().getServletContext();
Integer num = (Integer) sc.getAttribute("peopleOnline");
num--;
sc.setAttribute("peopleOnline",num);
} catch (Exception e) {
// TODO: handle exception
}
}
}
ServletRequestListener:监听ServletRequest对象的创建和销毁的监听器
方法
void requestDestroyed(ServletRequestEvent sre)
The request is about to go out of scope of the web application.
void requestInitialized(ServletRequestEvent sre)
The request is about to come into scope of the web application.
request对象何时创建和销毁
* 创建:客户端向服务器发送一次请求,服务器就会创建request对象.
* 销毁:服务器对这次请求作出响应后就会销毁request对象.
request的问题
访问一个Servlet会不会创建request对象:会
访问一个JSP会不会创建request对象:会
访问一个HTML会不会创建request对象:会
应用
public class MyServletRequestListener implements ServletRequestListener{
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("ServletRequest被销毁了...");
} @Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("ServletRequest被创建了...");
}
}
配置:
<listener>
<listener-class>com.cnblogs.weblistener.MyServletRequestListener</listener-class>
</listener>
企业中监听器的应用
在线人数,在线用户数,访问量,及数据持久化
JavaWeb-Servlet技术的监听器-解析与实例-网站在线用户信息与网页点击量
二类:监听三个域对象的属性变更的监听器:(属性添加,移除,替换)
ServletContextAttributeListener:监听ServletContext对象的属性变更
Method Summary
void attributeAdded(ServletContextAttributeEvent scab)
Notification that a new attribute was added to the servlet context.
void attributeRemoved(ServletContextAttributeEvent scab)
Notification that an existing attribute has been removed from the servlet context.
void attributeReplaced(ServletContextAttributeEvent scab)
Notification that an attribute on the servlet context has been replaced.
HttpSessionAttributeListener:监听HttpSession中的属性变更
Method Summary
void attributeAdded(HttpSessionBindingEvent se)
Notification that an attribute has been added to a session.
void attributeRemoved(HttpSessionBindingEvent se)
Notification that an attribute has been removed from a session.
void attributeReplaced(HttpSessionBindingEvent se)
Notification that an attribute has been replaced in a session.
ServletRequestAttributeListener:监听ServletRequest对象的属性变更
Method Summary
void attributeAdded(ServletRequestAttributeEvent srae)
Notification that a new attribute was added to the servlet request.
void attributeRemoved(ServletRequestAttributeEvent srae)
Notification that an existing attribute has been removed from the servlet request.
void attributeReplaced(ServletRequestAttributeEvent srae)
Notification that an attribute was replaced on the servlet request.
三类:监听HttpSession中的JavaBean的对象的状态改变的监听器
第三类监听器很特殊,不需要进行配置的.作用在JavaBean上的监听器.JavaBean可以自己感知到在Session中的状态.
HttpSessionBindingListener:监听HttpSession中的JavaBean的绑定和解除绑定
Method Summary
void valueBound(HttpSessionBindingEvent event)
Notifies the object that it is being bound to a session and identifies the session.
void valueUnbound(HttpSessionBindingEvent event)
Notifies the object that it is being unbound from a session and identifies the session.
HttpSessionActivationListener:监听HttpSession中的JavaBean的钝化和活化
Method Summary
void sessionDidActivate(HttpSessionEvent se) 活化(反序列化)
Notification that the session has just been activated.
void sessionWillPassivate(HttpSessionEvent se) 钝化(序列化到硬盘)
Notification that the session is about to be passivated.
优化Session:
通过配置<Context>标签配置定时session序列化.
在tomcat/conf/context.xml中配置<Context>:
在tomcat中所有的虚拟主机和虚拟路径都会按照这个配置执行.
在tomcat/conf/Catalina/localhost/context.xml配置<Context>:
在tomcat中的localhost虚拟主机中的所有虚拟路径按照这个配置执行.
在当前的工程下的META-INF/context.xml配置<Context>:
当前这个工程按照配置执行.
当前的工程下的META-INF/context.xml的代码:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!--
maxIdleSwap:1 1分钟session会自动序列化到硬盘.
directory:cnblogs 序列化后存放的位置.( tomcat/conf/Catalina/localhost/工程名/cnblogs)
-->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="cnblogs"/>
</Manager>
</Context>
Filter过滤器
过滤器实现自动登录
Cookie技术
利用Cookie记住用户的用户名和密码,设置号有效时间,用户访问页面的时候带入.
Filter:过滤器的概述
过滤器Filter:可以过滤从客户端向服务器发送的请求.
主要方法
void destroy()
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
void init(FilterConfig filterConfig)
使用过滤器
* 编写一个类实现Filter接口;
* 配置过滤器;
过滤器的生命周期
过滤器的创建和销毁:
* 创建:服务器启动的时候。
* 销毁:服务器关闭的时候。
(1) 加载和实例化
Web 容器启动时,即会根据 web.xml 中声明的 filter 顺序依次实例化这些 filter。 (2) 初始化
Web 容器调用 init(FilterConfig) 来初始化过滤器。容器在调用该方法时,向过滤器传递 FilterConfig 对象,FilterConfig 的用法和 ServletConfig 类似。利用 FilterConfig 对象可以得到 ServletContext 对象,以及在 web.xml 中配置的过滤器的初始化参数。在这个方法中,可以抛出 ServletException 异常,通知容器该过滤器不能正常工作。此时的 Web 容器启动失败,整个应用程序不能够被访问。实例化和初始化的操作只会在容器启动时执行,而且只会执行一次。 (3) doFilter
doFilter 方法类似于 Servlet 接口的 service 方法。当客户端请求目标资源的时候,容器会筛选出符合 filter-mapping 中的 url-pattern 的 filter,并按照声明 filter-mapping 的顺序依次调用这些 filter 的 doFilter 方法。在这个链式调用过程中,可以调用 chain.doFilter(ServletRequest, ServletResponse) 将请求传给下一个过滤器(或目标资源),也可以直接向客户端返回响应信息,或者利用 RequestDispatcher 的 forward 和 include 方法,以及 HttpServletResponse 的 sendRedirect 方法将请求转向到其它资源。需要注意的是,这个方法的请求和响应参数的类型是 ServletRequest 和 ServletResponse,也就是说,过滤器的使用并不依赖于具体的协议。 (4) 销毁
Web 容器调用 destroy 方法指示过滤器的生命周期结束。在这个方法中,可以释放过滤器使用的资源。
Filter生命周期
FilterConfig:过滤器的配置对象
Method Summary
String getFilterName()
Returns the filter-name of this filter as defined in the deployment descriptor.
String getInitParameter(String name)
Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.
Enumeration getInitParameterNames()
Returns the names of the filter's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the filter has no initialization parameters.
ServletContext getServletContext()
Returns a reference to the ServletContext in which the caller is executing.
public void init(FilterConfig filterConfig) throws ServletException {
// 获得当前的Filter的名称:
String filterName = filterConfig.getFilterName();
System.out.println(filterName);
// 获得初始化参数:
String username = filterConfig.getInitParameter("username");
String password = filterConfig.getInitParameter("password");
System.out.println(username+" "+password);
// 获得所有的初始化参数的名称:
Enumeration<String> en = filterConfig.getInitParameterNames();
while(en.hasMoreElements()){
String name = en.nextElement();
String value = filterConfig.getInitParameter(name);
System.out.println(name+" "+value);
}
}
FilterChain:过滤器链
过滤器链中的过滤器的执行的顺序与<filter-mapping>的配置顺序有关.
* doFilter(request,response); -- 放行,放行到下一个过滤器中,如果没有下一个过滤器,到达目标资源.
Filter相关的配置
<url-pattern>的配置:
* 完全路径匹配 :以 / 开始 /demo4/demo1.jsp
* 目录匹配 :以 / 开始 以 * 结束. /* /demo1/*
* 扩展名匹配 :不能以 / 开始 以 * 开始. *.do *.action
<servlet-name>的配置:根据Servlet的名称拦截Servlet. //替代<url-patten>的标签
<dispatcher>的配置:
* REQUEST :默认值.
* FORWARD :转发.
* INCLUDE :包含.
* ERROR :错误页面跳转.(全局错误页面)
在servlet中new Service() 和在service中 new Dao() 这种方式的替换。
自动登录代码实现
自动登录:访问index.jsp,点击上面的登录,跳到login.jsp,填写表单,提交到UserServlet。UserServlet中的处理,完成登录信息在cookie和session中的保存,再转发到index.jsp。index.jsp中,直接获取session域中的用户,显示用户欢迎等的登录状态信息。 用户关掉浏览器再访问index.jsp时,带这cookie去的,这个时候拦截器,取出cookie中的信息,验证后,存入session中,放行到index.jsp,index.jsp中的session域对象就有了登录信息了,就完成了自动登陆。
package com.boomoom.autologin.web.servlet; import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.boomoom.autologin.domain.User;
import com.boomoom.autologin.service.UserService; public class UserServlet extends HttpServlet{ @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* 1.接收参数:
* 2.封装数据:
* 3.调用业务层处理数据:
* 4.页面跳转:
*/
// 接收参数:
try{
Map<String,String[]> map = req.getParameterMap();
// 封装数据:
User user = new User();
BeanUtils.populate(user, map);
// 调用业务层:
UserService userService = new UserService();
User existUser = userService.login(user);
// 跳转页面:
if(existUser == null){
// 登录失败:
req.setAttribute("msg", "用户名或密码错误!");
req.getRequestDispatcher("/demo5/login.jsp").forward(req, resp);
}else{
// 登录成功:
// 记住用户名和密码: //在jsp页面中定义: <input type="checkbox" name="autoLogin" value="true"> 自动登录
String autoLogin = req.getParameter("autoLogin");
if("true".equals(autoLogin)){
// 自动登录的复选框已经勾选.
Cookie cookie = new Cookie("autoLogin",existUser.getUsername()+"#"+existUser.getPassword());
cookie.setPath("/day16");
cookie.setMaxAge(60 * 60 * 24 * 7);
resp.addCookie(cookie);
}
// 使用Session记录用户信息.
req.getSession().setAttribute("existUser", existUser);
resp.sendRedirect(req.getContextPath()+"/demo5/index.jsp");
}
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException();
}
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
UserServlet
package com.boomoom.autologin.web.filter; import java.io.IOException;
import java.sql.SQLException;
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.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.boomoom.autologin.domain.User;
import com.boomoom.autologin.service.UserService;
import com.boomoom.utils.CookieUtils; /**
* 自动登录的过滤器的实现
* @author admin
*
*/
public class AutoLoginFilter implements Filter{ @Override
public void init(FilterConfig filterConfig) throws ServletException {
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
/**
* 判断session中是否有用户的信息:
* * session中如果有:放行.
* * session中没有:
* * 从Cookie中获取:
* * Cookie中没有:放行.
* * Cookie中有:
* * 获取Cookie中存的用户名和密码到数据库查询.
* * 没有查询到:放行.
* * 查询到:将用户信息存入到session . 放行.
*/
// 判断session中是否有用户的信息:
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
User existUser = (User) session.getAttribute("existUser");
if(existUser != null){
// session中有用户信息.
chain.doFilter(req, response);
}else{
// session中没有用户信息.
// 获得Cookie的数据:
Cookie[] cookies = req.getCookies();
Cookie cookie = CookieUtils.findCookie(cookies, "autoLogin");
// 判断Cookie中有没有信息:
if(cookie == null){
// 没有携带Cookie的信息过来:
chain.doFilter(req, response);
}else{
// 带着Cookie信息过来.
String value = cookie.getValue();// aaa#111
// 获得用户名和密码:
String username = value.split("#")[0];
String password = value.split("#")[1];
// 去数据库进行查询:
User user = new User();
user.setUsername(username);
user.setPassword(password);
UserService userService = new UserService();
try {
existUser = userService.login(user);
if(existUser == null){
// 用户名或密码错误:Cookie被篡改的.
chain.doFilter(req, response);
}else{
// 将用户存到session中,放行
session.setAttribute("existUser", existUser);
chain.doFilter(req, response);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
} @Override
public void destroy() {
}
}
AutoLoginFilter
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.cnblogs.autologin.web.servlet.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/UserServlet</url-pattern>
</servlet-mapping> <filter>
<filter-name>AutoLoginFilter</filter-name>
<filter-class>com.cnblogs.autologin.web.filter.AutoLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AutoLoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
web.xml
在对过滤的要求较高的时候,cookie == null 和 user == null 的判断完成,不能简单的放行,而是要对请求的资源做判断再放行。静态资源放行,其他的请求转去登录页。
String uri = req.getReqestURI();
if (uri.endsWith("login.jsp")||uri.endsWith("loginServlet")||uri.endsWith("jpg")||uri.endsWith("png")||uri.endsWith("css")||uri.endsWith("js")||uri.endsWith("jhtml")) {
chain.doFilter(req, response);
} else {
req.getRequestDispatcher("/demo/login.jsp").forward(request, response);
}
cookie和user为null的时候,严谨的拦截方式
通用的字符集编码的过滤器
通常会提交带有中文的数据,GET/POST请求都有可能提交中文数据.通常情况下在Servlet中处理中文乱码.现在将乱码的处理交给过滤器完成.只需要在Servlet中关心参数的接收就可以了.只需要在Servlet中调用request.getParameter();接收参数就可以,而不去关心到底get/post如何处理乱码.
增强request中的getParameter方法
继承 :控制这个类构造.
装饰者模式 :增强的类和被增强类实现相同的接口,增强的类中获得到被增强的类的引用.缺点:接口中方法太多.
动态代理 :被增强的类实现接口就可以.
1、采用装饰者模式,这里的HttpServletRequestWrapper是一个模板类,继承这个类可以避免对HttpServletRequest接口的全部方法的实现。
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{ private HttpServletRequest request; public MyHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
} @Override
public String getParameter(String name) {
// 根据请求方式不同,去处理:
// 获得请求方式:
String method = request.getMethod();
if("get".equalsIgnoreCase(method)){
String value = null;
try {
value = new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return value;
}else if("post".equalsIgnoreCase(method)){
try {
request.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return super.getParameter(name);
} }
MyHttpServletRequestWrapper
package com.boomoom.encoding.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.http.HttpServletRequest; public class GenericEncodingFilter implements Filter{ @Override
public void init(FilterConfig filterConfig) throws ServletException {
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
MyHttpServletRequestWrapper myReq = new MyHttpServletRequestWrapper(req);
chain.doFilter(myReq, response);
} @Override
public void destroy() {
} }
GenericEncodingFilter
<filter>
<filter-name>GenericEncodingFilter</filter-name>
<filter-class>com.cnblogs.encoding.filter.GenericEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GenericEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
web.xml
在HttpServletRequestWrapper的getParameter方法的返回值处,还能做一个敏感词过滤的处理。
2、采用动态代理
补充:动态带的demo
package com.boomoom.b_proxy;
/**
* 服务员的接口.
* @author admin
*
*/
public interface Waiter { public void server(); public String sayHello(String name);
}
Waiter
package com.boomoom.b_proxy;
/**
* 服务器的实现类
* @author admin
*
*/
public class Waitress implements Waiter { @Override
public void server() {
System.out.println("服务中...");
} @Override
public String sayHello(String name) {
return "Hello "+name;
} }
Waitress
package com.boomoom.b_proxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import org.junit.Test; public class ProxyDemo1 { @Test
public void demo1(){
Waiter waiter = new Waitress();
// waiter.server(); // 使用动态代理:Proxy.newProxyInstance();
/**
* ClassLoader :类加载器.
* Class[] :被增强的对象实现的所有接口
* InvocationHandler :处理类.
*/
// 第一个参数:
ClassLoader classLoader = waiter.getClass().getClassLoader();
// 第二个参数:
Class[] interfaces = waiter.getClass().getInterfaces();
// 第三个参数: Waiter waiter2 = (Waiter)Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler(waiter));
waiter2.server();
// 说明现在调用代理对象的任何方法的时候,都是相当于调用invoke,InvocationHandler中的invoke都会执行.
String s = waiter2.sayHello("James");
System.out.println(s);
}
} class MyInvocationHandler implements InvocationHandler{ private Waiter waiter; public MyInvocationHandler(Waiter waiter){
this.waiter = waiter;
} @Override
/**
* 方法的参数:
* * proxy :产生的代理对象.
* * method :当前正在调用的目标类的方法.
* * params :正在执行的方法中的参数.
*/
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
// System.out.println("InvocationHandler invoke 执行了...");
// System.out.println("微笑=========");
// waiter.sayHello("James");
// System.out.println(method.getName());
if("server".equals(method.getName())){
System.out.println("微笑==========");
Object obj = method.invoke(waiter, params);
System.out.println("bye==========");
return obj;
}else{
return method.invoke(waiter, params);
}
}
}
ProxyDemo1
实现:采用注解,不用配置web.xml,主要是在GennericEncodingFilter的方法上做了修改:
package com.boomoom.encoding; import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; 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;
import javax.servlet.http.HttpServletRequest; @WebFilter(urlPatterns="/*")
public class GenericEncodingFilter implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;
// 增强req:
HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(),
req.getClass().getInterfaces(), new InvocationHandler() { @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 判断执行的方法是否是getParameter:
if("getParameter".equals(method.getName())){
// 调用的是getParameter:需要增强这个方法.
// 判断请求方式是GET还是POST:
String type = req.getMethod();
if("get".equalsIgnoreCase(type)){
String value = (String) method.invoke(req, args);
value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
return value;
}else if("post".equalsIgnoreCase(type)){
req.setCharacterEncoding("UTF-8");
}
}
return method.invoke(req, args);
}
}); chain.doFilter(myReq, response);
} @Override
public void destroy() { } }
GenericEncodingFilter
Listener监听器和Filter过滤器的更多相关文章
- Listener监听器与Filter过滤器
1.Listener [1]监听器简介 > Listener是JavaWeb的三大组件之一,Servlet.Filter.Listener > Li ...
- 02 Filter过滤器
Filter 一.Filter过滤器 Filter过滤器它是JavaWeb的三大组件之一.三大组件分别是:Servlet程序.Listener监听器.Filter过滤器 Filter过滤器是JavaE ...
- 15 Filter过滤器和Listener监听器
1.Filter:过滤器 (1) 概念:生活中的过滤器:净水器,空气净化器,土匪.web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能.过滤器的作用:一般用于完成通用的 ...
- Filter过滤器Listener:监听器
Filter过滤器 1. 概念 web中的过滤器:当访问服务器资源是,过滤器可以将请求拦截下来,完成一些特殊功能: 过滤器的作用 完成通用的操作:例如登录验证.统一编码处理.敏感字符过滤... 快速入 ...
- java web.xml listener servlet 和filter加载顺序
在该项目中总会遇到一些关于加载的优先问题.最近遇到了同样的类别似的,所以,如果你发现信息汇总下,以下是转载其他一些人,毕竟,人们写的不错.它不重复创建的轮.只是略作修改自己的观点. 首先能够肯定的是, ...
- .jsp文件的使用和理解以及一些小练习和Listener监听器
什么是 jsp,它有什么用? jsp 的全换是 java server pages.Java 的服务器页面.jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据.因为 Servle ...
- 什么是Listener监听器
什么是Listener监听器 1,Listener 监听器它是JavaWeb的三大组件之一.JavaWeb的三大组件:Servlet程序,Filter过滤器,Listener监听器. 2,Listen ...
- listener监听器
前言:之前写了一篇关于Filter的文章:http://tianweili.github.io/blog/2015/01/26/java-filter/,现在再来一篇Listener的,Filter和 ...
- 【Servlet】Java Serlvet Listener 监听器
Listener监听器 Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理 容器产生的事件分类 - 生命周期相关的事件 - 设置和删除Attribute数据 ...
随机推荐
- Day 3-6 生成器&迭代器
---恢复内容开始--- 列表生成式: list = [i*i for i in range(20)] # 这就是一个列表生成式 print(list) # [0, 1, 4, 9, 16, 25, ...
- (二)Wireshark的实用表格
主要内容: 1.了解端点概念,学习如何在Wireshark中查询端点信息 2.学习利用端点窗口与会话窗口来分析数据包的特点 3.学会Wireshark的协议分层统计窗口的用法 一.端点概念 和数学里的 ...
- 为什么js中要用void 0 代替undefined
这个是Backbone.js中的一句源码 if (callback !== void 0 && 'context' in opts && opts.context == ...
- flutter开发vscode用模拟器调试
android studio的太重,我装的是android sdk,使用avd的模拟器启动黑屏 启动夜神模拟器(已卸载) 建立连接: adb connect 127.0.0.1:62001 (夜 ...
- Laravel 出现 No application encryption key has been specified.
若文件根目录下没有 .env 1..env.example 改名使用命令 copy 修改为 .env 2.使用命令 php artisan key:generate 获取密码,自动保存到 .env3 ...
- mysql关联、子查询索引优化
1.驱动表:加索引不起作用,因为全表扫描.表1 left join 表2 ,此时表1是驱动表 被驱动表:给这个加索引. 关联查询 子查询时 尽量不使用not in 或者not exists 而是用 ...
- 将大数组里面的小数组平行展开的实现(Making a flat list out of list of lists in Python)
今天在生成数据的时候遇到了这个需求,其实写一个for循环可以很容易解决这个问题,但是无论是性能还是酷炫程度上都不行 所以顺手搜索了一下. 例子是将 l = [[1, 2, 3], [4, 5, 6], ...
- python RSA 加密与签名
PyCrypto装起来就简单多了,我是直接 sudo easy_install pycrypto 直接搞定的 先生成rsa的公私钥:打开控制台,输入 openssl 再输入 genrsa -out p ...
- linux 地址解析协议 arp
随便转载,保留出处:http://www.cnblogs.com/aaron-agu/ arp –na #查看 arp –s 123.253.68.209 00:19:56:6F:87:D4 #添加
- 如何消除原生Android网络状态上的惊叹号
喜欢使用原生Android系统的朋友可能会发现自己的状态栏信号图标上经常有一个惊叹号标志. 这是怎么回事呢?原因是Android为了对网络状态进行检测,采用了一种叫做captive detection ...