16-Javaweb-listener & filter

目录

一、listener(了解) 监听器  filter(★)    过滤器

1-1 listener

    1-1-1 监听内容

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

1-3 监听三个对象属性的变化

1-4 监听session中javabean的状态

1-5 使用步骤

1-6 演示各个监听器

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

1-6-2 监听三个对象属性的变化(添加 替换 删除)

1-6-3 监听session中javabean的状态

二、 案例1-自动登录

2-1 filter:过滤器

2-2 编写filter步骤

2-2-1 编写一个类

2-2-2 编写配置文件

2-2-3 测试

2-3 Filter接口的方法

2-4 filter的生命周期(了解)

2-5 FilterChain:过滤链

2-6 ★url-pattern配置

2-7 步骤分析

2-7-1 数据库和表

2-7-2 web项目

2-7-3 新建一个登录页面 表单

2-7-4 表单提交 loginservlet

2-7-5 下次访问网站的时候

2-7-6 扩展-cookie中写入中文

2-8 filter总结

2-8-1 filterConfig:(了解)同 servletConfig

2-8-2 filter-mapping的子标签(理解)

三、案例2-统一字符编码

3-1 步骤分析

3-1-1 方法加强

3-1-2 装饰者书写步骤

3-1-3 加强request.getParameter(String key)

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

3-2 关于获取参数的方法

总结


  • 一、listener(了解) 监听器  filter(★)    过滤器

  • 1-1 listener

    监听器
    作用:
        监听web中中的域对象  ServletContext  ServletRequest  HttpSession

  •     1-1-1 监听内容

        监听三个对象的创建和销毁(生命周期)
        监听三个对象属性的变化
        监听session中javabean的状态    
    注意:listener全部是接口  (规范)      

  • 1-2 监听三个对象的创建和销毁

    ServletContextListener
    ServletRequestListener
    HttpSessionListener

  • 1-3 监听三个对象属性的变化

    ServletContextAttributeListener
    ServletRequestAttributeListener
    HttpSessionAttributeListener

  • 1-4 监听session中javabean的状态

    HttpSessionActivationListener(钝化活化)写入磁盘,写进内存
    HttpSessionBindingListener(绑定和解绑)是否放入session中

  • 1-5 使用步骤

  1.  编写一个类 实现接口
  2.  重写方法
  3.  编写配置文件(大部分都是)    
  • 1-6 演示各个监听器

  • 1-6-1 监听三个对象的创建和销毁

  • ServletContextListener

        创建:服务器启动的时候,会为每一个项目都创建一个servletContext
        销毁:服务器关闭的时候,或者项目被移除的时候

public class MyServletContextLis 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.itheima.a_listener.a_hello_servletcontext.MyServletContextLis</listener-class>
	</listener> 


        以后用来加载配置文件(项目初始化操作)(spring框架内)

 

  • ServletRequestListener     <!-- 创建一个jsp页面,每次访问,为一次请求-->

        创建:请求来的时候
        销毁:响应生成的时候

public class MyRequestLis implements ServletRequestListener {

	@Override
	public void requestDestroyed(ServletRequestEvent sre) {
		System.out.println("请求已销毁~~~");
	}

	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		System.out.println("请求创建了~~~");
	}

}
<!-- 创建一个jsp页面,每次访问,为一次请求-->
<body>
	request声明周期的测试
</body>
	<listener>
		<listener-class>com.itheima.a_listener.b_life.MyRequestLis</listener-class>
	</listener>

 

  • HttpSessionListener

        创建:
            java中第一次调用request.getSession的时候
            jsp访问的时候创建(jsp的内置对象,访问就创建)
        销毁:
            三种情况:
                session超时
                手动销毁session
                服务器非正常关闭

public class MySessionLis implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent se) {
		System.out.println("session 创建了...........");
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		System.out.println("session 销毁了~~~~~~~~");
	}

}
<body>
	<%
		session.invalidate();
	%>
	session已销毁!
</body>

 

  • 1-6-2 监听三个对象属性的变化(添加 替换 删除)

    ServletContextAttributeListener
    ServletRequestAttributeListener
    HttpSessionAttributeListener

<body><!--设置属性-->
	<%
		application.setAttribute("username", "tom");
	%>
</body>

<!--修改属性-->
<body>
	<%
		application.setAttribute("username", "tom");
	%>
</body>

<!--移除属性-->
<body>
	<%
		application.removeAttribute("username");
	%>
</body>

