• 2017.11.7 JavaWeb------Servlet过滤器


    JavaWeb------Servlet过滤器

    (1)过滤器是web服务器上的组件,它们对客户和资源之间的请求和响应进行过滤。Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。
    @(2)过滤器的工作原理是:

    当servlet容器接收到对某个资源的请求,它要检查是否有过滤器与之关联。如果有过滤器与该资源关联,servlet容器将把该请求发送给过滤器。在过滤器处理完请求后,它将做下面3件事:
    •	产生响应并将其返回给客户;
    •	如果有过滤器链,它将把(修改过或没有修改过)请求传递给下一个过滤器;
    •	将请求传递给不同的资源。
    当请求返回到客户时,它是以相反的方向经过同一组过滤器返回。过滤器链中的每个过滤器够可能修改响应。
    

    (3)过滤器API主要包括:Filter、FilterConfig和FilterChain接口。

    1.FilterConfig 使用
    	Filter 的 init 方法中提供了一个 FilterConfig 对象。
    		如 web.xml 文件配置如下:
    			<filter>
    			    <filter-name>LoginFilter</filter-name>
    			    <filter-class>com.runoob.test.LogFilter</filter-class>
    			    <init-param>
    		        <param-name>Site</param-name>
    		        <param-value>abc</param-value>
    			    </init-param>
    		    </filter>
    2.在 init 方法使用 FilterConfig 对象获取参数:
    		public void  init(FilterConfig config) throws ServletException {
    		    // 获取初始化参数
    	    String site = config.getInitParameter("Site"); 
    		    // 输出初始化参数
    	    System.out.println("网站名称: " + site); 
    		}
    

    (4)回答一下两个问题

    1. 试简述过滤器有哪些功能?

    	1)转换字符编码
     中文网页编码常用的就是gb2312或是UTF-8,但TOMCAT会默认用编码iso-8859-1,所以需要把所有经过TOMCAT的中文字符进行转换,如果手动在request里改很麻烦,可以用一个filter对所有的request进行拦截,进行编码转换。
    	 2)管理Hibernate的session
     在Web 里用Hibernate常常是把session绑定到线程,但往往要求一个session在一个请求的活动中都有效,这样可以保证同一活动中能共享 lazy bean。用filter能到达这个目的,在doFilter之前绑定session到线程,在doFilter后关闭session,这样既可以保证 session不会泄漏,也能让lazy bean在同一请求周期里共享
    	 3)做权限审查
     在web层里需要对很多资源进行逻辑类似的安全保障,通过filter可以在调用这些资源前加上一个屏障,这样既可以把安全代码和逻辑代码相分离,也可以很好的reuse这些安全模块
    	 4)做cache
     在web层常常需要对一些请求返回进行缓存,这样可以有效的减轻服务器的压力,filter可以对请求进行拦截,查询缓存,若有效则直接返回缓存内容,若无效则进行实际的服务器请求,返回给用户,并对缓存进行更新,以备下次请求
    	 5)做拦截器的代理
     有的时候需要把一些拦截器用到web层,filter可以很好地充当代理的角色,比如可以在Spring里做好拦截器的Bean,再通过filter把这些Bean和相应的web请求桥接起来。
    	 6)过滤特殊字符
     有时需要过滤特殊字符,比如防止sql注入,Filter可以很好达到这个目的
    

    (5)web.xml配置各节点说明

    ~~<filter>指定一个过滤器。
    ~~<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
    ~~<filter-class>元素用于指定过滤器的完整的限定类名。
    ~~<init-param>元素用于为过滤器指定初始化参数,它的子元素param-name>指定参数的名字,<param-value>指定参数的值。
    ~~在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。
    ~~<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径 filter-name>子元素用于设置filter的注册名称。该值必须是在filter>元素中声明过的过滤器的名字
    <url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)
    
    ~~<servlet-name>指定过滤器所拦截的Servlet名称。
    ~~<dispatcher>指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个<dispatcher>子元素用来指定 Filter 对资源的多种调用方式进行拦截。
    
    ~~<dispatcher>子元素可以设置的值及其意义 REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
    
    ~~INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
    
    ~~FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
    
    ~~ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
    

    总结:过滤器中我们可以根据 doFilte() 方法中的 request 对象获取表单参数信息,例如:我们可以获取到请求的用户名和密码进行逻辑处理,也可以通过 response 对用户做出回应。比如,如果验证用户名不正确,禁止用户访问 web 资源,并且向浏览器输出提示,告诉用户用户名或者密码不正确等等;


    public void doFilter(ServletRequest req, ServletResponse resp,
    FilterChain chain) throws IOException, ServletException {
    
        //获取请求信息(测试时可以通过get方式在URL中添加name)
        //http://localhost:8080/servlet_demo/helloword?name=123
        String name = req.getParameter("name");
    
        // 过滤器核心代码逻辑
        System.out.println("过滤器获取请求参数:"+name);
        System.out.println("第二个过滤器执行--网站名称:www.runoob.com");
    
        if("123".equals(name)){
            // 把请求传回过滤链
            chain.doFilter(req, resp);
        }else{
            //设置返回内容类型
            resp.setContentType("text/html;charset=GBK");
    
            //在页面输出响应信息
            PrintWriter out = resp.getWriter();
            out.print("<b>name不正确,请求被拦截,不能访问web资源</b>");
            System.out.println("name不正确,请求被拦截,不能访问web资源");
        }
    }
    

    (6)实验题目:编写一个过滤器改变请求编码。

    【步骤1】编写一个loginform.html文件
    //loginform.html
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>使用过滤器改变请求编码</title>
        <meta http-equiv="Content-Type" content="text/html;charset=GB2312">
      </head>
      <body>
      <center>
      <h2>请输入用户名和口令:</h2>
      <form method="post" action="servlet/CheckParamServlet">
    	<table>
    	  <tr>
    		<td>用户名:</td>
    		<td><input name="name" type="text"></td>
    	  </tr>
    	  <tr>
    		<td>口    令:</td>
    		<td><input name="pass" type="password"></td>
    	  </tr>
    	  <tr>
    	        <td></td>
                    <td>
                      <input name="ok" type="submit" value="提交">
                      <input name="cancel" type="reset" value="重置">
                    </td>
    	  </tr>
    			 </table>
      		   </form>
     	   </center>
        </body>
    </html>
    

    【步骤2】编写处理请求参数的Servlet
    package servlets;
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    public class CheckParamServlet extends HttpServlet{
    	private static final long serialVersionUID = 1L;
    
    public void doGet(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException {
    
         String name = request.getParameter("name");
         String pass = request.getParameter("pass");
         response.setContentType("text/html;charset=gb2312");
         PrintWriter out = response.getWriter();
         
         out.println("<html><head><title>Param Test</title></head>");   
         out.println("<h3 align=center>你的用户名为:"+name+"</h3>");
         out.println("<h3 align=center>你的口令为:"+pass+"</h3>");
         out.println("</body></html>");          
       }
       public void doPost(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException { 
           doGet(request,response);
       } 
    }
    

    【步骤3】修改web.xml文件,加入下面代码:
    <servlet>
         <servlet-name>CheckParamServlet</servlet-name>
         <servlet-class>CheckParamServlet</servlet-class>
      </servlet>
      <servlet-mapping>
         <servlet-name>CheckParamServlet</servlet-name>
         <url-pattern>/servlet/check</url-pattern>
      </servlet-mapping>
    

    实验结果:当用户点击提交会出现用户名会变成问号的情况

    【步骤5】过滤器代码如下:
    package filter;
    import java.io.IOException;
    import javax.servlet.*;
    public class EncodingFilter implements Filter {
    	protected String encoding = null;
    	protected FilterConfig config;
    	public void init(FilterConfig filterConfig) throws ServletException {
    		this.config = filterConfig;
    		// 得到在web.xml中配置的编码
    		this.encoding = filterConfig.getInitParameter("Encoding");
    	}
    	public void doFilter(
    		ServletRequest request,
    		ServletResponse response,
    		FilterChain chain)
    		throws IOException, ServletException {
    		if (request.getCharacterEncoding() == null) {			
    			// 得到指定的编码
    			String encode = getEncoding();
    			if (encode != null) {				
    				//设置request的编码
    				request.setCharacterEncoding(encode);
    				response.setCharacterEncoding(encode);		
    			}
    		}
    		chain.doFilter(request, response);
    	}
    	protected String getEncoding() {
    		return encoding;
    	}
    	public void destroy() {
    	}
    }
    
    【步骤6】在web.xml文件中配置过滤器,加入下面代码:
    <filter>
       <filter-name>EncodingFilter</filter-name>
       <filter-class>filter.EncodingFilter</filter-class>
          <init-param>
            <param-name>Encoding</param-name>
            <param-value>gb2312</param-value>
          </init-param>
     </filter>
    
     <filter-mapping>
       <filter-name>EncodingFilter</filter-name>
       <url-pattern>/*</url-pattern>
     </filter-mapping>
    

    实验结果:输入的用户名实现了中文转换

  • 相关阅读:
    Python IDE
    python 3.x 不再提供raw_print()
    Python代码风格建议(转)
    在JSP页面中输出JSON格式数据
    MyEclipse 10 优化
    MB/GB/TB/PB/EB/ZB/YB/NB/DB/CB存储空间都是多大?如何换算?
    为什么民众不以偷税为耻_岑科
    彻底解剖人民币升值问题_岑科
    script 加载顺序问题的延展研究
    如何快速实现 markdown 转 HTML 文档?
  • 原文地址:https://www.cnblogs.com/qichunlin/p/7801020.html
Copyright © 2020-2023  润新知