所学Filter的总结和实验

Filter顾名思义是过滤器,那么我们如何使用他?
首先我们应该知道什么是Filter
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
  Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。
  如何写一个简答的过滤器
  @WebFilter("/myservlet1")//过滤路径
public class MyFilter1 implements Filter {

//初始化过滤器
@Override
public void init(FilterConfig filterConfig) throws ServletException {
    System.out.println("过滤器初始化了........init...  "+filterConfig);
}

//执行过滤
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    System.out.println("过滤前........doFilter ");
    //放行
    chain.doFilter(request, response);

    System.out.println("过滤后.......doFilter");

}

//销毁
@Override
public void destroy() {
    System.out.println("销毁了.....destroy");
}

}
  
  注意写过滤器必须要配置路径,你要让服务器知道你要过滤什么。
  2种方式
  1、在web.xml中配置
 



(参数根据需要不是必须的)







web.xml的优先级高于注解
2、利用注解@WebFilter配置
@WebFilter的参数
filename:过滤器的名字,决定了过滤器的初始化顺序(根据字母顺序排序)注意:是初始化顺序,不是拦截顺序。这里配置过的化可以直接在web.xml中直接配置映射。
value:过滤器拦截的路径。value可为数组,拦截多个路径。
initParams:初始化参数 通过config获取可以为一个数组用@WebInitParam()添加
其他的基本用不到。

拦截路径的常见形式:
1、/index.jsp 拦截index.jsp(举例说明)。
2、/*.jsp 拦截以jsp为结尾的jsp文件。
3、/*拦截所有的。

过滤器链
通常客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),那么这组过滤器就称为一条过滤器链。
每个过滤器实现某个特定的功能,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

过滤器的优先级
1、web.xml中根据Filter-mapping 的写入的先后先后顺序。
2、注解根据类名(注意是类名,不是filename)。
3、web.xml的优先级高于注解。
4、如果两个都配置了,则可能会过滤两次。

过滤的好处:可以进行预处理和后期处理。

过滤器的六个典型应用。
1、防止动态缓存(现在浏览器已经解决的这个问题)
2自动登陆(登陆之后将用户名密码通过加密放入cookie中,在过滤器中判断session的值为空的话在到cookie中找)。

//数据库工具类
public class DbHelper {

private static DataSource ds;
private static QueryRunner qr;
static{
	ds=new ComboPooledDataSource();
	qr=new QueryRunner(ds);
}
//执行非查询语句,返回值受影响的行数
public static int execute(String sql,Object... vs){
	try {
		return qr.execute(sql, vs);
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return 0;
}
//执行查询语句
public static <T> T querySingle(String sql,Class<T> clz,Object... vs){
	try {
		
		return qr.query(sql, new BeanHandler<>(clz),vs);
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return null;
}}




public class User {
private int id;
private String username;
private String pass;
public int getId() {
	return id;
}
public void setId(int id) {
	this.id = id;
}
public String getUsername() {
	return username;
}
public void setUsername(String username) {
	this.username = username;
}
public String getPass() {
	return pass;
}
public void setPass(String pass) {
	this.pass = pass;
}}

@WebFilter(value="/login.html")

public class AutoLoginFilter implements Filter {
/**

 * Default constructor. 
 */
public AutoLoginFilter() {
    // 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 {
	//强制转换为Http的请求和响应
	HttpServletRequest req=(HttpServletRequest) request;
	HttpServletResponse rep=(HttpServletResponse) response;
	
	//验证是否登录
	if(req.getSession().getAttribute("user")==null){
		//从Cookie获取上次保存的账号和密码
		Cookie[] cks=req.getCookies();
		User user=null;
		for(Cookie c:cks){
			if(c.getName().equals("user")){
				String[] us=c.getValue().split("@");
				user=new User();
				user.setUsername(us[0]);
				user.setPass(us[1]);
				break;
			}
		}
		//如果存储Cookie,那么就实现自动登录
		if(user!=null){//需要自动登录
			// 登录校验
			User user1 = DbHelper.querySingle("select * from tb_user where username=?", User.class, user.getUsername());
			boolean res=true;
			if (user1 != null) {
				if (user.getPass().equals(user1.getPass())) {
					req.getSession().setAttribute("user", user1);
					res=false;
					rep.sendRedirect(req.getServletContext().getContextPath()+"/success.jsp");
				}
			}
			if(res){//登录失败,之前的记录账号和密码错误
				Cookie ck=new Cookie("user","");
				ck.setPath("/");
				ck.setMaxAge(0);
				rep.addCookie(ck);
				rep.sendRedirect(req.getServletContext().getContextPath()+"/login.jsp");
			}
		}
		else{//直接登录页面
			chain.doFilter(request, response);
		}	
	}
	else{//如果已经登录,那么就直接放行
		rep.sendRedirect("success.jsp");
	}	
}
/**
 * @see Filter#init(FilterConfig)
 */
