美文网首页程序员
Filter应用(二)

Filter应用(二)

作者: 大炮对着虫子 | 来源:发表于2017-09-17 14:38 被阅读28次

如果不能简单的把事情说清楚,说明你还没有完全明白。

Filter我们一般用于做字符编码,登录拦截,跨域请求压缩处理

登录拦截

如果用户知道了页面的url,通过直接在浏览器上输入url,跳过了登录。我们需要对其非法操作进行拦截,如果不用过滤器的话,需要在每个页面在上判断,session里面的用户是否为Null,有了过滤器Filter我们可以为其加上个登录拦截的过滤器。

  <form action="" id="Myform">
        <input name="username" placeholder="用户名" required="" type="text" value="<%=uname%>"
        />
        <hr class="hr15">
        <input name="password" placeholder="密码" required="" type="password" value="<%=password%>"
        <input value="登录" style="width:100%;" type="submit" id="btn_login">
        />

当我们在登录的时候,会在serlvlet上为用户设置在session保存信息

session.setAttribute("user_name", username);

下面开始编辑我们的登录拦截器filter

首先,配置xml文件,拦截所有的url :/*

 <filter>
  <filter-name>LoginFilter</filter-name>
  <filter-class>filter.LoginFilter</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>LoginFilter</filter-name>
  <url-pattern>/*</url-pattern>
  </filter-mapping>

这里设置拦截的地址是/* 则文件访问的.js .css .jsp .do 等都会被拦截,即访问一个jsp界面,可能会被拦截很多次。所以应该做如下修改:只拦截.jsp 和.do

  <filter>
  <filter-name>LoginFilter</filter-name>
  <filter-class>filter.LoginFilter</filter-class>
  <init-param>
  <param-name>login</param-name>
  <param-value>login.jsp</param-value>
  </init-param>
  
   <init-param>
  <param-name>LoginServlet</param-name>
  <param-value>LoginServlet</param-value>
  </init-param>
  </filter>
  <filter-mapping>
  <filter-name>LoginFilter</filter-name>
  <url-pattern>*.jsp</url-pattern>
  </filter-mapping>
  
  <filter-mapping>
  <filter-name>LoginFilter</filter-name>
  <url-pattern>*.do</url-pattern>
  </filter-mapping>

下面是同步拦截,Filter的写法:

public class LoginFilter implements Filter {

    //不拦截的登录界面jsp  与不拦截的执行登录的servlet
    String login="";
    String servlet="";
    /**
     * Default constructor. 
     */
    public LoginFilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        // place your code here

        // pass the request along the filter chain

        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse resp = (HttpServletResponse)response;
        String contextUrl = req.getRequestURI();
        if(contextUrl.indexOf(login)>-1||contextUrl.indexOf(servlet)>-1)
        {
            
            chain.doFilter(request, response);
            return;
        }
        HttpSession session = req.getSession();
        if(session.getAttribute("user_name")==null){//说明没有登录,或者超时
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter out = resp.getWriter();
            out.println("<script language='javascript' type='text/javascript'>");
            out.println("alert('登录信息失效!请你重新登录!');window.parent.location.href='" + req.getContextPath() + "/login.jsp'");
            out.println("</script>");
            return; 
        }
        chain.doFilter(request, response);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
        
        login=fConfig.getInitParameter("login");
        servlet=fConfig.getInitParameter("LoginServlet");
        System.out.println(login+servlet);
    }
}

以上,当我们通过同步去请求.jsp和.do都会拦截。但如果我们采用的是ajax,则虽然有拦截到进去,但是并没有什么用。

下面介绍下ajax拦截:

if(session.getAttribute("user_name")==null){//说明没有登录,或者超时
            //异步
            if (req.getHeader("x-requested-with") != null&& req.getHeader("x-requested-with") .equalsIgnoreCase("XMLHttpRequest")) {
                resp.addHeader("sessionstatus", "timeOut");   //这个头是随意加的,键值对。
                resp.addHeader("loginPath", "login.jsp"); 
                return ;
            }
            else   //同步
            {
            
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter out = resp.getWriter();
            out.println("<script language='javascript' type='text/javascript'>");
            out.println("alert('登录信息失效!请你重新登录!');window.parent.location.href='" + req.getContextPath() + "/login.jsp'");
            out.println("</script>");
            return; 
            }
        }

之后,新建个.js文件,在每个需要拦截的.jsp加入.js

