为什么需用到过滤器?
项目开发中,经常会涉及到重复代码的实现!
注册 ----> Servlet 【1. 设置编码】 ----> JSP
修改 ---->Servlet 【1. 设置编码】 ----> JSP
其他,
如判断用户是否登陆,只有登陆才能有操作权限!
涉及到重复判断: 获取session,取出session数据,判断是否为空,为空说明没有登陆,不能操作; 只有登陆后,才能操作!
如何解决:
1. 抽取重复代码,封装
2. 每个用到重复代码的地方,手动的调用!
过滤器,设计执行流程:
1. 用户访问服务器
2. 过滤器: 对Servlet请求进行拦截
3. 先进入过滤器, 过滤器处理
4. 过滤器处理完后, 在放行, 此时,请求到达Servlet/JSP
5. Servlet处理
6. Servlet处理完后,再回到过滤器, 最后在由tomcat服务器相应用户;
(过滤器就像回家的门!)
过滤器执行流程

过滤器相关Api
|-- interface Filter 过滤器核心接口
Void init(filterConfig); 初始化方法,在服务器启动时候执行
Void doFilter(request,response,filterChain); 过滤器拦截的业务处理方法
Void destroy(); 销毁过滤器实例时候调用
|-- interface FilterConfig 获取初始化参数信息
String getInitParameter(java.lang.String name)
Enumeration getInitParameterNames()
|-- interface FilterChain 过滤器链参数;一个个过滤器形成一个执行链;
void doFilter(ServletRequest request, ServletResponse response) ; 执行下一个过滤器或放行
/**
* 过滤器,测试
*/
public class HelloFilter implements Filter{
public HelloFilter(){
System.out.println("1. 创建过滤器实例");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2. 执行过滤器初始化方法");
String encoding = filterConfig.getInitParameter("encoding");
System.out.println(encoding);
Enumeration<String> enums = filterConfig.getInitParameterNames();
while (enums.hasMoreElements()){
String name = enums.nextElement();
String value = filterConfig.getInitParameter(name);
System.out.println(name + "\t" + value);
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("3. 执行过滤器业务处理方法");
chain.doFilter(request, response);
System.out.println("5. Servlet处理完成,又回到过滤器");
}
@Override
public void destroy() {
System.out.println("6. 销毁过滤器实例");
}
}
<filter>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>path</param-name>
<param-value>c:/...</param-value>
</init-param>
<filter-name>hello_filter</filter-name>
<filter-class>cn.itcast.a_filter_hello.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hello_filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
案例
编码统一处理
几乎每一个Servlet都要涉及编码处理:处理请求数据中文问题!
【GET/POST】
每个servlet都要做这些操作,把公用的代码抽取-过滤器实现!
代码实现思路:
1. Login.jsp 登陆,输入“中文”
2. LoginServlet.java 直接处理登陆请求
3. EncodingFilter.java 过滤器处理请求数据编码:GET/POST
过滤器:
/**
* 编码处理统一写到这里(servlet中不需要再处理编码)
* @author Jie.Yuan
*
*/
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
HttpServletRequest proxy = (HttpServletRequest) Proxy.newProxyInstance(
request.getClass().getClassLoader(),
new Class[]{HttpServletRequest.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object returnValue = null;
String methodName = method.getName();
if ("getParameter".equals(methodName)) {
String value = request.getParameter(args[0].toString());
String methodSubmit = request.getMethod();
if ("GET".equals(methodSubmit)) {
if (value != null && !"".equals(value.trim())){
value = new String(value.getBytes("ISO8859-1"),"UTF-8");
}
}
return value;
}
else {
returnValue = method.invoke(request, args);
}
return returnValue;
}
});
chain.doFilter(proxy, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
过滤器配置:
<filter>
<filter-name>encoding</filter-name>
<filter-class>cn.itcast.a_loginFilter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Servlet:
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("userName");
System.out.println("用户:" + name);
}
无效数据过滤
模拟:论坛过滤敏感词汇!
实现思路:
1. Dis.jsp 讨论区页面
2. DisServlet.java 处理提交
---》 获取请求参数
---》 保存到request域
-----》 跳转dis.jsp 【从request取数据显示(处理后)】
3. DataFilter.java 过滤器
----》编码
---》 无效数据处理
即: 在上一个案例基础上,再添加无效数据过滤的相关代码!
JSP引入ckeditor组件:客户端组件,便于用户输入内容!
JSP
<script src="${pageContext.request.contextPath }/ckeditor/ckeditor.js"></script>
<link rel="stylesheet" href="${pageContext.request.contextPath }/ckeditor/samples/sample.css">
<body>
${requestScope.content }
<form name="frmDis" action="${pageContext.request.contextPath }/dis" method="post">
发表评论: <textarea class="ckeditor" rows="6" cols="30" name="content"></textarea>
<br/>
<input type="submit" value="评论" >
</form>
</body>
Filter:
在上个过滤器案例的基础上,增加如下代码:
for (String data : dirtyData) {
if (value.contains(data)){
value = value.replace(data, "*****");
}
}