过滤器:
* 概述:
* Filter的作用:
起到过滤的作用.
* Filter执行的时机:
* 在执行对应的Servlet之前.(过滤Request对象中的内容)* 在执行对应的Servlet之后.(过滤Response对象中的内容)
* 发展:
* Filter最早在Servlet 2.3版本提供.* Filter在Servlet 2.5版本完善.
运行原理:
* 如何使用Filter:
* Filter是JavaEE提供的一个接口.(自定义Filter需要实现该接口,并重写所有方法)* Filter提供的方法:
* init()
* doFilter()
* destroy()
* 实现步骤:
* 创建Java类,实现Filter接口,并且重写所有方法.* 在web.xml文件中进行配置.
<filter>
<filter-name>MyFilter1</filter-name>
<filter-class>app.java.filter.MyFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
MyFIlter1.java:
package app.java.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 自定义过滤器:
* * 实现Filter接口,并且重写该接口提供所有的方法.
* @author JYL
*
*/
public class MyFilter1 implements Filter {
/**
* Filter的构造函数:
* * 执行时机:在Tomcat服务器启动时.
* * 执行次数:在Filter的生命周期中只执行一次.
* * Filter与Servlet一样,都是单例多线程的.(线程安全问题)
*/
public MyFilter1() {
System.out.println("这是MyFilter1的构造函数...");
}
/**
* init(FilterConfig config)方法:
* * 作用:用于过滤器的初始化.
* * 执行时机:在Tomcat服务器启动时.
* * 执行次数:在Filter的生命周期中只执行一次.
*/
public void init(FilterConfig config) throws ServletException {
System.out.println("这是MyFilter1的init()方法...");
}
/**
* doFilter(ServletRequest request, ServletResponse response,FilterChain chain)方法:
* * 作用:用于过滤器的过滤.
* * 执行时机:客户端访问当前Filter拦截的资源路径时.
* * 执行次数:在Filter的生命周期中,每次拦截,每次执行.
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("这是MyFilter1的doFilter()方法...");
//过滤器的放行
chain.doFilter(request, response);
}
/**
* destroy()方法:
* * 作用:用于过滤器的销毁.
* * 执行时机:在Tomcat服务器关闭时.
* * 执行次数:在Filter的生命周期中只执行一次.
*/
public void destroy() {
System.out.println("这是MyFilter1的destroy()方法...");
}
}
web.xml:
<filter>
<filter-name>MyFilter1</filter-name>
<filter-class>app.java.filter.MyFilter1</filter-class>
</filter>
<filter>
<filter-name>MyFilter2</filter-name>
<filter-class>app.java.filter.MyFilter2</filter-class>
<init-param>
<param-name>mingjiao</param-name>
<param-value>zhangwuji</param-value>
</init-param>
</filter>
* Filter的生命周期:
* 出生:Hello World* init()方法
* 活着:Love World
* doFilter()方法
* 死去:GoodBye World
* destroy()方法
* 过滤器链:
* 问题:* 如何定义过滤器被执行的先后顺序?
* Filter的doFilter()方法具有一个参数FilterChain,通过调用chain.doFilter()方法可以放行.
* 在过滤器链中,执行chain.doFilter()方法,是否还是放行的作用?
* 如果是,应该被放行到哪里去了?(单个Filter时,直接被放行到对应的Web资源[Servlet、JSP])
* 解决以上问题:
* chain.doFilter()方法依旧是放行方法.
* 如果执行的不是过滤器链中最后一个过滤器的话,执行chain.doFilter()方法,会被放行到下一个过滤器里.
* 如果执行的是过滤器链中最后一个过滤器的话,chain.doFilter()方法,才会被放行到对应Web资源中.
* 过滤器链中的过滤器执行的先后顺序由web.xml文件中的<filter-mapping>标签定义的先后顺序决定.
再建一个filter:
package app.java.filter;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilter2 implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("这是MyFilter2的doFilter()方法...");
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
System.out.println("这是MyFilter2的init()方法...");
Enumeration enums = config.getInitParameterNames();
while (enums.hasMoreElements()) {
String name = (String) enums.nextElement();
String value = config.getInitParameter(name);
System.out.println(name+" : "+value);
}
}
}
<filter>
<filter-name>MyFilter1</filter-name>
<filter-class>app.java.filter.MyFilter1</filter-class>
</filter>
<filter>
<filter-name>MyFilter2</filter-name>
<filter-class>app.java.filter.MyFilter2</filter-class>
<init-param>
<param-name>mingjiao</param-name>
<param-value>zhangwuji</param-value>
</init-param>
</filter>
* 实际开发的意义:
* 单个Filter完成单个任务.
* 读取web.xml文件中的初始化参数.
* 在web.xml文件中是如何配置的:
<filter>
<filter-name>MyFilter2</filter-name>
<filter-class>app.java.filter.MyFilter2</filter-class>
<init-param>
<param-name>mingjiao</param-name>
<param-value>zhangwuji</param-value>
</init-param>
</filter>
* FilterConfig的用法与ServletConfig一致.
* 在web.xml文件中配置全局初始化参数<context-param>,通过ServletContext对象读取.
* 完全匹配:/xxxx
* 目录匹配:/aaaa/
* 扩展名匹配:*.do
* 优先级别:完全匹配 -> 目录匹配 -> 扩展名匹配
* 如果当前Filter拦截对应Servlet的话:
* 还可以使用<servlet-name>标签 就是把<filter-mapping>里的<url-pattern>标签改为<servlet-name>
* Filter拦截Servlet默认情况是拦截直接请求.
* 在web.xml文件中配置<filter-mapping>标签中具有<dispatcher>
* <dispatcher>标签在同一个Filter的配置中,可以配置多个.
* <dispatcher>标签的值:
* REQUEST:是默认值,表示一次请求.
* FORWARD:表示请求转发到.
* INCLUDE:表示包含(例如JSP包含另一个JSP等)
* ERROR:表示JSP的<%@ page errorPage=""%>
在MyFilter2.java中对MyServlet2进行拦截:
xml:
<filter-mapping>
<filter-name>MyFilter2</filter-name>
<servlet-name>MyServlet2</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>MyFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
MyServlet1.java:
package app.java.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/servlet2").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
MyServlet2.java:
package app.java.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("这是Servlet2.........");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
此时访问Servlet2可以直接访问2,也可以通过1的请求转发访问:
直接访问servlet2:
访问servlet1:
没有执行拦截的任务
* Filter的生命周期:
* 出生:Hello World* init()方法
* 活着:Love World
* doFilter()方法
* 死去:GoodBye World
* destroy()方法
* 扩展:
* 面向对象:这个人就是对象,年龄、性别等是属性,
出生、上学、结婚等方法.
* 类与对象的区别:
* 类:比作女生.
* 对象:就是范冰冰.
* 实现、继承、多态、封装等概念.
* 面向过程:这个人从出生,长大、上学、工作、...、去世.
* Filter的案例:
* 全站乱码案例:* 利用Servlet的doGet()和doPost()方法中,可以解决中文乱码:
* doGet()
String value = request.getParameter("");
value = new String(value.getBytes("ISO8859-1"),"utf-8");
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
* 实际开发时,Web应用程序的逻辑比较复杂(多个Servlet).
* 上述的解决方案,仅能解决当前Servlet的中文乱码问题.
* 如果使用上述方案,解决中文乱码问题:代码重复性太多.
使用过滤器来解决:
EncodingFilter.java:
package app.java.filter.demo1;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 当前Filter用于解决全站中文乱码问题.
* @author JYL
*/
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//1 进行Request与Response对象的类型强转
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
//2 解决中文乱码问题:1)请求的中文乱码(GET\POST);2)响应的中文乱码.
request.setCharacterEncoding("utf-8");//针对post方式
response.setContentType("text/html;charset=utf-8");
//3 放行
chain.doFilter(request, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
}
TestServlet.java:(Servlet)
package app.java.filter.demo1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+" : "+password);
response.getWriter().println("中文解决了,真好!!!!");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+" : "+password);
response.getWriter().println("中文解决了,真好!!!!");
}
}
index.jsp:
<body>
<c:if test="${empty user }">
<h1><a href="login.jsp">去登录</a></h1>
</c:if>
<c:if test="${not empty user }">
<h1>欢迎你,${user }!</h1>
</c:if>
<form action="test" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
<a href="test?username=张无忌&password=123">GET方式发送的请求</a>
</body>
xml:
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>app.java.filter.demo1.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
针对get方式:
偷梁换柱:
MyRequest:
package app.java.filter.demo1;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* 自定义的Request对象
* @author JYL
*/
public class MyRequest extends HttpServletRequestWrapper {
public MyRequest(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {//此处的getParameter有可能是get也有可能是post
//而这个方法是针对Get方式的,所以要进行判断
String value = super.getParameter(name);
if(super.getMethod().equalsIgnoreCase("GET")){
try {
value = new String(value.getBytes("ISO-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return value;
}
}
EncodingFilter.java:
package app.java.filter.demo1;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 当前Filter用于解决全站中文乱码问题.
* @author JYL
*/
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//1 进行Request与Response对象的类型强转
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
//2 解决中文乱码问题:1)请求的中文乱码(GET\POST);2)响应的中文乱码.
request.setCharacterEncoding("utf-8");//针对post方式
response.setContentType("text/html;charset=utf-8");
//3 创建自定义的Request对象
MyRequest myRequest = new MyRequest(request);
//3 放行
chain.doFilter(myRequest, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
}
TestServlet.java:
package app.java.filter.demo1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+" : "+password);
response.getWriter().println("中文解决了,真好!!!!");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+" : "+password);
response.getWriter().println("中文解决了,真好!!!!");
}
}
*
登录页面:
<body>
<c:if test="${empty user }">
<h1><a href="login.jsp">去登录</a></h1>
</c:if>
<c:if test="${not empty user }">
<h1>欢迎你,${user }!</h1>
</c:if>
<form action="test" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
<a href="test?username=张无忌&password=123">GET方式发送的请求</a>
</body>
处理登录的servlet:
package app.java.filter.demo2;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 当前Servlet用于处理用户登录逻辑.
*
*
*/
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if(username==null||password==null||"".equals(username)||"".equals(password)){
// 说明用户没有输入用户名和密码
request.setAttribute("error_msg", "请输入你的用户名和密码!");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}else if(username.equals("admin")&&password.equals("admin")){
// 获取自动登陆的值,进行判断
String autologin = request.getParameter("autologin");
if("on".equals(autologin)){
Cookie cookie = new Cookie("user",username+"#"+password);
cookie.setMaxAge(60*60*24*7);
cookie.setPath("/");
response.addCookie(cookie);
}
request.getSession().setAttribute("user", username);
response.sendRedirect("/day0106/index.jsp");
}
}
}
过滤器:
package app.java.filter.demo2;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/**
* 当前Filter用于完成用户自动登录功能.
* @author JYL
*/
public class AutoLoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
Cookie[] cookies = request.getCookies();
if(cookies != null){
for (Cookie cookie : cookies) {
if(cookie != null){
String name = cookie.getName();
if("user".equals(name)){
// 曾经登录过
String value = cookie.getValue();
String username = value.split("#")[0];
String password = value.split("#")[1];
request.getSession().setAttribute("user", username);
chain.doFilter(request, resp);
}else{
// 没有登陆过
chain.doFilter(request, resp);
}
}
}
}else{
// 没有登陆过
chain.doFilter(request, resp);
}
}
public void init(FilterConfig arg0) throws ServletException {
}
}
xml:
<filter>
<filter-name>AutoLoginFilter</filter-name>
<filter-class>app.java.filter.demo2.AutoLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AutoLoginFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
* Filter的生命周期:
* 出生:Hello World* init()方法
* 活着:Love World
* doFilter()方法
* 死去:GoodBye World
* destroy()方法