public void init(FilterConfig fConfig) throws ServletException {
	// TODO Auto-generated method stub
}

}

案例三 过滤脏词(通过重写requset的方法完成)
public class DirtyFilter 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 {
	
	chain.doFilter(new DirtyHttpServletRequest((HttpServletRequest)request), response);

}

@Override
public void destroy() {
	// TODO Auto-generated method stub
}
static class DirtyHttpServletRequest extends HttpServletRequestWrapper{

	private List<String> dirtywords=new ArrayList<String>();
	public DirtyHttpServletRequest(HttpServletRequest request) {
		super(request);
		dirtywords.add("sb");
		dirtywords.add("狗蛋");
		dirtywords.add("扯淡");
	}
	@Override
	public String getParameter(String name) {
		// TODO Auto-generated method stub
		String v=super.getParameter(name);
		for (String s : dirtywords) {
			v=v.replaceAll(s, "***");
		}
		return v;
	}
}

}

4、解决编码问题
public class CharacterEncodingFilter implements Filter {

//filter配置
private FilterConfig config;
//默认编码
private String defaultcharset="utf-8";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
	// TODO Auto-generated method stub
	this.config=filterConfig;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
		throws IOException, ServletException {
	String charset=config.getInitParameter("charset");
	if(charset==null){
		charset=defaultcharset;
	}
	//1设置请求和响应的编码
	request.setCharacterEncoding(charset);
	response.setContentType("text/html;charset="+charset);
	//2放行
	chain.doFilter(request, response);
	System.out.println("xxxxxxxxxxxxxxxx");

}

@Override
public void destroy() {
	
}

}
5、在服务器端压缩文件,到客户端解压,达到快速传递文件的效果。
@WebFilter("*.jsp")
public class GlobalGzipFilter implements Filter {

/**
 * Default constructor. 
 */
public GlobalGzipFilter() {
    // 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
	// 重构响应对象
	GzipResponse rsp=new GzipResponse((HttpServletResponse)response, new ByteArrayOutputStream());
	
	// pass the request along the filter chain
	chain.doFilter(request, rsp);
	//获取响应的内容
	ByteArrayOutputStream baos=rsp.getOutStream();
	System.out.println("压缩之前:"+baos.size()+"字节");
	//开始压缩
	//创建内存流对象,存储压缩之后的的内容
	ByteArrayOutputStream newbaos=new ByteArrayOutputStream();
	GZIPOutputStream gzip=new GZIPOutputStream(newbaos);
	gzip.write(baos.toByteArray());
	gzip.flush();
	gzip.close();
	System.out.println("压缩之后:"+newbaos.size()+"字节");
	HttpServletResponse resp=(HttpServletResponse)response;
	//设置消息头,标记内容为gzip
	resp.setHeader("Content-Encoding", "gzip");
	resp.getOutputStream().write(newbaos.toByteArray());//写出真正的内容	
}

/**
 * @see Filter#init(FilterConfig)
 */
public void init(FilterConfig fConfig) throws ServletException {
	// TODO Auto-generated method stub
}
//自定义的响应对象
private class GzipResponse extends HttpServletResponseWrapper{

	private ByteArrayOutputStream baos;//内存输出字节流
	private PrintWriter pw;
	public GzipResponse(HttpServletResponse response,ByteArrayOutputStream baos) {
		super(response);
		this.baos=baos;
		// TODO Auto-generated constructor stub
	}
	//获取响应内容的内存流对象,存储着要响应的数据
	public ByteArrayOutputStream getOutStream(){
		// TODO Auto-generated method stub
		if(pw!=null){
			pw.flush();
		}
		return baos;
	}
	@Override
	public PrintWriter getWriter() throws IOException {
		//将响应的内容写出到指定的内存流中
		pw=new PrintWriter(new OutputStreamWriter(baos,"UTF-8"));
		return pw;
	}	
}

}
案例6 实现图片防盗链
@WebFilter(filterName = “StealFilter”,urlPatterns = {".jpg",".png"})

public class StealFilter implements Filter {

public void destroy() {
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    HttpServletRequest request= (HttpServletRequest) req;
    HttpServletResponse response= (HttpServletResponse) resp;
    String referer = request.getHeader("referer");
    String url="http://localhost:8080"+request.getContextPath();
    System.out.println(url);
    if(referer!=null&&referer.startsWith(url)){
        System.out.println("页面正常请求");
        chain.doFilter(req, resp);
    }else{
        System.out.println("盗链");
        request.getRequestDispatcher("/error/steal.jpg").forward(request, response);
    }

}

public void init(FilterConfig config) throws ServletException {

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值