web day21 web过滤器Filter,应用案例统计IP,解决全站乱码,粗粒度权限控制,页面静态化

JavaWeb三大组件

1. 都需要在web.xml中进行配置

Servlet

Listener(2个感知监听器不需要配置)

Filter

过滤器

它会在一组资源(jsp、servlet、.css、.html等等)的前面执行!

它可以让请求得到目标资源,也可以不让请求达到!

* 过滤器有拦截请求的能力!

登录:

允许它访问AServlet、BServlet、CServlet

-------------------------------

过滤器如何编写

1. 写一个类实现Filter接口

2. 在web.xml中进行配置

Filter接口

void init(FilterConfig)

* 创建之后,马上执行;Filter会在服务器启动时就创建!

void destory()

* 销毁之前执行!在服务器关闭时销毁

voiddoFilter(ServletRequest,ServletResponse,FilterChain)

* 每次过滤时都会执行

Filter是单例的!

web.xml部署

<filter>

<filter-name>xxx</filter-name>

<filter-class>cn.itcast.web.filter.AFitler</fitler-class>

</filter>

<fitler-mapping>

<filter-name>xxx</filter-name>

<url-pattern>/*</url-pattern>

<!--除了url-pattern servlet也可以 -->

</filter-mapping>

-------------------------------

FilterConfig-->与ServletConfig相似

* 获取初始化参数:getInitParameter()

* 获取过滤器名称:getFilterName()

* 获取appliction:getServletContext()

FilterChain

*doFilter(ServletRequest, ServletResponse):放行!

放行,就相当于调用了目标Servlet的service()方法!

-------------------------------

-------------------------------

多过滤器

FilterChain#doFilter()方法:

执行目标资源,或是执行下一个过滤器!如果没有下一个过滤器那么执行的是目标资源,如果有,那么就执行下一个过滤器!

-------------------------------

过滤器的四种拦截方式

<dispatcher>REQUEST</dispatcher>默认的!

<dispatcher>FORWARD</dispatcher>

<dispatcher>INCLUDE</dispatcher>

<dispatcher>ERROR</dispatcher>

在<filter-mapping>中进行配置!

-------------------------------

多个过滤器的执行顺序

<filter-mapping>的配置顺序决定了过滤器的执行顺序!

Filter应用案例

1.分IP统计网站访问次数

代码

lintener

public class AListener implements ServletContextListener {
	/**
	 * 在服务器启动时创建Map,保存到ServletContext
	 */
    public void contextInitialized(ServletContextEvent sce) {
    	// 创建Map
    	Map<String,Integer> map = new LinkedHashMap<String,Integer>();
    	// 得到ServletContext
    	ServletContext application = sce.getServletContext();
    	// 把map保存到application中
    	application.setAttribute("map", map);
    }

    public void contextDestroyed(ServletContextEvent sce) {
    }
}

filter

/**
 * 从application中获取Map
 * 从request中得到当前客户端的IP
 * 进行统计工作,结果保存到Map中
 * @author cxf
 *
 */
public class AFilter implements Filter {
	private FilterConfig config;
	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		/*
		 * 1. 得到application中的map
		 * 2. 从request中获取当前客户端的ip地址
		 * 3. 查看map中是否存在这个ip对应访问次数,如果存在,把次数+1再保存回去
		 * 4. 如果不存在这个ip,那么说明是第一次访问本站,设置访问次数为1
		 */
		/*
		 * 1. 得到appliction
		 */
		ServletContext app = config.getServletContext();
		Map<String,Integer> map = (Map<String, Integer>) app.getAttribute("map");
		/*
		 * 2. 获取客户端的ip地址
		 */
		String ip = request.getRemoteAddr();
		/*
		 * 3. 进行判断
		 */
		if(map.containsKey(ip)) {//这个ip在map中存在,说明不是第一次访问
			int cnt = map.get(ip);
			map.put(ip, cnt+1);
		} else {//这个ip在map中不存在,说明是第一次访问
			map.put(ip, 1);
		}
		app.setAttribute("map", map);//把map再放回到app中

		chain.doFilter(request, response);//肯定放行
	}

	/**
	 * 在服务器启动时就会执行本方法,而且本方法只执行一次!
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		this.config = fConfig;
	}
}

2.粗粒度权限控制

public class AdminFilter implements Filter {

	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		/*
		 * 1. 得到session
		 * 2. 判断session域中是否存在admin,如果存在,放行
		 * 3. 判断session域中是否存在username,如果存在,放行,否则打回到login.jsp,并告诉它不要瞎留达
		 */
		HttpServletRequest req = (HttpServletRequest) request;
		String name = (String)req.getSession().getAttribute("admin");
		if(name != null) {
			chain.doFilter(request, response);
		} else {
			req.setAttribute("msg", "您可能是个啥,但肯定不是管理员!");
			req.getRequestDispatcher("/login.jsp").forward(request, response);
		}
	}

	public void init(FilterConfig fConfig) throws ServletException {

	}
}

