listener

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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值