xml
	<listener>
		<listener-class>com.itheima.a_listener.c_attr.MyServletContextAttrLis</listener-class>
	</listener>
public class MyServletContextAttrLis implements ServletContextAttributeListener {

	@Override
	//添加
	public void attributeAdded(ServletContextAttributeEvent scab) {
		System.out.println("在serveltcontext中添加了一个属性,属性为:"+scab.getName());
	}

	@Override
	//移除
	public void attributeRemoved(ServletContextAttributeEvent scab) {
		System.out.println("在serveltcontext中移除了一个属性,属性为:"+scab.getName());

	}

	@Override
	//替换
	public void attributeReplaced(ServletContextAttributeEvent scab) {
		System.out.println("在serveltcontext中替换了一个属性,属性为:"+scab.getName());

	}

}

 

  • 1-6-3 监听session中javabean的状态

    注意:这两个接口需要javabean实现.是让javabean感知到自己的状态    
    HttpSessionBindingListener(绑定和解绑)

        检测java是否添加到session或者从session中移除

<body>
	将person对象添加到session中
	<%
		session.setAttribute("p", new Person(1,"tom")); 
	%>
</body>

<body>
	将person对象从session中移除
	<%
		session.removeAttribute("p");
	%>
</body>
public class Person implements HttpSessionBindingListener{
	private int id;
	private String name;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person() { }
	
	public Person(int id, String name) {
		this.id = id;
		this.name = name;
	}
	@Override
	//绑定到了session中
	public void valueBound(HttpSessionBindingEvent event) {
		System.out.println("person对象绑定到了session中");
	}
	
	@Override
	//从session中移除
	public void valueUnbound(HttpSessionBindingEvent event) {
		System.out.println("person对象从session中移除了~~");
	}
	
}


    HttpSessionActivationListener(钝化和活化)

        钝化:javabean从session中序列化(持久化)到磁盘上

        活化:javabean从磁盘上加载到了session中

        可以通过配置文件修改javabean什么时候钝化
            修改一个项目
                只需要在项目下/meta-info创建一个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>

<body>
	将person和person2对象添加到session中
	<%
		/* session.setAttribute("p", new Person(1,"tom")); */
		session.setAttribute("p2", new Person2(2,"jack"));
	%>
</body>


<body>
${p2.name }
</body>

<?xml version="1.0" encoding="UTF-8"?>
<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>
public class Person2 implements HttpSessionActivationListener,Serializable{
	private int id;
	private String name;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person2() { }
	
	public Person2(int id, String name) {
		this.id = id;
		this.name = name;
	}
	@Override
	//钝化
	public void sessionWillPassivate(HttpSessionEvent se) {
		System.out.println("person对象 写入磁盘 钝化");
	}
	@Override
	//活化
	public void sessionDidActivate(HttpSessionEvent se) {
		System.out.println("person对象 活化了~~~");
	}
	
}

 

  • 二、 案例1-自动登录

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

  • 2-1 filter:过滤器

    过滤请求和响应
    作用:

  1.         自动登录.
  2.         统一编码.
  3.         过滤关键字

        ....
    Filter是一个接口

  • 2-2 编写filter步骤

  • 2-2-1 编写一个类

    a.实现filter接口
    b.重写方法

public class HelloFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("过滤器 hello filter 收到了请求~~~");
		
		//放行
		chain.doFilter(request, response);
		
		System.out.println("过滤器 hello filte 收到了响应~~~");
		
	}

	@Override
	public void destroy() {
		
	}

}
/**
 * filter 入门
 */
public class Demo1Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("demo1 servlet执行了");
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

  • 2-2-2 编写配置文件

    a.注册filter
    b.绑定路径

  <filter>
    <filter-name>HelloFilter</filter-name>
    <filter-class>com.itheima.b_filter.d_hello.HelloFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>HelloFilter</filter-name>
    <url-pattern>/demo1</url-pattern>
  </filter-mapping>


  <servlet>
    <description></description>
    <display-name>Demo1Servlet</display-name>
    <servlet-name>Demo1Servlet</servlet-name>
    <servlet-class>com.itheima.b_filter.d_hello.Demo1Servlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Demo1Servlet</servlet-name>
    <url-pattern>/demo1</url-pattern>
  </servlet-mapping>

 

  • 2-2-3 测试

<a href="${pageContext.request.contextPath }/demo1">filter入门</a><br>
  • 2-3 Filter接口的方法

  •     init(FilterConfig config):初始化操作
  •     doFilter(ServletRequest request, ServletResponse response, FilterChain chain):处理业务逻辑
