过滤器可以用来做权限校验或是编码转换等功能。
多个过滤器可以串联在一起,做多重过滤。
自定义的过滤器需实现javax.servlet.Filter介面。
编码转换案例:
设定过滤範围及encoding方式@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "encoding",value = "utf-8")})public class CharacterEncodingFilter implements Filter {…}urlPatterns = "/*" //过滤目标为此网站下所有网页initParams = {@WebInitParam(name = "encoding",value = "utf-8")} //将encoding方式设为utf-8(或其他编码)
在init方法中读取参数 public void init(FilterConfig fConfig) throws ServletException { this.encoding = fConfig.getInitParameter("encoding"); }
在doFilter中过滤请求 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if(encoding != null) { request.setCharacterEncoding(encoding); } HttpServletRequest r = (HttpServletRequest)request; if(r.getMethod().equalsIgnoreCase("get")) { //只针对GET请求进行过滤,POST方法通常不会乱码。 Enumeration<?>names = request.getParameterNames(); while(names.hasMoreElements()) { String[] values = request.getParameterValues(names.nextElement().toString()); for(int i = 0;i < values.length; ++i) { values[i] = new String(values[i].getBytes("ISO-8859-1"),encoding); } } } chain.doFilter(request, response); //过滤器处理完后丢给下一个过滤器或引导至资源网页。 }
权限校验案例:
用户登入成功后,将用户保存至session中。将之前写的LoginSvl稍作修正,原本把用户名保存在request,这次保存到session里面
@WebServlet("/LoginSvl")public class LoginSvl extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String uname = request.getParameter("uname"); request.getSession().setAttribute("uname", uname); String pwd = request.getParameter("pwd"); //request.setAttribute("uname", uname); request.getRequestDispatcher("/main/hello.jsp").forward(request, response); }}
定义用户权限过滤器@WebFilter(filterName = "/UserFilter", urlPatterns = "/user/*")public class UserFilter implements Filter { (前略…) public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; Object object = req.getSession().getAttribute("uname"); if(object != null) { //这边因为是範例,所以没有从资料库拿使用者名单,只是简单的从session里确认是否有uname被储存了。 chain.doFilter(request, response); }else { request.setAttribute("msg", "请先登录"); req.getRequestDispatcher("/main/login.jsp").forward(request, response); } }}
製作jsp页面新增user/UserInfo.jsp页面,随意添加一行内容。
Hi,${uname}
跑看看过滤器是否起作用吧。
监听器的种类繁多,用来监听各种不同对象。不像Filter一样只有一种。例如:
ServletContextListener
当伺服器启动时会创建ServletContext物件,此时利用监听器即可加载一些初始化资讯。
@WebListenerpublic class MyContextListener implements ServletContextListener {} public void contextDestroyed(ServletContextEvent sce) { } public void contextInitialized(ServletContextEvent sce) { System.out.println("Tomcat启动,ServletContext被创建"); }
HttpSessionListener
一个Session代表一个在线上的用户,因此可以用监听器追蹤或管理用户状态。
注:统计用户对象时,如果用户主动登出,Web应用程式会自动创建另一个会话对象,因此线上人数不会变更。只有用户超时未操作时,线上人数才会减少。
聊天室管理
利用监听器也可以踢掉不当发言的使用者,流程如下:
在自订的HttpSessionListener里新增一个Map来管理所有session在LoginSvl里面也新增一个Map,把所有登入后的使用者放进去。如果有想踢掉的使用者,先从LoginSvl的Map找出使用者的sessionid,然后用此id找到在监听器map里相对应的session,使其失效即可。@WebListenerpublic class OnlineUserListerner implements HttpSessionListener { public static Map<String,HttpSession> allUser; static { allUser = new ConcurrentHashMap<>(); } public void sessionCreated(HttpSessionEvent se) { HttpSession session = se.getSession(); allUser.put(session.getId(), session); } public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); allUser.remove(session.getId(), session); }}
@WebServlet("/LoginSvl")public class LoginSvl extends HttpServlet { private Map<String,String> loginedUsers = new ConcurrentHashMap<>(); (中略…) protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String uname = request.getParameter("uname"); String pwd = request.getParameter("pwd"); LoginBiz biz = new LoginBiz(); User user = biz.login(uname,pwd); request.getSession().setAttribute("user", uname); loginedUsers.put(uname, request.getSession().getId()); request.getRequestDispatcher("/main/main.jsp").forward(request, response); }}
踢除某用户的方法
String sessionid = loginedUsers.get(uname);HttpSession session = OnlineUserListerner.allUser.get(sessionid);session.invalidate();
ServletRequestListener
监听每一次用户访问纪录,可用于统计网站被访问次数,例如:
@WebListenerpublic class PageViewListener implements ServletRequestListener { AtomicInteger pv; public PageViewListener() { System.out.println("PageViewListener被建立"); pv = new AtomicInteger(0); } public void requestDestroyed(ServletRequestEvent sre) { } public void requestInitialized(ServletRequestEvent sre) { System.out.println(pv.incrementAndGet()); }
此监听器在Tomcat启动时被建立
使用AtomicInteger pv当作计数器。
每次收到客户端的request就会触发一次requestInitialized()。