Part01:Filter过滤器
1、Filter概述:
- Filter是在Servlet2.3后增加的新功能,运行在服务器端的程序,在与之相关的Servlet或者JSP页面之前运行
- Filter作用:过滤请求和响应
- Filter常用场景:自动登录、统一编码、过滤一些特殊符号或者敏感词汇
2、自写一个Filter
- 编写一个类继承Filter并实现它的方法
import javax.servlet.*;
import java.io.IOException;
public class Demo01Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
}
}
- 在web.xml文件中映射filter,绑定路径
<!--映射filter-->
<filter>
<filter-name>Demo01Filter</filter-name>
<filter-class>Demo01.Demo01Filter</filter-class>
</filter>
<!--绑定Servlet路径-->
<filter-mapping>
<filter-name>Demo01Filter</filter-name>
<url-pattern>/demo01</url-pattern>
</filter-mapping>
3、Filter的方法:
- init(FilterConfig):初始化
- doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain):执行过滤
- destroy( ):销毁
3、Filter的生命周期:
- 和Servlet一样,Filter也是一个单实例多线程的
- 在项目启动的时候,服务器创建Filter的对象,调用init方法实现初始化操作;
- 每当请求来的时候。服务器获取一个线程,执行doFiter方法,实现过滤掉逻辑;
- 当服务器移除Filter的时候或者服务器正常关闭的时候,服务器调用destroy方法,实现销毁操作;
4、Filter的url-pattern的配置:
- 完全匹配:以“/”开始;如:/servlet
- 目录匹配:以”/“开始,以“ * ”结束;如:/a/、/
- 后缀名匹配:以“ * ”开始;如:.jsp、.action
5、FliterChain:过滤链
- 多个Filter组合在一起
- 执行顺序:多个Filter的执行顺序是由web.xml文件中filter-mapping的位置决定的,当一个filter收到多个请求的时候,调用filterChain.doFilter才可以访问下一个匹配的filter,若当前的filter是最后一个filter,调用filterChain.doFilter才能访问目标资源
6、filter-mapping中的子标签:
- servlet-name:可以指定具体过滤哪个Servlet
- dispatcher:指定过滤哪种方式过来的请求,可以出现多次
- REQUEST:默认值,只过滤从浏览器发送过来的请求,不过滤请求转发的
- FORWARD:只过滤转发过来的请求
- INCLUDE:只过滤包含过来的请求
- EROR:只过滤错误过来的请求
7、在web.xml中配置全局的统一错误页面,可以配置多个
<error-page>
<error-code>404</error-code>
<location>/index.jsp</location>
</error-page>
8、FilterConfig
- 获取Filter的名称
- 获取Filter的初始化参数
- 获取Filter的所有初始化名称
- 获取上下文对象ServletContext
@WebFilter(filterName = "Demo02Filter" ,urlPatterns = {"/demo01"})
public class Demo02Filter implements Filter {
FilterConfig fc = null;
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter(req, resp);
//获取Filter的名称
String filterName = fc.getFilterName();
System.out.println(filterName);
//获取初始化参数
String code = fc.getInitParameter("code");
System.out.println(code);
//获取所有初始化参数
Enumeration<String> initParameterNames = fc.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
String s = initParameterNames.nextElement();
System.out.println(s+":"+fc.getInitParameter(s));
}
//获取上下文对象
ServletContext servletContext = fc.getServletContext();
System.out.println(servletContext);
chain.doFilter(req,resp);
}
public void init(FilterConfig config) throws ServletException {
fc=config;
}
}
<!--在web.xml文件中的init-param标签中设置初始化参数-->
<!--映射filter-->
<filter>
<filter-name>Demo02Filter</filter-name>
<filter-class>Demo01.Demo02Filter</filter-class>
<init-param>
<param-name>code</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>db</param-name>
<param-value>mysql</param-value>
</init-param>
</filter>
<!--绑定Servlet路径-->
<filter-mapping>
<filter-name>Demo02Filter</filter-name>
<url-pattern>/demo01</url-pattern>
</filter-mapping>
Part02:自动登录案例
1、需求:
- 当用户第一次登录该网站的时候,如果勾选了“请记住我”复选框,那么在关闭浏览器后,下次再访问该网站时不需要登录就能访问,会自动登录。
2、源码
- Filter代码
@WebFilter(filterName = "UserFilter",urlPatterns = {"/*"})
public class UserFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//把ServletRequest强转为HttpServletRequest
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
//判断Session中是否有用户存在
String username1 = (String) request.getSession().getAttribute("username");
//若有,return不执行下面语句,避免重复查询数据库
if (username1 != null){
//放行
chain.doFilter(request,response);
return;
}
//获取所有的cookie,
Cookie[] cookies = request.getCookies();
Cookie coo = null;
//判断cookies是否为空
if(cookies != null){
//从cookies中查找与user匹配的cookie
for (Cookie cookie:cookies
) {
//如果相匹配
if("user".equals(cookie.getName())){
coo = cookie;
}
}
}
//判断是否是第一次登录
if(coo != null){
//若不是第一次登录,完成自动登录
//获取cookie中的用户名和密码
String value = coo.getValue();
//切割value字符串
String[] split = value.split("-");
String username = split[0];
String password = split[1];
//通过用户名和密码调用UserService的方法
User user = UserService.queryUser(username, password);
if(user != null){
//保证用户在线,把用户名放入Session中
request.getSession().setAttribute("username",user.getUsername());
//放行
chain.doFilter(request,response);
}
}else {
//若是第一次登录,放行
chain.doFilter(request,response);
}
}
public void init(FilterConfig config) throws ServletException {
}
}
- Servlet代码
@WebServlet(name = "UserServlet",urlPatterns = {"/yzm"})
public class UserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置response编码格式为utf-8,这样给前台写中文信息不会出现乱码
response.setHeader("content-type","text/html;charset=utf-8");
//获取前台输入的验证码
String code = request.getParameter("code");
//获取Session
HttpSession session = request.getSession();
//获取Session中存的随机生成的验证码
String code1 = (String) session.getAttribute("code");
//清空Session,保证点击登录时,验证码是最新的
session.removeAttribute("code");
//若前台输入的验证码为空或者都为空格
if(code==null || code.trim().length()==0){
//System.out.println("请输入验证码");
//把错误信息放入request域中
request.setAttribute("msg","请输入验证码");
//请求转发
request.getRequestDispatcher("/login.jsp").forward(request,response);
}else if(!(code.equalsIgnoreCase(code1))){
//判断输入的验证码是否和Session中存的一致,忽略大小写
//System.out.println("请输入正确的验证码");
request.setAttribute("msg","请输入正确的验证码");
//请求转发
request.getRequestDispatcher("/login.jsp").forward(request,response);
}else {
//获取请求的用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
//调用UserService的queryUser方法,把从前端HTML获取的用户名和密码传过去
User user = UserService.queryUser(username,password);
//判断从数据库中查询的数据,若查询到,登录成功,否则,登录失败
if(user == null){
//往前端HTML页面写信息
//response.getWriter( ).print("登录失败");
//System.out.println("登录失败");
request.setAttribute("msg","登录失败");
//请求转发
request.getRequestDispatcher("/login.jsp").forward(request,response);
}else {
//获取前台"请记住我"复选框的value值
String remember = request.getParameter("remember");
//判断是否勾选"请记住我"复选框
if("ok".equals(remember)){
//创建Cookie//把当前的用户名和密码放入Cookie中
Cookie cookie = new Cookie("user", username+"-"+password);
//设置Cookie的存活时间
cookie.setMaxAge(3600);
//把Cookie写回给浏览器
response.addCookie(cookie);
}
//request.getSession().setAttribute("username",user.getUsername());
//往前端HTML页面写信息
response.getWriter( ).print(username+",欢迎回来");
//System.out.println("登录成功");
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Part03:统一编码案例
1、需求:
- 在向服务器发送请求的时候,使用Filter过滤乱码
2、截图
3、源码
- Filter代码
@WebFilter(filterName = "EncodingFilter",urlPatterns = {"/*"})
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
chain.doFilter(new MyRequest(request), response);
}
public void init(FilterConfig config) throws ServletException {
}
}
class MyRequest extends HttpServletRequestWrapper {
public MyRequest(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
//获取提交方式
String method = super.getMethod();
//如果是get方式
if("get".equalsIgnoreCase(method)){
String username = super.getParameter("username");
try {
username = new String(username.getBytes("iso-8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return username;
//如果是post方式
}else if("post".equalsIgnoreCase(method)){
try {
super.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.getParameter(name);
}
return super.getParameter(name);
}
}
- Servlet代码
@WebServlet(name = "EncodingServlet",urlPatterns = {"/encoding"})
public class EncodingServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println(username);
}
}
- HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>以get方式提交</h3>
<form method="get" action="/encoding">
用户名:<input type="text" name="username"/>
<input type="submit" value="提交">
</form>
<hr/>
<form method="get" action="/encoding">
用户名:<input type="text" name="username"/>
<input type="submit" value="提交">
</form>
</body>
</html>