1. 程式人生 > >JavaWeb的Filter過濾器應用

JavaWeb的Filter過濾器應用

過濾器應用案例

分ip統計網站的訪問次數

ip

count

192.168.1.111

2

192.168.1.112

59

統計工作需要在所有資源執行前,那麼就可以放到Filter中了。

我們這個過濾器不打算做攔截操作!因為我們只是用來做統計的。

用什麼東西來裝載統計的資料。Map<String,Integer>

Map什麼時候建立(使用ServletContextListener,在伺服器啟動時完成建立,並只在到ServletContext中),Map儲存到哪裡!(Map儲存到ServletContext中!!!)

Ø  Map需要在Filter中用來儲存資料

Ø  Map需要在頁面使用,列印Map中的資料

思路分析

因為一個網站可能有多個頁面,無論哪個頁面被訪問,都要統計訪問次數,所以使用過濾器最為方便。

因為需要分IP統計,所以可以在過濾器中建立一個Map,使用IP為key,訪問次數為value。當有使用者訪問時,獲取請求的IP,如果IP在Map中存在,說明以前訪問過,那麼在訪問次數上加1,即可;IP在Map中不存在,那麼設定次數為1。

把這個Map存放到ServletContext中!

程式碼描述

index.jsp

  <body>

<h1>分IP統計訪問次數</h1>

<table align="center"

width="50%" border="1">

    <tr>

       <th>IP地址</th>

       <th>次數</th>

    </tr>

<c:forEach items="${applicationScope.ipCountMap }" var="entry">

    <tr>

       <td>${entry.key }</td>

       <td>${entry.value }</td>

    </tr>

</c:forEach>

</table>

  </body>

IPFilter

public class IPFilter implements Filter {

    private ServletContext context;

    public void init(FilterConfig fConfig) throws ServletException {

       context = fConfig.getServletContext();

       Map<String, Integer> ipCountMap = Collections

              .synchronizedMap(new LinkedHashMap<String, Integer>());

       context.setAttribute("ipCountMap", ipCountMap);

    }

    @SuppressWarnings("unchecked")

    public void doFilter(ServletRequest request, ServletResponse response,

           FilterChain chain) throws IOException, ServletException {

       HttpServletRequest req = (HttpServletRequest) request;

       String ip = req.getRemoteAddr();

       Map<String, Integer> ipCountMap = (Map<String, Integer>) context

              .getAttribute("ipCountMap");

       Integer count = ipCountMap.get(ip);

       if (count == null) {

           count = 1;

       } else {

           count += 1;

       }

       ipCountMap.put(ip, count);

       context.setAttribute("ipCountMap", ipCountMap);

       chain.doFilter(request, response);

    }

    public void destroy() {}

}

  <filter>

    <display-name>IPFilter</display-name>

    <filter-name>IPFilter</filter-name>

    <filter-class>cn.cloud.filter.ip.IPFilter</filter-class>

  </filter>

  <filter-mapping>

    <filter-name>IPFilter</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

使用者許可權控制

RBAC à 基於角色的許可權控制

l  tb_user

l  tb_role

l  tb_userrole

l  tb_menu(增、刪、改、查)

l  tb_rolemenu

需求說明

我們給出三個頁面:index.jsp、user.jsp、admin.jsp。

l  index.jsp:誰都可以訪問,沒有限制;

l  user.jsp:只有登入使用者才能訪問;

l  admin.jsp:只有管理員才能訪問。

思路分析

設計User類:username、password、grade,其中grade表示使用者等級,1表示普通使用者,2表示管理員使用者。

當用戶登入成功後,把user儲存到session中。

建立LoginFilter,它有兩種過濾方式:

l  如果訪問的是user.jsp,檢視session中是否存在user;

l  如果訪問的是admin.jsp,檢視session中是否存在user,並且user的grade等於2。

程式碼描述

User.java

public class User {

    private String username;

    private String password;