//放行——执行servlet
chain.doFilter(request, response);
  •     destroy() :销毁操作

  • 2-4 filter的生命周期(了解)

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

<a href="${pageContext.request.contextPath }/demo2">filter生命周期</a><br>


<filter>
    <filter-name>LifeFilter</filter-name>
    <filter-class>com.itheima.b_filter.e_life.LifeFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>LifeFilter</filter-name>
    <url-pattern>/demo2</url-pattern>
  </filter-mapping>
public class LifeFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("filter 55555555555555555555555");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("filter  6666666666666666666666666666");
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
		System.out.println("filter 444444444444444444444444");
	}

}

 

  • 2-5 FilterChain:过滤链

    通过chain的dofilter方法,可以将请求放行到下一个过滤器,直到最后一个过滤器放行才可以访问到servlet|jsp
    doFilter()放行方法

  • 2-6 ★url-pattern配置

    3种
    完全匹配    必须以"/" 开始  例如: /a/b
    目录匹配    必须以"/" 开始 以"*"结束  例如:/a/b/*
    后缀名匹配    以"*."开始 以字符结束   例如 :  *.jsp  *.do  *.action
例如:
    afilter  路径  /*
    bFilter  路径  /demo4
★一个资源有可能被多个过滤器匹配成功,多个过滤器的执行顺序是按照web.xml中filter-mapping的顺序执行的

<a href="${pageContext.request.contextPath }/a/b/demo3">filterchain执行顺序</a><br>


  <filter>
    <filter-name>AFilter</filter-name>
    <filter-class>com.itheima.b_filter.f_chain.AFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>AFilter</filter-name>
    <url-pattern>/a/b/*</url-pattern>
  </filter-mapping>
  <filter>
    <filter-name>BFilter</filter-name>
    <filter-class>com.itheima.b_filter.f_chain.BFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>BFilter</filter-name>
    <url-pattern>/a/*</url-pattern>
  </filter-mapping>
public class AFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		System.out.println("afilter 收到请求");
		
		//放行
		chain.doFilter(request, response);
		
		System.out.println("afilter 收到响应");
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

}

 

public class BFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		System.out.println("bfilter 收到请求");
		
		//放行
		chain.doFilter(request, response);
		
		System.out.println("bfilter 收到响应");
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

}
public class Demo3Servlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("demo3 servlet 执行了!!!");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

 

  • 2-7 步骤分析

  • 2-7-1 数据库和表

    create database day16;
    use day16;
    create table user(
        id int primary key auto_increment,
        username varchar(20),
        password varchar(20)
    );
    insert into user values(null,'tom','123');

  • 2-7-2 web项目

    jar包 工具类 配置文件

  • 2-7-3 新建一个登录页面 表单

<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);//js全局对象中的解码
			alert(s);
			
			//将解码后的用户名付给username的文本框
			document.getElementsByName("username")[0].value=s;
		}
	</script>
</body>
  • 2-7-4 表单提交 loginservlet

    接受用户名和密码
    调用service完成登录操作,返回值User
    判断user是否为空
        若不为空,将user放入session中
            判断是否勾选了自动登录
                若勾选了:
                    需要将用户名和密码写回浏览器

/**
 *登录
 */
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//0.设置编码
		request.setCharacterEncoding("utf-8");
		
		//1.获取用户名和密码
		String username=request.getParameter("username");
		String password=request.getParameter("password");
		
		//2.调用service'
		User user=null;
		try {
			user = new UserService().login(username,password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//3.判断user是否为空
		if(user==null){
			request.setAttribute("msg", "用户名和密码不匹配");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
			return;
		}else{
			//若不为空,将user放入session中
			request.getSession().setAttribute("user", user);
			
			//判断是否勾选了自动登录  若勾选了需要将用户名和密码放入cookie中, 写回浏览器
			if(Constant.IS_AUTO_LOGIN.equals(request.getParameter("autoLogin"))){
				//创建cookie 注意中文
				Cookie c=new Cookie("autologin", username+"-"+password);
				c.setMaxAge(3600);
				c.setPath(request.getContextPath()+"/");
				
				response.addCookie(c);
			}
			
			//判断是否勾选了记住用户名 若勾选了需要将用户名放入cookie中 写回浏览器
			if(Constant.IS_SAVE_NAME.equals(request.getParameter("saveName"))){
				//创建cookie
				Cookie c=new Cookie("savename", URLEncoder.encode(username, "utf-8"));
				c.setMaxAge(3600);
				c.setPath(request.getContextPath()+"/");
				
				response.addCookie(c);
			}
			//页面重定向
			response.sendRedirect(request.getContextPath()+"/success.jsp");
		}
		
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 

  • 2-7-5 下次访问网站的时候

    过滤器拦截任意请求
        判断有无指定的cookie
            有cookie,获取用户名和密码
            调用service完成登录操作,返回user
            当user不为空的时候将user放入session中.


当我们换用jack登录的时候发现登录的是tom
    自动登录只需要登录一次:当session中没有用户的时候
    访问有些资源是不需要自动登录的(和登录还有注册相关的资源)    
    修改filter的逻辑:
        首先判断session中是否有user
            若没有 并且访问的路径不是和登录注册相关的时候
                才去获取指定的cooki

使用了request 域,必须使用 请求转发

其他任意,

但是访问站外资源,必须使用重定向

	<filter>
		<filter-name>AutoLoginFilter</filter-name>
		<filter-class>com.itheima.web.filter.AutoLoginFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>AutoLoginFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
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() {
		
	}

}

 

  • 2-7-6 扩展-cookie中写入中文

//创建cookie  时将数据编码
Cookie c=new Cookie("savename", URLEncoder.encode(username, "utf-8"));

 页面获取中文需要解码

	<script type="text/javascript">
		onload=function(){
			var s="${cookie.savename.value }";
			s=decodeURI(s);//js全局对象中的解码
			alert(s);
			
			//将解码后的用户名付给username的文本框
			document.getElementsByName("username")[0].value=s;
		}
	</script>
  • 2-8 filter总结

  • 2-8-1 filterConfig:(了解)同 servletConfig

    过滤器的配置对象
    作用:
        获取全局管理者
        获取当前filter的名称
        获取当前filter的初始化参数

  • 2-8-2 filter-mapping的子标签(理解)

    servlet-name:匹配那个servlet ,值写的是serlvet标签中servlet-name的值
        建议:不要在一个filter中重复的匹配servlet(会执行两次过滤器)
            例如: serlvet的url-pattern为  /a/b/hello   serlvetname:HelloServlet
                如果filter中的url-pattern  /*(包含下面的 匹配)
                最好不要在写 servlet-name:HelloServlet            

  <filter>
    <filter-name>Name4ServletFilter</filter-name>
    <filter-class>com.itheima.b_filter.g_servletname.Name4ServletFilter</filter-class>
  </filter>
  <!--拦截  Demo11Servlet-->
  <filter-mapping>
    <filter-name>Name4ServletFilter</filter-name>
    <servlet-name>Demo11Servlet</servlet-name>
  </filter-mapping>


    dispatcher:(可以出现任意次)
        匹配哪种请求
        默认的是REQUEST,一旦显式的写出来哪种请求,默认就不起作用了
            理解
                REQUEST:从浏览器发送过来的请求(默认) 理解(请求转发的内容不拦截)
                FORWARD:转发过来的请求 理解    
    

  <filter>
	<filter-name>DispatcherFilter</filter-name>
	<filter-class>com.itheima.b_filter.h_dispather.DispatcherFilter</filter-class>
  </filter>
  
  <filter-mapping>
  	<filter-name>DispatcherFilter</filter-name>
  	<url-pattern>/e/*</url-pattern>
  	<dispatcher>FORWARD</dispatcher>
  	<dispatcher>REQUEST</dispatcher>
  </filter-mapping> 

    
            了解
                ERROR:因服务器错误而发送过来的请求

<body>
	亲,不好意思,你访问页面不存在~~
</body>


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


                INCLUDE:包含过来的请求

 

 

  • 三、案例2-统一字符编码

需求:
    以前我们开发的时候若有参数,第一步都是设置编码,才不会出现乱码,通过过滤器设置,到servlet或者jsp上的时候已经没有乱码问题
技术分析:
    filter 配置路径/* 过滤器的第一个位置
    在filter中重写getParameter(加强)

  • 3-1 步骤分析

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

  • 3-1-1 方法加强

    1.继承(获取构造器)
    2.装饰者模式(静态代理)
    3.动态代理    

  • 3-1-2 装饰者书写步骤

    1.要求装饰者和被装饰者实现同一个接口或者继承同一个类
    2.装饰者中要有被装饰者的引用
    3.对需要加强方法进行加强
    4.对不需要加强的方法调用原来的方法即可    

  • 3-1-3 加强request.getParameter(String key)

    首先请求的方式不同,处理的方式也不同
        获取请求的方法
        若是get请求
            new String(value.getBytes("iso8859-1"),"utf-8");
        若是post请求
            只需要设置一句话
            request.setCharacterEncoding("utf-8");            


public class EncodingFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@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() {
		// TODO Auto-generated method stub
		
	}

}

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);
	}
	
}
/**
 * Servlet implementation class LoginServlet
 */
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//1.获取用户名和密码
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		
		//2.打印在控制台
		System.out.println(username+"::"+password);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 

  • 3-1-4 最后将包装过的request对象(MyRequest)传递给servlet即可

        //2.放行 将包装过的request传递
        chain.doFilter(new MyRequest(request), response);

  • 3-2 关于获取参数的方法

    String getParameter(String name);// arr[0]
    String[] getParameterValues(String name);// map.get(name)
    Map<String,String[]> getParameterMap();

/**
 * 统一编码
 * @author Administrator
 *
 */
public class EncodingFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
		//1.强转
		HttpServletRequest request=(HttpServletRequest) req;
		HttpServletResponse response=(HttpServletResponse) resp;
		
		//2.放行
		chain.doFilter(new MyRequest(request), response);
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}
class MyRequest extends HttpServletRequestWrapper{
	private HttpServletRequest request;
	private boolean flag=true;
	
	
	public MyRequest(HttpServletRequest request) {
		super(request);
		this.request=request;
	}
	
