WEB23 Filter过滤器
今日任务:
1 自动登录
2 统一GET和POST中文乱码的问题
学习目标:
了解过滤器的执行原理
会编写过滤器
知道如何在过滤器中对request进行增强—装饰者模式
案例1----自动登录
需求:
不需要输入用户名和密码,即可登录成功
技术分析: Filter
什么是filter?
filter(过滤器): 本质上是一个类,帮助我们处理请浏览器求资源时的一种过滤,
符合条件让通过继续访问资源,如果不符合条件的就不让访问了
filter的作用?
作用:拦截浏览器的请求的
如何使用filter?
1 入门案例:
1.编写一个类实现Filter接口
(着重是doFilter)
2.在web.xml下编写配置文件
(设定要拦截的资源)
例如:
<filter>
<filter-name>HelloFilter</filter-name>
<filter-class>cn.itcast.a_hello.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HelloFilter</filter-name>
<url-pattern>/demo1</url-pattern>
</filter-mapping>
注意:如果有多个拦截器都匹配要拦截的资源
多个拦截器都执行,顺序是<url-pattern>在web.xml下的顺序
API:
常用方法:
init(FilterConfig config):初始化
doFilter(ServletRequest req,ServletReponse resp,FilterChain chain):过滤方法
destroy():销毁
fileter生命周期:(了解)
在服务器启动的时候,服务器创建filter对象,且调用init方法实现初始化
当请求来的时候,若能匹配上url-pattern,则 服务器调用doFilter 过滤请求
当服务器正常关闭的时候,服务器调用destroy实现销毁操作
配置信息:
url-pattern的写法 (和servlet一样)
完全匹配 以/开头 /demo1 /a/b/c 匹配单个资源
目录匹配 以/开头以结尾 / /a/* 匹配多个资源
后缀名匹配 *.jsp *.do *.action
注意:如果匹配上,多个都执行,执行顺序由在web.xml中url-pattern的顺序决定,谁在上面谁先执行
可以写多个:
serlvet-name:过滤具体的那个serlvet
serlvet-name:过滤具体的那个serlvet
serlvet-name:过滤具体的那个serlvet
注意: 先匹配url-pattern,然后匹配serlvet-name
filter-mapping的标签
dispatcher:过滤哪种方式过来的请求
REQUEST:默认的 只过滤从浏览器端发送过来的请求
FORWARD:只过滤转发过来的请求
INCLUDE:只过滤包含过来的请求
ERROR:只过滤错误过来的请求
统一错误页面的配置 404 500
在web.xml中可以配置error-page标签
例如:
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
///
案例1-自动登录的步骤分析:
1.页面
2.在登录成功之后,需要将user放入session中.保证整个会话只需要登录一次
3.修改login.htm为login.jsp 修改表单提交路径
4.修改login.jsp 若勾选了自动登录,需要将勾选的状态发送到servlet上
需要给 自动登录设置name和value属性
自动登录
5.修改登录成功之后的逻辑
当登录成功之后,需要将用户名和密码 放入cookie中,在浏览器端保存
6.下次访问任意资源实现自动登录功能
功能:自动登录
路径:/*
通过过滤器做
7.过滤器里的逻辑
0.从session中获取user
若user为空,继续执行
若user不为空,代表登录成功,不需要自动登录,放行即可,不用执行以下逻辑
1.获取cookie(指定名称的cookie)
2.判断cookie是否为空
若为空.直接放行 不登录
若不为空,获取cookie中存放的用户名和密码
通过用户名和密码 调用service完成登录操作,返回值为user对象
继续判断user是否为空
若user为空 ,不登录 放行
若user不为空,完成登录 将user放入session中
最后的问题:
访问每一个资源的时候,都执行了filter,去数据库中查询一次.这样不好,
只需要登录一次,判断session中user是否为空,若不为空,不执行自动登录逻辑
/
案例2-统一编码:
需求:
在servlet中以前操作,第一步设置编码.我们的目标,在一个地方设置,在servlet中获取参数的时候已经不存在中文乱码问题了
步骤分析: 对reuqest的getParameter进行加强
编写一个过滤器,
路径:/*
操作:
对reuqest的getParameter进行加强
加强的方式:
1.继承
2.装饰者模式(静态代理)
3.动态代理(明天讲)
/
装饰者模式书写步骤:
1.要求装饰者和被装饰者要实现同一个接口或者继承同一个类
2.在装饰者中要有被装饰者的应用
3.对需要加强的方法进行增强
4.对不需要加强的方法调用原来的方法
//
//
/
/
总结:
Filter:过滤器
作用:
过滤请求和响应
filter编写步骤:
1.编写一个类
实现Filter(javax.servlet.Filter)
重写三个方法(主要的是 doFilter)
2.编写配置文件
注册filter
绑定路径
url-pattern的写法(和servlet一样)
执行顺序由web.xml中 filter-mapping的顺序决定
filter-mapping的两个子标签(理解)
servlet-name:指定过滤那个servlet
dispatcher:过滤那种方式过来的请求
值:
REQUEST:默认的 只过滤从浏览器发送过来的请求
FORWARD:只过滤转发过来的请求
设置统一错误页面
在web.xml中配置 error-page
///
自动登录代码:
package cn.itcast.servlet;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.websocket.Session;
import cn.itcast.domain.User;
import cn.itcast.service.serviceDemo;
/**
-
Servlet implementation class Servletlogin
*/
public class Servletlogin extends HttpServlet {
private static final long serialVersionUID = 1L;/**
*登录验证
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
request.setCharacterEncoding(“utf-8”);
response.setContentType(“text/html;charset=utf-8”);
String username = request.getParameter(“username”);
String password = request.getParameter(“password”);HttpSession session = request.getSession(); serviceDemo sd=new serviceDemo(); System.out.println(username+":"+password); User user = sd.login(username,password); if(user!=null){ session.setAttribute("user", user); System.out.println("2222="+session.getId()); String ck = request.getParameter("ck"); System.out.println("ck"+ck); if("ok".equals(ck)){ //把用户名和密码保存到浏览器cookie中 Cookie cookie1 = new Cookie("username",user.getUsername()); Cookie cookie2 = new Cookie("password",user.getPassword()); //设置cookie保存的时长 cookie1.setMaxAge(1000*60*60*24); cookie2.setMaxAge(1000*60*60*24); //保存cookie response.addCookie(cookie1); response.addCookie(cookie2); } response.sendRedirect(request.getContextPath()+"/index.jsp"); }else{ request.setAttribute("user", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }
}
/**
- @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
- @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
}
编码案例代码:
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 cn.itcast.utils.GZrequest;
public class codeFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)request;
String method = req.getMethod();
if(“post”.equalsIgnoreCase(method)){
req.setCharacterEncoding(“utf-8”);
chain.doFilter(request, response);
}else{
GZrequest gZrequest=new GZrequest(req);
chain.doFilter(gZrequest, response);
}
}
@Override
public void destroy() {
}
}