    private int grade;

    //get…set方法

}

在UserService中建立一個Map,用來儲存所有使用者。Map中的key中使用者名稱,value為User物件。

UserService.java

public class UserService {

    private static Map<String,User> users = new HashMap<String,User>();

    static {

       users.put("zhangSan", new User("zhangSan", "123", 1));

       users.put("liSi", new User("liSi", "123", 2));

    }

    public User login(String username, String password) {

       User user = users.get(username);

       if(user == null) return null;

       return user.getPassword().equals(password) ? user : null;

    }

}

login.jsp

  <body>

  <h1>登入</h1>

    <p style="font-weight: 900; color: red">${msg }</p>

    <form action="<c:url value='/LoginServlet'/>" method="post">

    使用者名稱:<input type="text" name="username"/><br/>

    密 碼:<input type="password" name="password"/><br/>

    <input type="submit" value="登入"/>

    </form>

  </body>

index.jsp

  <body>

    <h1>主頁</h1>

    <h3>${user.username }</h3>

    <hr/>

    <a href="<c:url value='/login.jsp'/>">登入</a><br/>

    <a href="<c:url value='/user/user.jsp'/>">使用者頁面</a><br/>

    <a href="<c:url value='/admin/admin.jsp'/>">管理員頁面</a>

  </body>

/user/user.jsp

<body>

<h1>使用者頁面</h1>

<h3>${user.username }</h3>

<hr/>

</body>

/admin/admin.jsp

<body>

  <h1>管理員頁面</h1>

  <h3>${user.username }</h3>

  <hr/>

</body>

LoginServlet

public class LoginServlet extends HttpServlet {

    public void doPost(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 userService = new UserService();

       User user = userService.login(username, password);

       if(user == null) {

           request.setAttribute("msg", "使用者名稱或密碼錯誤");

           request.getRequestDispatcher("/login.jsp").forward(request, response);

       } else {

           request.getSession().setAttribute("user", user);

           request.getRequestDispatcher("/index.jsp").forward(request, response);

       }

    }

}

