过滤器
1、为什么需用到过滤器?
项目开发中,经常会涉及到重复代码的实现!
注册 ---- Servlet 【1. 设置编码】 ---- JSP
修改 ---- Servlet 【1. 设置编码】 --- JSP
其他,
如判断用户是否登陆,只有登陆才能有操作权限!
涉及到重复判断: 获取session,取出session数据,判断是否为空,为空说明没有登陆,不能操作; 只有登陆后,才能操作!
如何解决:
1.抽取重复代码,封装
2.每个用到重复代码的地方,手动的调用!
过滤器,设计执行流程
1.用户访问服务器
2.过滤器: 对Servlet请求进行拦截
3.先进入过滤器, 过滤器处理
4.过滤器处理完后, 在放行, 此时,请求到达Servlet/JSP
5.Servlet处理
6.Servlet处理完后,再回到过滤器, 最后在由tomcat服务器相应用户;
(过滤器就像回家的门!)
2、HelloWorld案例
Java.servlet.*;
|-- interface Filter 及过滤器
开发步骤:
1.写一个普通java类,实现Filter接口
2.配置过滤器
过滤器相关Api
|-- interface Filter 过滤器核心接口
Void init(filterConfig); 初始化方法,在服务器启动时候执行
Void doFilter(request,response,filterChain); 过滤器拦截的业务处理方法
Void destroy(); 销毁过滤器实例时候调用
|-- interface FilterConfig 获取初始化参数信息
* 案例
* java
public class HelloFilter implements Filter{
// 创建实例
public HelloFilter(){
System.out.println("1. 创建过滤器实例");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2. 执行过滤器初始化方法");
// 获取过滤器在web.xml中配置的初始化参数
String encoding = filterConfig.getInitParameter("encoding");
System.out.println(encoding);
// 获取过滤器在web.xml中配置的初始化参数 的名称
Enumeration<String> enums = filterConfig.getInitParameterNames();
while (enums.hasMoreElements()){
// 获取所有参数名称:encoding、path
String name = enums.nextElement();
// 获取名称对应的值
String value = filterConfig.getInitParameter(name);
System.out.println(name + "\t" + value);
}
}
// 过滤器业务处理方法: 在请求到达servlet之前先进入此方法处理公用的业务逻辑操作
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("3. 执行过滤器业务处理方法");
// 放行 (去到Servlet)
// 如果有下一个过滤器,进入下一个过滤器,否则就执行访问servlet
chain.doFilter(request, response);
System.out.println("5. Servlet处理完成,又回到过滤器");
}
@Override
public void destroy() {
System.out.println("6. 销毁过滤器实例");
}
}
* web.xml
<!-- 过滤器配置 -->
<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.albin.a_filter_hello.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hello_filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
拦截指定的请求
<!-- 配置第二个过滤器 -->
<filter>
<filter-name>hello_filter2</filter-name>
<filter-class>cn.albin.a_filter_hello.HelloFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>hello_filter2</filter-name>
<!-- 1. 拦截所有
<url-pattern>/*</url-pattern>
-->
<!-- 2. 拦截指定的jsp
<url-pattern>/index.jsp</url-pattern>
<url-pattern>/list.jsp</url-pattern>
-->
<!-- 拦截所有的jsp
<url-pattern>*.jsp</url-pattern>
-->
<!-- 3. 根据servlet的内部名称拦截
<servlet-name>IndexServlet</servlet-name>
-->
<!-- 拦截指定的servlet
<url-pattern>/index</url-pattern>
-->
<!-- 4. 指定拦截指定的类型 -->
<url-pattern>/*</url-pattern>
<!-- 拦截直接访问的请求或者重定向的资源 -->
<dispatcher>REQUEST</dispatcher>
<!--<dispatcher>FORWARD</dispatcher>-->
</filter-mapping>
3、编码处理统一写到这里(servlet中不需要再处理编码)
几乎每一个Servlet都要涉及编码处理:处理请求数据中文问题!
【GET/POST】
每个servlet都要做这些操作,把公用的代码抽取-过滤器实现!
代码实现思路:
1.Login.jsp 登陆,输入“中文”
2.LoginServlet.java 直接处理登陆请求
3.EncodingFilter.java 过滤器处理请求数据编码:GET/POST
* 案例
java
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"); // POST提交有效 response.setContentType("text/html;charset=UTF-8"); /* * 出现GET中文乱码,是因为在request.getParameter方法内部没有进行提交方式判断并处理。 * String name = request.getParameter("userName"); * * 解决:对指定接口的某一个方法进行功能扩展,可以使用代理! * 对request对象(目标对象),创建代理对象! */ 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(); // 判断:对getParameter方法进行GET提交中文处理 if ("getParameter".equals(methodName)) { // 获取请求数据值【 <input type="text" name="userName">】 String value = request.getParameter(args[0].toString()); // 调用目标对象的方法 // 获取提交方式 String methodSubmit = request.getMethod(); // 直接调用目标对象的方法 // 判断如果是GET提交,需要对数据进行处理 (POST提交已经处理过了) if ("GET".equals(methodSubmit)) { if (value != null && !"".equals(value.trim())){ // 处理GET中文 value = new String(value.getBytes("ISO8859-1"),"UTF-8"); } } return value; } else { // 执行request对象的其他方法 returnValue = method.invoke(request, args); } return returnValue; } }); // 二、放行 (执行下一个过滤器或者servlet) chain.doFilter(proxy, response); // 传入代理对象 } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } }
web.xml
<!--1. 编码处理过滤器配置 --> <filter> <filter-name>encoding</filter-name> <filter-class>cn.albin.a_loginFilter.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>