JavaWeb 之过滤器

1. 什么是过滤器
- Servlet 是用来处理请求的, 过滤器是用来拦截请求的.
- 当用户请求某个 Servlet 时,会先执行部署在这个请求上的 Filter, 而 Filter 决定是否调用 Servlet.
当执行 Servlet 代码完成后, 还会执行 Filter 后面的代码!! - 它会在一组资源(jsp, servlet, css, html 等等)的前面执行.
- Filter 是单例的!!
2. 编写过滤器
2.1 步骤
- 写一个类实现 Filter 接口;
- 在 web.xml 中进行配置.
2.2 filter 接口的三个方法
void init(FilterConfig)- 创建之后,马上执行, Filter 会在服务器启动时创建!
void destroy()- 销毁之前执行. 在服务器关闭时,销毁!
void doFilter(ServletRequest, ServletResponse, FilterChain)- 每次过滤时,都会执行.
2.3 web.xml 中的配置
<filter>
<filter-name>xxx</filter-name>
<filter-class>cn.itcast.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>xxx</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.4 Filter 相关的类型
FilterConfig, 与 ServletConfig 相似
- 获取初始化参数:
getInitParameter(); - 获取过滤器名称:
getFilterName(); - 获取 application:
getServletContext(); (较常用) - 获取所有初始化参数的名称:
Enumeration getInitParameterNames();
- 获取初始化参数:
FilterChain
- doFilter(ServletRequest, ServletResponse), 表示放行!
相当于调用了目标 Servlet 的 service() 方法.
- doFilter(ServletRequest, ServletResponse), 表示放行!
2.5 多过滤器
- FilterChain 的 doFilter() 方法: 执行目标资源, 或是执行下一个过滤器!
// 如果访问 AServlet, 需要经过AFilter 和 BFilter 两个过滤器,
AFilter#start...
BFilter#start...
AServlet...
BFilter#end...
AFilter#end...
3. 过滤器的四种拦截方式
- 拦截请求(默认拦截方式)
- 拦截转发
- 拦截包含
- 拦截错误
// <filter-mapping> 进行配置 <dispatcher> 元素
<filter>
<filter-name>AFilter</filter-name>
<filter-class>cn.itcast.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/AServlet</url-pattern>
<dispatcher>REQUEST</dispatcher> // 拦截请求
<dispatcher>FORWARD</dispatcher> // 拦截转发
<dispatcher>INCLUDE</dispatcher> // 拦截包含
<dispatcher>ERROR</dispatcher> // 拦截错误
</filter-mapping>
4. 多个过滤器的执行顺序
- <filter-mapping> 的配置顺序决定了过滤器的执行顺序!!
5. 过滤器的应用场景
- 执行目标资源之前做预处理工作, 例如设置编码,这种通常都会放行, 只是在目标资源执行之前做一些准备工作;
- 通过条件判断是否放行, 例如校验当前用户是否已经登录, 或者用户 IP 是否已经被禁用;
- 在目标资源执行后, 做一些后续的特殊处理工作, 例如对目标资源输出的数据进行处理;
// 示例一: 分 IP 统计访问次数
/*
* 分析:
* 1. 使用 Map<String, Integer> 来装载统计的数据;
* 2. 使用 ServletContextListener, 在服务器启动时完成创建;
* 3. Map 保存到 ServletContext 中;
* 因为 Map 需要在 Filter 中用来保存数据,
* 而页面需要打印 Map 中的数据.
*/
// AListener
public class AListener implements SerlvetContextListener {
// 在服务器启动时, 创建Map, 保存到 ServletContext中
public void contextInitialized(SerlvetContextEvent sce){
Map<String, Integer> map = new LinkedHashMap<String,Integer>();
// 得到 ServletContext
ServletContext application = sce.getServletContext();
// 把 map 保存到 application 中
application.setAttribute("map",map);
}
public void contextDestroyed(ServletContextEvent sce){
}
}
// AFilter
public class AFilter implements Filter{
private FilterConfig config;
public void destory(){
}
public void init(FilterConfig config) throws ServletException{
// 赋值
this.config = config;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException{
// 得到 application 中的 map
ServletContext app = config.getServletContext();
Map<String,Integer> map = (Map<String,Integer>)app.getAttribute("map");
// 从 request 域中得到 ip 地址
String ip = request.getRemoteAddr();
// 查看 map 中是否存在这个 ip 对应的访问次数, 如果存在, 把次数加 1 再保存回去
// 如果不存在这个 ip, 那么设置这个 ip 的访问次数为 1
if(map.containsKey(ip)){
int cnt = map.get(ip);
map.put(ip,cnt+1);
}else{
map.put(ip,1);
}
// 把 map 放回到 application 中
app.setAttribute("map",map);
// 放行
chain.doFilter(request,response);
}
}
// 示例二: 解决全站字符乱码(POST 和 GET 中文乱码问题)
// index.jsp
<body>
<h1>主页</h1>
<%-- POST 请求 --%>
<form action="<c:url value='/AServlet'/>" method="post">
用户名:<input type="text" name="username" value="张三"/><br/>
<input type="submit" value="登录"/>
</form>
<%-- GET 请求, tomcat 8.0 以上版本,没有乱码问题 --%>
<a href="<c:url value='/AServlet?username=李四'"/>点击这里</a>
</body>
// EncodingFilter
// 处理 POST 请求编码问题
request.setCharacterEncoding("utf-8");
// 处理 GET 请求编码问题
// 需要调包 request:
// 写一个 request 的装饰类
// 在放行时,使用我们自己的 request
if(req.getMethod().equals("GET")){
HttpServletRequest req = (HttpServletRequest)request;
EncodingRequest er = new EncodingRequest(req);
chain.doFilter(er,response);
}else if(req.getMethod().equals("POST")){
chain.doFilter(request,response);
}
// EncodingRequest 类, 即 request 的装饰类
// 装饰 request 的 getParameter(String name) 方法
public class EncodingRequest implements HttpServletRequest{
private HttpServletRequest request;
// 有参构造方法(是你,还有你)
public EncodingRequest(HttpServletRequest request){
this.request = request;
}
// 增强 request 的方法
public String getParameter(String name){
String value = request.getParameter(name);
// 处理编码问题
try{
value = new String(value.getBytes("iso-8859-1"),"utf-8");
}catch(Exception e){
throw new RuntimeException(e);
}
return value;
}
// 复写 request 其他方法 (一切拜托你)
....
}
// EncodingRequest 类的升级版
// EncodingRequest 类继承 HttpServletRequestWrapper 类即可
// HttpServletRequestWrapper 实现了 HttpServletRequest 中的所有方法
public class EncodingRequest extends HttpServletRequestWrapper{
private HttpServletRequest req;
// 构造方法
public EncodingRequest(HttpServletRequest request){
// 将 request 参数传递给父类 HtttpServletRequestWrapper
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;
}
}
参考资料:
JavaWeb 之过滤器的更多相关文章
- [javaweb]Java过滤器与包装设计模式的实用案例.
在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可以使用Decorator(装饰器)模式对request.response对象进行包装,再把包装对象传给目 ...
- JavaWeb基础—过滤器Filter
一.概念 JavaWeb三大组件之一(组件都有一个特性,需要在web.xml中配置) 过滤器:会在一组资源(jsp servlet等)的前面执行,可以让请求得到目标资源,也可以终止请求,不再继续 也就 ...
- IT兄弟连 JavaWeb教程 过滤器3
过滤器案例:字符编码过滤器 在JavaWeb程序开发中,由于Web容器内部所使用编码格式并不支持中文字符集,所以,处理浏览器请求中的中文数据就会出现乱码现象. 图3 无字符编码过滤器 从上图可以看出 ...
- IT兄弟连 JavaWeb教程 过滤器1
Servlet过滤器是从Servlet2.3规范开始新增的功能,并在Servlet2.4规范中得到增强,监听器可以监听到Web应用程序启动和关闭.创建过滤器和监听器需要继承相应接口,并对其进行配置. ...
- JavaWeb 10_Filter过滤器
一.什么是Filter? 1.Filter 过滤器它是JavaWeb的三大组件之一-.三大组件分别是: Servlet 程序.Listener 监听器.Filter 过滤器2.Filter 过滤器它是 ...
- javaweb登陆过滤器实现
在web.xml中配置登陆过滤器: <!-- 配置登陆过滤器 --> <filter> <filter-name>loginFilter</filter-na ...
- JavaWeb中过滤器Filter的使用示例
https://github.com/YouXianMing/Java-Web-Study/tree/master/Servlet-Filter 过滤器示例基于以下流程 测试效果如下 web.xml配 ...
- JavaWeb基础-过滤器监听器
过滤器 1定义:过滤器是一个服务器的组件,他可以截取用户端的请求与响应信息,并对这些信息进行过滤;过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息. 2过滤器的工作原理: 3过滤器 ...
- JavaWeb的过滤器Filter
Filter的作用是在请求到达web资源(HTML.css.Servlet.Jsp)之前拦截,做一个预处理. 创建一个类实现Filter接口,在web.xml中对文件进行配置 <filter&g ...
随机推荐
- PHP-CURL在POST请求时的注意事项
今天搞12306抢票, 在用CURL模拟POST请求校验验证码时, 无论如何12306都返回零, 正常应该返回True或者False, 最后查找原因如下 只是请求头 Content-Type 用了 a ...
- Hackerrank - Game Of Rotation 题解
旋转一个数组以得到最大值. 陷阱就是:不能排序.须要模拟操作旋转,并设计公式计算旋转后的和. 要求是O(n)时间完毕. 原题: https://www.hackerrank.com/challenge ...
- php模板原理PHP模板引擎smarty模板原理浅谈
mvc是开发中的一个伟大的思想,使得开发代码有了更加清晰的层次,让代码分为了三层各施其职.无论是对代码的编写以及后期的阅读和维护,都提供了很大的便利. 我们在php开发中,视图层view是不允许有ph ...
- Atitit. Ati IDE 开发平台的第一版规划
Atitit. Ati IDE 开发平台的第一版规划 1. 增加业务类型复杂类型内置1 1.1. 简单类型string int float自动类型转换以及2 1.2. $变量str连接2 2. Dsl ...
- xilinx平台DDR3设计教程之仿真篇_中文版教程
https://wenku.baidu.com/view/ac32c8bcf705cc1754270923.html https://wenku.baidu.com/view/1d665697f185 ...
- 【HDU-5246】超级赛亚ACMer(贪心)
之前用了个nlogn的算法超时了.仅仅能改成n的算法了 大题贪心思路就是 对每一个人的能力值从小到大进行排序,当前能力值为now,那么我们找到一个人的能力使得这个能力值 <= now.now + ...
- java代码中fastjson生成字符串和解析字符串的方法和javascript文件中字符串和json数组之间的转换方法
1.java代码中fastjson生成字符串和解析字符串的方法 List<TemplateFull> templateFulls = new ArrayList<TemplateFu ...
- linux嵌入式大神的博客文章---持续更新中
linux kernel子系统相关博客:http://www.wowotech.net/ 经典博文: http://blog.csdn.net/zqixiao_09 http://blog.china ...
- IOS设计模式浅析之桥接模式(Bridge)
引言 在项目开发中,我们会遇到这样的一种场景:某些类型由于自身的逻辑,往往具有两个或多个维度的变化,比如说大话设计模式书中所说的手机,它有两个变化的维度:一是手机的品牌,可能有三星.苹果等:二是手机上 ...
- 给linux操作系统安装中文环境
如果设置的默认环境是英文,需要安装中文环境.最简答的方法如下: sudo apt-get install language-pack-zh-hant sudo apt-get install lang ...