------------------
public class UserFilter implements Filter {
	public void destroy() {
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		/*
		 * 1. 得到session
		 * 2. 判断session域中是否存在admin,如果存在,放行
		 * 3. 判断session域中是否存在username,如果存在,放行,否则打回到login.jsp,并告诉它不要瞎留达
		 */
		HttpServletRequest req = (HttpServletRequest) request;
		String name = (String)req.getSession().getAttribute("admin");
		if(name != null) {
			chain.doFilter(request, response);
			return;
		}

		name = (String)req.getSession().getAttribute("username");
		if(name != null) {
			chain.doFilter(request, response);
		} else {
			req.setAttribute("msg", "您啥都不是,不要瞎溜达!");
			req.getRequestDispatcher("/login.jsp").forward(request, response);
		}
	}

	public void init(FilterConfig fConfig) throws ServletException {

	}
}

3.解决post/get中文编码问题

原理:利用装饰模式及HttpServletRequestWrapper包装类

filter

public class EncodingFilter implements Filter {
	public void destroy() {

	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// 处理post请求编码问题
		request.setCharacterEncoding("utf-8");

		HttpServletRequest req = (HttpServletRequest) request;

		/*
		 * 处理GET请求的编码问题
		 */
//		String username = request.getParameter("username");
//		username = new String(username.getBytes("ISO-8859-1"), "UTF-8");

		/*
		 * 调包request
		 * 1. 写一个request的装饰类
		 * 2. 在放行时,使用我们自己的request
		 */
		if(req.getMethod().equals("GET")) {
			EncodingRequest er = new EncodingRequest(req);
			chain.doFilter(er, response);
		} else if(req.getMethod().equals("POST")) {
			chain.doFilter(request, response);
		}
	}

	public void init(FilterConfig fConfig) throws ServletException {

	}
}

装饰包装类

/**
 * 装饰reqeust
 * @author cxf
 *
 */
public class EncodingRequest extends HttpServletRequestWrapper {
	private HttpServletRequest req;

	public EncodingRequest(HttpServletRequest request) {
		super(request);
		this.req = request;
	}

	public String getParameter(String name) {
		String value = req.getParameter(name);

		// 处理编码问题
		try {
			value = new String(value.getBytes("iso-8859-1"), "utf-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}

		return value;
	}
}

4.页面静态化

1. 第一步

写一个简单的单表查询(略)

2. 第二步:什么是页面静态化!

首次访问去数据库获取数据,然后把数据保存到一个html页面中(服务器)

二次访问,就不再去数据库获取了,而是直接显示html

----------------------------------------------------------

1. 目标!

给出一个过滤器,把servlet请求的资源所做输出保存到html中,重定向到html页面。

二次访问时,这个html已经存在,那么直接重定向,不用再去访问servlet!

代码

filter

public class StaticFilter implements Filter {
	private FilterConfig config;
	public void destroy() {}
	public void init(FilterConfig fConfig) throws ServletException {
		this.config = fConfig;
	}

	public void doFilter(ServletRequest request,
			ServletResponse response, FilterChain chain)
					throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;
		/*
		 * 1. 第一次访问时,查找请求对应的html页面是否存在,如果存在重定向到html
		 * 2. 如果不存在,放行!把servlet访问数据库后,输出给客户端的数据保存到一个html文件中
		 *   再重定向到html
		 */
		/*
		 * 一、获取category参数!
		 * category有四种可能:
		 * * null --> null.html
		 * * 1 --> 1.html
		 * * 2 --> 2.html
		 * * 3 --> 3.html
		 *
		 * html页面的保存路径, htmls目录下
		 *
		 * 判断对应的html文件是否存在,如果存在,直接重定向!
		 */
		String category = request.getParameter("category");
		String htmlPage = category + ".html";//得到对应的文件名称
		String htmlPath = config.getServletContext().getRealPath("/htmls");//得到文件的存放目录
		File destFile = new File(htmlPath, htmlPage);

		if(destFile.exists()) {//如果文件存在
			// 重定向到这个文件
			res.sendRedirect(req.getContextPath() + "/htmls/" + htmlPage);
			return;
		}

		/*
		 * 二、如果html文件不存在,我们要生成html
		 * 1. 放行,show.jsp会做出很多的输出,我们要让它别再输出给客户端,而是输出到我们指定的一个html文件中
		 * 完成:
		 * * 调包response,让它的getWriter()与一个html文件绑定,那么show.jsp的输出就到了html文件中
		 */
		StaticResponse sr = new StaticResponse(res, destFile.getAbsolutePath());
		chain.doFilter(request, sr);//放行,即生成了html文件

		// 这时页面已经存在,重定向到html文件
		res.sendRedirect(req.getContextPath() + "/htmls/" + htmlPage);
	}
}

包装响应类

public class StaticResponse extends HttpServletResponseWrapper {
	private PrintWriter pw;

