A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

filter
  • filter会比listener用的多得多
  • Spring想要接入到项目中需要用到Listener
  • Strut想要接入到项目中需要用到Filter

过滤器Filter(筛请求的)
  • 在真正访问资源之前有一层过滤
  • filter的简介
    • filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行,并且可以对目标资源访问前后进行逻辑处理

  • 快速入门
    • 编写一个过滤器的类实现Filter接口
    • 实现接口中尚未实现的方法(着重实现doFilter方法)
    • 在web.xml中进行配置(主要是配置要对哪些资源进行过滤)(配置方法跟servlet一样)

  • filter拦截之后需要放行才能访问到相应的资源地址,不然就执行完dofilter方法后停止

public class QuickFilter implements Filter {
    public void destroy() {
        System.out.println("QuickFilter1销毁");
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("QuickFilter1 doFilter调用");
        chain.doFilter(request, response);
    }
    public void init(FilterConfig fConfig) throws ServletException {
        System.out.println("QuickFilter1初始化");
    }
}<!--web.xml-->
<filter>
    <filter-name>QuickFilter</filter-name>
    <filter-class>com.itcast.filter.QuickFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>QuickFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>filter的访问流程
  • 客户端发送请求给服务器时,tomcat请求会先获取到请求信息,创建对应点request和response对象
  • 如果不添加过滤的话,tomcat引擎会带着request和response对象创建servlet,并把参数传递过去
  • 如果添加了filter,则会在servlet之间设置了过滤器
  • 在过滤器中需要调用chain.doFilter(request,response)后,请求才能被放行去找资源文件

filter作用
  • 对request和response进行配置值
  • 权限过滤

filter的API
  • filter生命周期及其与生命周期相关的方法
    • Filter接口有三个方法,并且这个三个都是与Filter的生命相关的方法
      • init(Filterconfig):代表filter对象初始化方法,filter对象创建时执行(==服务器一启动就创建filter对象==)
      • doFilter(ServletRequest,ServletResponse,FilterChain):代表filter执行过滤的核心方法,如果某资源在已经被配置到这个filter进行过滤的话,那么每次访问这个资源都会执行doFilter方法
        • FilterChain内部维护着各个filter的索引

      • destory():代表是filter销毁方法,当filter对象销毁时执行该方法

    • ==Filter对象的生命周期==
      • Filter何时创建:服务器启动时就创建该filter对象
      • Filter何时销毁:服务器关闭时filter销毁


  • Filter的AP详解
    • init(FilterConfig):其中参数config代表该Filter对象的配置信息的对象,内部封装是该filter的配置信息
    • destory()方法:filter对象销毁时执行
    • doFilter方法:doFilter(ServletRequest,ServletResponse,FilterChain)
      • 其中的参数:
      • ServletRequest/ServletResponse:每次在执行doFilter方法时web容器负责创建一个request和一个response对象作为doFilter的参数传递进来
      • 该request和response就是在访问目标资源的service方法时的request和response(其实不是同一个对象,但是里面的数据是一样的)
      • FilterChain:过滤器链对象,通过该对象的doFilter方法可以放行该请求



