Java进阶-14.listener和filter

一、listener

1.概念

Javaweb中的监听器是用于监听web常见对象HttpServletRequest,HttpSession,ServletContext。

监听web对象的创建与销毁

监听web对象的属性变化

监听session绑定javaBean操作

注意:Listener全部是接口,需要servlet实现对应的接口,对应的类如下:

监听三个对象的创建和销毁

ServletContextListener

ServletRequestListener

HttpSessionListener

监听三个对象属性的变化

ServletContextAttributeListener

ServletRequestAttributeListener

HttpSessionAttributeListener

监听sessionjavabean的状态

HttpSessionActivationListener(钝化和活化)

HttpSessionBindingListener(绑定和解绑),放在session中就是绑定

2.监听三个对象的创建和销毁

要先配置web.xml

<listener>

    <listener-class>it.dragon.listner.myservletcontextlis</listener-class>

</listener>

ServletContextListener

创建服务器启动的时候会为每一个项目都创建一个servletContext

销毁服务器关闭的时候或者项目被移除的时候

以后用来加载配置文件,在系统启动之后,加载所有配置文件。

ServletRequestListener

创建:整个项目中,有请求来的时候

销毁:整个项目中,有响应生成的时候

HttpSessionListener

创建:java中第一次调用request.getSession的时候、jsp访问的时候创建

销毁:session超时、手动销毁session、服务器非正常关闭

3.监听三个对象属性的变化(添加 替换 删除)

ServletContextAttributeListener

ServletRequestAttributeListener

HttpSessionAttributeListener

监听sessionjavabean的状态

这两个类需要Javabean实现,而不是servlet。

HttpSessionBindingListener(绑定和解绑),检测java是否添加到session或者从session中移除

        session.setAttribute('p',new Person("张三"))

HttpSessionActivationListener(钝化和活化)

钝化:javabeansession中序列化到磁盘上正常关闭项目时候就会自动序列化

活化:javabean从磁盘上加载到了session中,重新启动时候就可以

注意:类必须实现序列化 serializable

可以通过配置文件修改javabean什么时候钝化,若只对一个项目生效,只需要在项目下/meta-info创建一个context.xml。注意在IDEA中,web项目没有这个文件夹,需要自己创建,否则读取不到context.xml文件。

<Context>
    <!--
        maxIdleSwap :1分钟 如果session不使用就会序列化到硬盘.
        directory   :itheima 序列化到硬盘的文件存放的位置.
    -->
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="itheima"/>
    </Manager>
</Context>

二、filter

Filter是sun公司中servlet2.3后增加的一个新功能。(Servlet规范中三个技术  Servlet  Listener  Filter)在javaEE中定义了一个接口 javax.servlet.Filter来描述过滤器。通过Filter可以拦截访问web资源的请求与响应操作。WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp,Servlet,静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

Filter是一个接口,编写filter步骤:

1.编写一个类

   a.实现filter接口,implements Filter

   b.重写方法,

2.编写配置文件

   a.注册filter

   b.绑定路径

3.测试

1.Filter接口的方法

init(FilterConfig config):初始化操作

doFilter(ServletRequest request, ServletResponse response, FilterChain chain):处理业务逻辑

destroy() :销毁操作

2.filter生命周期

filter单实例多线程,filter在服务器启动的时候服务器创建filter,调用init方法实现初始化操作。请求来的时候创建一个线程根据路径调用dofilter执行业务逻辑,当filter被移除的时候或者服务器正常关闭的时候调用destory方法执行销毁操作。

3.FilterChain

通过chaindofilter方法可以将请求放行到下一个过滤器直到最后一个过滤器放行才可以访问到servlet或者jsp。

4.url-pattern配置

通过配置url,使得能够匹配到的servlet都将使用该过滤器。

完全匹配    必须以"/" 开始  例如: /a/b