	/**
	 * String path:html文件路径!
	 * @param response
	 * @param path
	 * @throws UnsupportedEncodingException
	 * @throws FileNotFoundException
	 */
	public StaticResponse(HttpServletResponse response, String path)
			throws FileNotFoundException, UnsupportedEncodingException {
		super(response);

		// 创建一个与html文件路径在一起的流对象
		pw = new PrintWriter(path, "utf-8");
	}

	public PrintWriter getWriter() {
		// 返回一个与html绑定在一起的printWriter对象
		// jsp会使用它进行输出,这样数据都输出到html文件了。
		return pw;
	}
}

时间: 2024-12-15 06:52:18

web day21 web过滤器Filter,应用案例统计IP,解决全站乱码,粗粒度权限控制,页面静态化的相关文章

传智播客JavaWeb day14--监听器(用户踢人)、过滤器(解决全站乱码)

1. 2. 3. 4. 5. filter应用 1.用过滤器解决全站乱码问题 1.1 乱码分类 乱码分为get和post方式请求乱码 1.2 post请求乱码解决 post请求乱码很好解决只需一行代码搞定request.setCharacterEncoding("utf-8")告诉服务器用utf-8来获取参数即可 1.3 get请求乱码解决 问题:不能针对某个参数去解决乱码问题,因为过滤器是全站通用的,其他的请求可能没有这个参数,所以想到改造获取请求参数的三个方法,而直接继承的方式会有

利用filter和动态代理解决全站乱码问题

1.利用filter和动态代理解决全站乱码问题 1.1filter的代码 package com.baowei.filter; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import javax.servlet.Filter; import javax.servlet

学习笔记_过滤器应用(粗粒度权限控制(拦截是否登录、拦截用户名admin权限))

RBAC ->基于角色的权限控制 l  tb_user l  tb_role l  tb_userrole l  tb_menu(增.删.改.查) l  tb_rolemenu 1 说明 我们给出三个页面:index.jsp.user.jsp.admin.jsp. l  index.jsp:谁都可以访问,没有限制: l  user.jsp:只有登录用户才能访问: l  admin.jsp:只有管理员才能访问. 2 分析 设计User类:username.password.grade,其中grad

高性能Java Web 页面静态化技术

package com.yancms.util; import java.io.*; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; import org.apache.commons.httpclient.params.HttpMethodParams; /** * 静态页面引擎技术(突乱了乱码问题UTF-8) * @author 吴彦文 * */ public cl

Servlet中通过过滤器实现统一的手动编码(解决中文乱码)

<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://<a href="http://lib.csdn.net/base/javaee" class='replace_word' title="Java EE知识库" target='_blank' style='color:#

利用Filter技术解决中文乱码的终极实现

利用包装类,解决乱码问题 web.xml的配置 <filter> <filter-name>CharacterEncodingFilter2</filter-name> <filter-class>cn.itcast.web.filter.example.CharacterEncodingFilter2</filter-class> </filter> <filter-mapping> <filter-name>

Java Web学习(35):Filter学习(三)

解决项目字符乱码 乱码问题说明:基本上在每个Servlet中都要处理乱码问题,所以应该把这个工作放到过滤器中来完成. 获取请求参数中的乱码问题: POST请求:request.setCharacterEncoding("UTF-8"); GET请求:new String(request.getParamter("xxx").getBytes("ISO-8859-1","UTF-8"); 响应的乱码问题: response.se

深入分析JavaWeb Item36 -- 过滤器Filter高级应用

在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可以使用Decorator(装饰器)模式对request.response对象进行包装,再把包装对象传给目标资源,从而实现一些特殊需求. 一.Decorator设计模式 1.1.Decorator设计模式介绍 当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强: 编写子类,覆盖需增强的方法. 使用Decorator设计模式对方法进行增强. 使用代理 在阎宏博士的<JAVA与模式>一书中

监听器listener&amp;过滤器filter

Servlet技术规范 描述三种技术 : Servlet(服务器小程序) .Filter(过滤器) .Listener(监听器) Filter运行在服务器端,对服务器端web资源的访问 进行拦截,起到过滤的作用 Servlet API中 定义接口 Filter,用户只需要编写程序实现Filter接口,完成过滤器编写 Filter快速入门1.编写类 实现 Filter接口2.在服务器端注册 Filter (配置拦截哪个web资源) ----- web.xml   <!-- 注册过滤器 -->