Filter的配置
  • url-pattern配置时
    • 完全匹配  /sertvle1
    • 目录匹配  /aaa/bbb/* ----用的最多
      • /user/*:访问前台的资源进入此过滤器
      • /admin/*:访问后台的资源时执行此过滤器

    • 扩展名匹配  *.abc  *.jsp(扩展名匹配只能以*开头)

  • 注意:url-pattern可以使用servlet-name替代,也可以混用(开发中url-pattern用的多)
  • dispatcher:访问的方式(了解,基本不用,面试也不问)
    • REQUEST:默认值,代表直接访问某个资源时执行filter
    • FORWARD:转发时才执行filter
    • INCLUDE: 包含资源时执行filter
    • ERROR:发生错误时 进行跳转是执行filter

  • 总结Filter的作用?
    • 自动登录
    • 公共代码的提取(解决乱码问题)
    • 屏蔽非法文字
    • 进行响应数据的压缩
    • 可以对request和response中的方法进行增强(装饰者模式/动态代理)
    • 进行权限控制


登陆的基本实现
  • 登陆成功会进行重定向跳转,在跳转之前,把用户对象存到session中(所有公司都这么干)
  • 在主页显示用户名,如果用户登陆了话

<!--用于提示用户名和密码错误-->
<div>
    <span style="color: red">${info }</span>   
</div>//web层
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
   
    String username = request.getParameter("username");
    String password = request.getParameter("password");
   
    UserService service = new UserService();
    User user = service.login(username,password);
   
    if (user == null) {
        //登陆失败
        request.setAttribute("info", "用户名或密码错误");
        request.setAttribute("username", username);//把用户名带回去页面
        request.getRequestDispatcher("/login.jsp").forward(request, response);
    }else {
        //登陆成功,把用户对象存放在session中
        request.getSession().setAttribute("user", user);
        response.sendRedirect(request.getContextPath() + "/index.jsp");
    }
}<!--index.jsp-->
<c:if test="${sessionScope.user == null }"> <!--${empty user }-->
    <li><a href="login.jsp">登录</a></li>
    <li><a href="register.jsp">注册</a></li>
</c:if>
<c:if test="${sessionScope.user != null }"> <!--${not empty user }-->
    <li>欢迎:${sessionScope.user.realname }</li>
    <li><a href="javascript:void(0)">退出</a></li>
</c:if>自动登录
  • 后期开发会接触到token来记住登陆
  • 把用户信息存放到cookie,访问的时候带过去自动帮你登陆.但是这样做的话,每个servlet都要加上自动登录的逻辑
  • 在filter中一般都会对request进行强转-->HttpServletRequest

//登陆成功后
String autoLogin = request.getParameter("autoLogin");//null or "autoLogin"
if(autoLogin != null && autoLogin.equals("autoLogin")) {
    Cookie cookie_username = new Cookie("username", username);
    Cookie cookie_pwd = new Cookie("password", password);
    cookie_username.setMaxAge(60 * 24 * 3);
    cookie_pwd.setMaxAge(60 * 24 * 3);
    response.addCookie(cookie_username);
    response.addCookie(cookie_pwd);
}//filter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    User user = (User) req.getSession().getAttribute("user");
    if(user != null) {
        chain.doFilter(request, response);
        return;
    }
    String usrename = null;
    String password = null;
    Cookie[] cookies = req.getCookies();
    if (cookies == null) {
        chain.doFilter(request, response);
        return;
    }
    for (Cookie co : cookies) {
        if ("username".equals(co.getName())) {
            usrename = co.getValue();
        }
        if ("password".equals(co.getName())) {
            password = co.getValue();
        }
    }
    if(usrename != null && password != null) {
        UserService service = new UserService();
        user = service.login(usrename, password);
    }
    if(user == null) {
        chain.doFilter(request, response);
        return;
    }else {
        req.getSession().setAttribute("user", user);
        chain.doFilter(req, response);
    }
}解决全局乱码问题
  • cookie不能写中文,怎么结局cookie写中文的问题
    • 先把中文编码,然后再解码
    • URLEncoder.encode(String s,String encodeType)
    • URLDeocder.decode(String s,String encodeType)

  • filter中对请求体的数据进行编码
    • request.setCharacterSet("UTF-8")
    • response.setContextType("text/html;charset=utf-8");

  • 对于get请求的参数:
    • 在filter中对request进行增强(装饰设计模式)
    • javaEE工程师提供了HttpServletRequestWrapper(专门用于装饰者提供的)
    • 重写getParameter(),getParameterMap()..


class EncoderRequest extends HttpServletRequestWrapper {
    private HttpServletRequest request = null;
    private boolean isGet = false;
   
    public EncoderRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
        isGet = "get".equals(request.getMethod().toLowerCase())? true:false;
    }
   
    @Override
    public String getParameter(String name) {
        String parameter = request.getParameter(name);
        if (isGet) {
            try {
                parameter = new String(parameter.getBytes("iso8859-1"),"utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return parameter;
    }
}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    req.setCharacterEncoding("utf-8");
    res.setContentType("utf-8");
    EncoderRequest enRequest = new EncoderRequest(req);
    chain.doFilter(enRequest, response);
}

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马