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>

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

posted @ 2017-11-07 20:48  LegendQi  阅读(300)  评论(0编辑  收藏  举报