	@Override
	public String getParameter(String name) {  
		if(name==null || name.trim().length()==0){
			return null;
		}
		String[] values = getParameterValues(name);
		if(values==null || values.length==0){
			return null;
		}
		
		return values[0];
	}
	
	@Override
	/**
	 * hobby=[eat,drink]
	 */
	public String[] getParameterValues(String name) {
		if(name==null || name.trim().length()==0){
			return null;
		}
		Map<String, String[]> map = getParameterMap();
		if(map==null || map.size()==0){
			return null;
		}
		
		return map.get(name);
	}
	
	@Override
	/**
	 * map{ username=[tom],password=[123],hobby=[eat,drink]}
	 */
	public Map<String,String[]> getParameterMap() {  
		
		/**
		 * 首先判断请求方式
		 * 若为post  request.setchar...(utf-8)
		 * 若为get 将map中的值遍历编码就可以了
		 */
		String method = request.getMethod();
		if("post".equalsIgnoreCase(method)){
			try {
				request.setCharacterEncoding("utf-8");
				return request.getParameterMap();
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else if("get".equalsIgnoreCase(method)){
			Map<String,String[]> map = request.getParameterMap();
			if(flag){
				for (String key:map.keySet()) {
					String[] arr = map.get(key);
					//继续遍历数组
					for(int i=0;i<arr.length;i++){
						//编码
						try {
							arr[i]=new String(arr[i].getBytes("iso8859-1"),"utf-8");
						} catch (UnsupportedEncodingException e) {
							e.printStackTrace();
						}
					}
				}
				flag=false;
			}
			//需要遍历map 修改value的每一个数据的编码
			
			return map;
		}
		
		return super.getParameterMap();
	}

 

  • 总结

  • 1 listener 监听器

    监听javaweb中的三个域对象        
    监听三个对象的创建和销毁
        ServletContextListener
        ServletRequestListener
        HttpSessionListener
    监听三个对象属性的变化
        ServletContextAttributeListener
        ServletRequestAttributeListener
        HttpSessionAttributeListener
    监听javabean在session中的状态
        注意:    javabean实现的接口 不需要在web.xml中配置
        HttpSessionActivationListener(javabean的活化和钝化)
        HttpSessionBindingListener(添加到session中还是从session中移除)    
    编写步骤:
        1.编写一个类  实现接口
        2.编写配置文件 
            <listener>
                <listener-class>....
            </listener>

  • 2 filter 接口,过滤请求和响应

    编写步骤:
        1.编写一个类 
            实现filter 重写三个方法
        2.编写配置文件    
            注册filter 绑定路径
    filter的生命周期(了解)
    url-pattern配置(和servlet一样)
        一个路径匹配到多个filter的时候,执行顺序有有web.xml中filter-mapping的顺序来决定的
    FilterChain
        必须放行才有可能到下一个Filter或者资源上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值