LoginUserFilter.java

  <filter>

    <display-name>LoginUserFilter</display-name>

    <filter-name>LoginUserFilter</filter-name>

    <filter-class>cn.cloud.filter.LoginUserFilter</filter-class>

  </filter>

  <filter-mapping>

    <filter-name>LoginUserFilter</filter-name>

    <url-pattern>/user/*</url-pattern>

  </filter-mapping>

public class LoginUserFilter implements Filter {

    public void destroy() {}

    public void init(FilterConfig fConfig) throws ServletException {}

    public void doFilter(ServletRequest request, ServletResponse response,

           FilterChain chain) throws IOException, ServletException {

       response.setContentType("text/html;charset=utf-8");

       HttpServletRequest req = (HttpServletRequest) request;

       User user = (User) req.getSession().getAttribute("user");

       if(user == null) {

           response.getWriter().print("您還沒有登入");

           return;

       }

       chain.doFilter(request, response);

    }

}

LoginAdminFilter.java

  <filter>

    <display-name>LoginAdminFilter</display-name>

    <filter-name>LoginAdminFilter</filter-name>

    <filter-class>cn.itcast.filter.LoginAdminFilter</filter-class>

  </filter>

  <filter-mapping>

    <filter-name>LoginAdminFilter</filter-name>

    <url-pattern>/admin/*</url-pattern>

  </filter-mapping>

public class LoginAdminFilter implements Filter {

    public void destroy() {}

    public void init(FilterConfig fConfig) throws ServletException {}

    public void doFilter(ServletRequest request, ServletResponse response,

           FilterChain chain) throws IOException, ServletException {

       response.setContentType("text/html;charset=utf-8");

       HttpServletRequest req = (HttpServletRequest) request;

       User user = (User) req.getSession().getAttribute("user");

       if(user == null) {

           response.getWriter().print("您還沒有登入!");

           return;

       }

       if(user.getGrade() < 2) {

           response.getWriter().print("您的等級不夠!");

           return;

       }

       chain.doFilter(request, response);

    }

}

禁止資源快取

瀏覽器只是要快取頁面,這對我們在開發時測試很不方便,所以我們可以過濾所有資源,然後新增去除所有快取!

public class NoCacheFilter extends HttpFilter {

    public void doFilter(HttpServletRequest request,

           HttpServletResponse response, FilterChain chain)

           throws IOException, ServletException {

       response.setHeader("cache-control", "no-cache");

       response.setHeader("pragma", "no-cache");

       response.setHeader("expires", "0");

       chain.doFilter(request, response);

    }

}

POST和GET中文編碼

servlet:

l  POST:request.setCharacterEncoding(“utf-8”);

l  GET:

Ø  String username = request.getParameter(“username”);

Ø  username = new String(username.getBytes(“ISO-8859-1”), “utf-8”);

需求說明

亂碼問題:

l  獲取請求引數中的亂碼問題;

Ø  POST請求:request.setCharacterEncoding(“utf-8”);

Ø  GET請求:newString(request.getParameter(“xxx”).getBytes(“iso-8859-1”), “utf-8”);

l  響應的亂碼問題:response.setContextType(“text/html;charset=utf-8”)。

思路分析

全站亂碼問題的難點:處理GET請求引數的問題。

public class EncodingFilter extends HttpFilter {

    public void doFilter(HttpServletRequest request,

           HttpServletResponse response, FilterChain chain)

           throws IOException, ServletException {

       String charset = this.getInitParameter("charset");

       if(charset == null || charset.isEmpty()) {

           charset = "UTF-8";

       }

       request.setCharacterEncoding(charset);

       response.setContentType("text/html;charset=" + charset);

       chain.doFilter(request, response);

    }

}

如果是POST請求,當執行目標Servlet時,Servlet中呼叫request.getParameter()方法時,就會根據request.setCharacterEncoding()設定的編碼來轉碼!這說明在過濾器中呼叫request.setCharacterEncoding()方法會影響在目標Servlet中的request.getParameter()方法的行為!

但是如果GET請求, request只有getParameter(),而沒有setParameter()方法

下面是三種對a物件進行增強的手段:

程式碼描述

EncodingRequest

public class EncodingRequest extends HttpServletRequestWrapper {

    private String charset;

    public EncodingRequest(HttpServletRequest request, String charset) {

       super(request);

       this.charset = charset;

    }

    public String getParameter(String name) {

       HttpServletRequest request = (HttpServletRequest) getRequest();

       String method = request.getMethod();

       if(method.equalsIgnoreCase("post")) {

           try {

              request.setCharacterEncoding(charset);

           } catch (UnsupportedEncodingException e) {}

       } else if(method.equalsIgnoreCase("get")) {

           String value = request.getParameter(name);

           try {

              value = new String(name.getBytes("ISO-8859-1"), charset);

           } catch (UnsupportedEncodingException e) {

           }

           return value;

       }

       return request.getParameter(name);

    }

}

EncodingFilter

public class EncodingFilter extends HttpFilter {

    public void doFilter(HttpServletRequest request,

           HttpServletResponse response, FilterChain chain)

           throws IOException, ServletException {

       String charset = this.getInitParameter("charset");

       if(charset == null || charset.isEmpty()) {

           charset = "UTF-8";

       }

       response.setCharacterEncoding(charset);

       response.setContentType("text/html;charset=" + charset);

       EncodingRequest res = new EncodingRequest(request, charset);

       chain.doFilter(res, response);

    }

}

web.xml

  <filter>

    <filter-name>EncodingFilter</filter-name>

    <filter-class>cn.itcast.filter.EncodingFilter</filter-class>

    <init-param>

        <param-name>charset</param-name>

        <param-value>UTF-8</param-value>

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>EncodingFilter</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>