Java EE入门教程系列第四章Servlet(四)——过滤器

4.4 过滤器

4.4.1 过滤器(Filter)简介

Servlet过滤器是服务器与客户端请求和响应的中间层组件。在实际项目开发中,Servlet过滤器主要用于拦截浏览器与服务间的请求与响应,根据过滤器内部的设置,查看、提取或修改交互的数据,之后再转给下一个资源。

主要作用有:

1)对请求的访问进行预处理,如防止乱码、添加必要的安全信息或安全处理等

2)对被过滤资源进行身份验证,实现一定程度上的权限控制

3)对请求进行合理的转发指派,降低服务器负载,提高服务器效率

可以把过滤器看成银行大堂经理,当用户去办理业务时,大堂经理会询问客户需要做什么,根据业务内容进行引导。如果表格填写错误,还会帮忙修正,如果用户去错了银行,也会进行提醒。

从工作原理看,过滤器可以改变一个request或修改一个response。过滤器并不是一个Servlet,它不会生成response,只是在request要离开Servlet时再处理response。以一种Servlet链的方式完成响应。一个过滤器的处理过程包括:

1)在客户端发起对Servlet文件的request时截获请求

2)在Servlet被调用前检查request

3)根据过滤器的设计,修改request头和request数据

4)根据过滤器的设计,修改response头和response数据

5)在Servlet被调用之后截获这个对象

开发者在创建自己的Filter时,必须要实现javax.servlet.Filter这个接口。该接口包含3个抽象方法:init()、doFilter()、destroy()。大多数情况下,Filter的销毁使用Java系统的自动回收机制,如果没有初始化配置的特殊要求,init()方法也不需要重载。

4.4.2 创建过滤器

首先创建被过滤文件First.java

package cy.filter;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class First
 */
@WebServlet("/First")
public class First extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public First() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.setContentType("text/html;charset=UTF-8");
		request.setCharacterEncoding("UTF-8");
		PrintWriter out=response.getWriter();
		try {
			  String getInfo=(String) getServletContext().getAttribute("Message");
				out.println("<html");
				out.println("<head>");
				out.println("<title></title>");
				out.println("</head>");
				out.println("<body>");
				out.println("lalala");
				
				out.println("</body>");
				out.println("</html");
			}finally {
				out.close();
			}
		System.out.println("执行当前的Servlet文件");
	}

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

}

右键项目名-new-Filter-填写类和包名

添加被过滤文件

package cy.filter;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

/**
 * Servlet Filter implementation class Filter
 */
@WebFilter(urlPatterns = { "/First"}, filterName = "Filter", servletNames = { "First" })
public class Filter implements javax.servlet.Filter {

    /**
     * Default constructor. 
     */
    public Filter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		// place your code here
		System.out.println("执行doFilter之前");
		// pass the request along the filter chain
		chain.doFilter(request, response);
		System.out.println("执行doFilter之后");
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

 

执行First.java:

从执行结果可以好好体会一下过滤过程。

下面举一个相对复杂一些的例子。实际上网过程中经常遇到这样的情况,没有登录浏览贴吧帖子时,看到帖子点击回复按钮时系统会弹出错误提示,提醒用户登录后才可以回复。这个功能可以使用过滤器方式实现。

下面将通过3个文件模拟上述过程:

回帖文件sendInfo.java,需要输入title和id两个参数,然后显示出来

package cy.filter;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class First
 */
@WebServlet("/sendInfo")
public class sendInfo extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public sendInfo() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out=response.getWriter();
		String title=request.getParameter("title");
		String id=request.getParameter("id");
		try {
			  
				out.println("<html");
				out.println("<head>");
				out.println("<title></title>");
				out.println("</head>");
				out.println("<body>");
				out.println("一个测试的信息:”"+title+"”来自于"+id);
				
				out.println("</body>");
				out.println("</html");
			}finally {
				out.close();
			}
		System.out.println("执行当前的Servlet文件");
	}

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

}

可以先运行一下这个文件,不过要注意这个文件不是直接运行的,回忆一下前面URL传参的知识,在地址栏给出参数即可得到信息:

过滤器文件MyFilter.java,过滤第一个文件,依据是检查里面的参数id的值是否不为空且值为“Hedy”,如果是则不作任何处理,让

Servlet向浏览器发送内容,如果不是,则拦截请求,直接重定向到错误文件

package cy.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class MyFilter
 */
@WebFilter(urlPatterns = { "/sendInfo" },filterName="MyFilter", servletNames = { "sendInfo" })
public class MyFilter implements Filter {

    /**
     * Default constructor. 
     */
    public MyFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		// place your code here
		HttpServletRequest req=(HttpServletRequest)request;//对这两个参数进行强制转换的原因是:doFilter()方法本身的请求与响应的参数类型为ServletRequest和ServletResponse,而Servlet请求与响应的参数类型为HttpServletRequest和HttpServletResponse.为了让过滤器拦截请求的同时可以获取客户端传过来的参数id,需要转换这个类型,从而通过getParameter()方法获取参数值。
		HttpServletResponse res=(HttpServletResponse)response;
      String isLog=req.getParameter("id");
      System.out.println(isLog);
      if((isLog!=null)&&(isLog.equals("Hedy"))) {
    	// pass the request along the filter chain
  		chain.doFilter(request, response); 
      }
      else {
    	  res.sendRedirect("/JSPLab/error.jsp");
      }
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

错误页面error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>出错啦!请先登录</h2>
</body>
</html>

这时再次运行sendInfo.java,修改id参数值不为Hedy:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值