Filter和Listener
1.Filter快速入门
作用:过滤请求和响应内容,做一些统一处理,比如某些页面需要登录,设置编码,敏感词过滤
1.方式一:使用注解
@WebFilter("/*")//拦截路径,拦截项目下的所有资源
public class FilterDemo implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//放行,如果不放行,那么目标资源就访问不到了
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
2.方式二:使用web.xml
<filter>
<filter-name>FilterDemo</filter-name>
<filter-class>cn.itcast.web.filter.FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
2.filter的生命周期
1、init():在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
2、doFilter():每一次请求被拦截资源时,会执行。执行多次
3、destroy():在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
3.拦截路径配置
1. 完全路径拦截: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
2. 目录拦截: /user/* 访问/user下的所有资源时,过滤器都会被执行
3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
4. 全部拦截 /*
4.拦截方式—浏览器请求和请求转发
//浏览器直接请求index.jsp资源时,该过滤器会被执行 默认的拦截方式
@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
//只有转发访问index.jsp时,该过滤器才会被执行
@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
//浏览器直接请求index.jsp或者转发访问index.jsp。该过滤器才会被执行
@WebFilter(value="/index.jsp",dispatcherTypes ={ DispatcherType.FORWARD,DispatcherType.REQUEST})
5.案例一:登录验证
@WebFilter(value = {"/list.jsp","/update.jsp","/add.jsp","/index.jsp"},dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//强制转换
HttpServletRequest request = (HttpServletRequest)servletRequest;
//从获取session中获取user
Object user = request.getSession().getAttribute("user");
if(user != null){
//登陆过
filterChain.doFilter(servletRequest,servletResponse);
}else {
//没有登录
request.setAttribute("login_msg","您没有登录,请登录!"); request.getRequestDispatcher("login.jsp").forward(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
}
}
6.案例二:统一编码的过滤器
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("Text/html;charset=utf-8");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
7.案例三:过滤敏感词汇
@WebFilter(value = "/TestServlet",dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
public class TestFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
ServletRequest proxy = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
/*
InvocationHandler 监视器
invoke 参数显示
proxy 代理对象
method 执行的方法
args 方法中的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("getParameter")){
String str = (String) method.invoke(req, args);
if(str.contains("傻")){//当且仅当此字符串包含指定的char值序列时才返回true
str = "呵呵";
}
return str;
}
return method.invoke(req,args);
}
});
//放行
chain.doFilter(proxy, resp);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
8.动态代理
什么是代理
代理的前提条件:代理对象和真实对象要实现相同的接口;
public interface SaleComputer {
public String sale(double money);
public void show();
}
public class Lenovo implements SaleComputer {
@Override
public String sale(double money) {
System.out.println("花了"+money+"元买了一台联想电脑");
return "联想电脑";
}
@Override
public void show() {
System.out.println("展示电脑。。。。。");
}
}
public class ProxyTest {
public static void main(String[] args) {
//创建对象
Lenovo lenovo = new Lenovo();
//动态代理增强lenovo对象
SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// System.out.println("执行了.....");
// System.out.println(method.getName());
// System.out.println(args[0]);
//使用真实对象调用改方法
if(method.getName().equals("sale")){
double money = (double)args[0];
money *=0.85;
Object obj = method.invoke(lenovo, money);
return obj;
}else {
Object obj = method.invoke(lenovo, args);
return obj;
}
}
});
//调用方法
String sale = proxy_lenovo.sale(8000);
System.out.println(sale);
proxy_lenovo.show();
}
}
代码效果:
花了6800.0元买了一台联想电脑
联想电脑
展示电脑。。。。。
9.listener使用思路
监听对象:Servlet中的域对象
1.注解
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象被创建了。。。");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象被销毁了。。。");
}
}
2.web.xml
<listener>
<!-- 类的全路径 -->
<listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class>
</listener>