目录匹配    必须以"/" 开始 "*"结束  例如:/a/b/*

后缀名匹配   "*."开始 以字符结束   例如 :  *.jsp  *.do  *.action

例如:

    afilter  路径  /*

    bFilter  路径  /demo4

一个资源(servlet)有可能被多个过滤器匹配成功多个过滤器的执行顺序是按照web.xmlfilter-mapping的顺序执行。

5.案例1-自动登录

需求:登录的时候,勾选自动登录登录成功之后关闭浏览器,下一次访问网站的时候完成登录操作(自动登录)。

autofilter

public class AutoLoginFilter implements Filter{	
	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		//1.强转
		HttpServletRequest request =(HttpServletRequest) req;
		HttpServletResponse response =(HttpServletResponse) resp;		
		//2.完成自动登录
		//2.1 判断session中有无登录登录用户 没有的话继续自动登录
		User user=(User) request.getSession().getAttribute("user");
		if(user==null){
			//没有用户  需要自动登录
			//2.2 判断访问的资源是否和登录注册相关,若相关则不需要自动登录
			String path = request.getRequestURI();// /day1601/xxx
            //如果是登录界面,那么显然就不需要进行自动登录了
			if(!path.contains("/login")){				
				//2.3获取指定的cookie
				Cookie c = CookUtils.getCookieByName("autologin", request.getCookies());
				//判断cookie是否为空
				//若不为空 获取值(username和passowrd) 调用serivce完成登录  判断user是否为空 不为空 放入session
				if(c!=null){
					String username=c.getValue().split("-")[0];
					String password=c.getValue().split("-")[1];
					
					//调用serivce完成登录
					//user=null;
					try {
						user = new UserService().login(username, password);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					if(user!=null){
						//将user放入session中
						request.getSession().setAttribute("user", user);
					}
				}
			}			
		}
		//3.放行
		chain.doFilter(request, response);
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {		
	}
	@Override
	public void destroy() {		
	}

}

loginservlet

public class Login extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String usernaeme = req.getParameter("username");
        String passwd = req.getParameter("password");
        User user = null;
        try {
            user = new UserService().login(usernaeme,passwd);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        if(user==null){
            req.setAttribute("msg","can not match username and passed");
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }else{
            req.getSession().setAttribute("user",user);
            if(Constant.IS_AUTO_LOGIN.equals(req.getParameter("autoLogin"))){
                Cookie c = new Cookie("autoLogin",usernaeme+"_"+passwd);
                c.setMaxAge(3600);
                c.setPath(req.getContextPath()+"/");
                resp.addCookie(c);
            }
            if(Constant.IS_SAVE_NAME.equals(req.getParameter("saveName"))){
                //创建cookie
                Cookie c=new Cookie("savename", URLEncoder.encode(usernaeme, "utf-8"));
                c.setMaxAge(3600);
                c.setPath(req.getContextPath()+"/");

                resp.addCookie(c);
            }
            resp.sendRedirect(req.getContextPath()+"/success.jsp");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

login.jsp

<body>
	<form method="post" action="${pageContext.request.contextPath }/login">
		<table>
			<tr>
				<td>用户名</td>
				<td><input type="text" name="username" ></td>
			</tr>
			<tr>
				<td>密码</td>
				<td><input type="text" name="password"></td>
			</tr>
			<tr>
				<td colspan="1"><input type="checkbox" name="saveName" value="ok">记住用户名</td>
				<td colspan="1"><input type="checkbox" name="autoLogin" value="ok">自动登录</td>
			</tr>
			<tr>
				<td colspan="2"><input type="submit"></td>
			</tr>
		</table>
	</form>
	<script type="text/javascript">
		onload=function(){
			var s="${cookie.savename.value }";
			s=decodeURI(s);
			alert(s);			
			//将解码后的用户名付给username的文本框
			document.getElementsByName("username")[0].value=s;			
		}
	</script>
</body>
</html>

6.filterConfig

过滤器的配置对象,作用:

获取全局管理者

获取当前filter的名称

获取当前filter的初始化参数

7.filter-mapping的子标签

servlet-name

匹配哪个servlet ,就写serlvet标签中servlet-name的值。建议不要在一个filter中重复的匹配servlet。

例如:serlveturl-pattern:/a/b/hello,serlvet-name:HelloServlet;如果filter中的url-pattern  /*,最好不要在写 servlet-name:HelloServlet。

dispatcher匹配哪种请求

默认的是REQUEST,一旦显式的写出来哪种请求默认就不起作用了。

REQUEST:从浏览器发送过来的请求

FORWARD:转发过来的请求

ERROR:因服务器错误而发送过来的请求,可以自定义好看的界面

INCLUDE:包含过来的请求

<error-page>
    <error-code>404</error-code>
    <location>/404.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/500.jsp</location>
</error-page>

8.案例2-统一字符编码

需求:开发的时候若有参数第一步都是设置编码才不会出现乱码通过过滤器设置servlet或者jsp上的时候已经没有乱码问题。

技术分析:

    filter 配置路径/* 过滤器的第一个位置,这样可以匹配所有的servlet。

    filter中重写getParameter(加强)

步骤分析:我们只需要在filter request进行加强(例如只对request.getParameter()进行加强)

方法加强

1.继承(获取构造器)

2.装饰者模式(静态代理)

3.动态代理

装饰者书写步骤:

1.要求装饰者和被装饰者实现同一个接口或者继承同一个类

2.装饰者中要有被装饰者的引用

3.对需要加强方法进行加强

4.对不需要加强的方法调用原来的方法即可

 加强request.getParameter(String key)

首先请求的方式不同处理的方式也不同

若是get请求

    new String(value.getBytes("iso8859-1"),"utf-8");

若是post请求,只需要设置一句话

    request.setCharacterEncoding("utf-8");

最后将包装过的request对象(MyRequest)传递给servlet即可

public class EncodingFilter implements Filter{
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {		
	}
	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		//1.强转
		HttpServletRequest request=(HttpServletRequest) req;
		HttpServletResponse response=(HttpServletResponse) resp;		
		//2.放行 将包装过的request传递
		chain.doFilter(new MyRequest(request), response);
	}
	@Override
	public void destroy() {	
	}
}
class MyRequest extends HttpServletRequestWrapper{	
	private HttpServletRequest request;
	public MyRequest(HttpServletRequest request) {
		super(request);
		this.request=request;
	}	
	@Override
	public String getParameter(String name) {
		//获取请求方式
		String m = request.getMethod();
		if("get".equalsIgnoreCase(m)){
			//get请求
			String value = request.getParameter(name);
			try {
				return new String(value.getBytes("iso8859-1"),"utf-8");
			} catch (UnsupportedEncodingException e) {
			}
		}else if("post".equalsIgnoreCase(m)){
			try {
				request.setCharacterEncoding("utf-8");
			} catch (UnsupportedEncodingException e) {
			}
			return request.getParameter(name);			
		}
		return super.getParameter(name);
	}	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值