$(document).ajaxComplete(function(event, xhr, settings) { 
    if(xhr.getResponseHeader("sessionstatus")=="timeOut"){ 
        if(xhr.getResponseHeader("loginPath")){ 
            alert("由于你长时间没有操作,导致Session失效!请你重新登录!"); 
                window.parent.location.href="/SaleOnline/"+xhr.getResponseHeader("loginPath"); 
            }else{  
                alert("由于你长时间没有操作,导致Session失效!请你重新登录!"); 
                }  
        }  
    }); 

于是,我们的拦截 完美成功。

跨域请求

什么是跨域
当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.google.com),那么我们就可以认为它们是相同的域(协议,域名,端口都必须相同)。
跨域就指着协议,域名,端口不一致,出于安全考虑,跨域的资源之间是无法交互的(例如一般情况跨域的JavaScript无法交互,当然有很多解决跨域的方案)

作为java开发,同样需要解决跨域的问题。
思路:设置个拦截器,对需要支持跨域的请求进行拦截,然后在Filter里增加跨域支持。

Filter代码:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletResponse  httpServletResponse = (HttpServletResponse) response;
            HttpServletRequest  httpServletRequest = (HttpServletRequest) request;
            httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");  //实际开发需要修改为指定的IP地址
            httpServletResponse.setHeader("Access-Control-Allow-Headers", "accept,content-type"); 
            httpServletResponse.setHeader("Access-Control-Allow-Methods", "OPTIONS,GET,POST,DELETE,PUT"); 
            chain.doFilter(httpServletRequest, httpServletResponse);
            //chain.doFilter(request, response);
        }

压缩处理

压缩处理涉及到文件IO处理,渣渣程序猿对这个文件处理一直都是绕过去的,这里备份下代码留着日后 好 翻笔记。 难受

public class GzipFilter implements Filter{

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        
         final HttpServletRequest request = (HttpServletRequest) arg0;
         final HttpServletResponse response = (HttpServletResponse) arg1;
         final ByteArrayOutputStream bout = new ByteArrayOutputStream();
         final PrintWriter pw = new PrintWriter(new OutputStreamWriter(bout,"UTF-8"));
         chain.doFilter(request, getHttpServletResponseProxy(response, bout, pw));
         pw.close();
        
         //拿到目标资源的输出
          byte result[] = bout.toByteArray();
          System.out.println("原始大小:" + result.length);
          ByteArrayOutputStream bout2 = new ByteArrayOutputStream();
          GZIPOutputStream gout = new GZIPOutputStream(bout2);
          gout.write(result);
          gout.close();
        //拿到目标资源输出的压缩数据
          byte gzip[] = bout2.toByteArray();
          System.out.println("压缩大小:" + gzip.length);
          response.setHeader("content-encoding", "gzip");
          response.setContentLength(gzip.length);
          response.getOutputStream().write(gzip);
    }
    
     private ServletResponse getHttpServletResponseProxy(
                 final HttpServletResponse response,
                 final ByteArrayOutputStream bout, 
                 final PrintWriter pw) {      
                  return (ServletResponse) Proxy.newProxyInstance(GzipFilter.class.getClassLoader(), 
                           response.getClass().getInterfaces(), 
                        new InvocationHandler(){
                           @Override
                           public Object invoke(Object proxy, Method method, Object[] args)
                                       throws Throwable {
                          if(method.getName().equals("getWriter")){
                               return pw; 
                              }else if(method.getName().equals("getOutputStream")){
                                  return new MyServletOutputStream(bout);
                             }else{
                                 return method.invoke(response, args);
                           }
                             }
                        });
           }
        
        
      
           class MyServletOutputStream extends ServletOutputStream{
                
              private ByteArrayOutputStream  bout = null;
              public MyServletOutputStream(ByteArrayOutputStream  bout){
                 this.bout = bout;
               }
                @Override
                public void write(int b) throws IOException {
                       bout.write(b);
                   }
                @Override
                public boolean isReady() {
                    // TODO Auto-generated method stub
                    return false;
                }
                @Override
                public void setWriteListener(WriteListener arg0) {
                    // TODO Auto-generated method stub
                    
                }
               
               }
        
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
        
    }

}

web.xml


相关文章

网友评论

    本文标题:Filter应用(二)

    本文链接:https://www.haomeiwen.com/subject/htwpsxtx.html