1、首先笔记一个配置了一个小时的解决后却发现十分简单的问题:
Mysql的jar包要导入web-inf目录下,谨记,谨记!终于迎来了黑色字体的成功语句。
2、URI和URL的区别:
URI(Uniform Resource Identifier)可以分成URL(Uniform Resource Locator)、URN或同时具备locators和names特性的一个东西。URN的作用就好像一个人的名字,URL就像一个人的地址。URN确定了东西的身份,URL提供了找到它的方式。
3、Filter有如下几个种类:
①用户授权的filter:过滤用户非法请求
②日志filter:详细记录某些特殊的用户请求
③负责解码的filter:包括对非标准编码的请求解码
④能改变XML内容的XSLT filter等
⑤filter可负责拦截多个请求或相应;一个请求或响应也可被多个filter拦截。
4、filter的用途之一:实现代码的重用
如系统中有多个servlet,都要进行权限控制、记录日志等通用处理,这将导致在这些servlet的service方法中有部分代码是相同的,因此可以把这些通用处理提取到Filter中完成,这样各servlet中剩下的只是特定请求相关的处理代码,而通用处理则交给filter完成。
5、Listener(监听器):监听web应用的内部事件,从而允许当web内部事件发生时回调事件监听器内的方法。
6、常用的web事件监听器接口:
①ServletContextListener:Implementations of this interface receive notifications(通知)about changes to the servlet context of the web application they are part of. To receive notification events, the implementation class must be configured in the deployment(部署)descriptor for the web application. 用于监听web应用的启动和关闭。
②ServletContextAttributeListener:Implementations of this interface receive notifications of changes to the attribute list on the servlet context of a web application. To receive notification events, the implementation class must be configured in the deployment descriptor for the web application.用于监听ServletContext范围内的属性的改变。
③ServletRequestListener:A ServletRequestListener can be implemented by the developer interested in being notified of requests coming in and out of scope in a web component. A request is defined as coming into scope when it is about to enter the first servlet or filter in each web application, as going out of scope when it exits the last servlet or the first filter in the chain.用于监听用户请求。
④ServletRequestAttributeListener:A ServletRequestAttributeListener can be implemented by the developer interested in being notified of request attribute changes. Notifications will be generated while the request is within the scope of the web application in which the listener is registered. A request is defined as coming into scope when it is about to enter the first servlet or filter in each web application, as going out of scope when it exits the last servlet or the first filter in the chain.用于监听ServletRequest范围内属性的改变。
⑤HttpSessionListener:Implementations of this interface are notified of changes to the list of active sessions in a web application. To receive notification events, the implementation class must be configured in the deployment descriptor for the web application.用于监听用户session的开始和结束。
⑥HttpSessionAttributeListener:This listener interface can be implemented in order to get notifications of changes to the attribute lists of sessions within this web application。用于监听HttpSession范围内属性的改变
7、代码示例:
(1)Filter示例:
①AuthorityFilter.java:首先按照配置参数设置了request编码所用的字符集,接下来判断session范围内是否有user属性——没有该属性即认为没有登录,若没有登录请求其他页面,则系统直接跳转到登录页面。
package com.deng.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Servlet Filter implementation class AuthorityFilter */ @WebFilter(filterName="authority", urlPatterns={"/*"}, initParams={ @WebInitParam(name="encoding",value="UTF-8"), @WebInitParam(name="loginPage",value="/Mylogin.jsp"), @WebInitParam(name="successPage",value="/SuccessLogin.jsp") }) public class AuthorityFilter implements Filter { private FilterConfig config;//Filter的配置信息 public AuthorityFilter() { // TODO Auto-generated constructor stub } public void destroy() { this.config = null; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String encoding = config.getInitParameter("encoding"); String loginPage = config.getInitParameter("loginPage"); String successPage = config.getInitParameter("successPage"); request.setCharacterEncoding(encoding);//设置request编码的字符集为UTF-8 HttpServletRequest requ = (HttpServletRequest)request; String requestPath = requ.getRequestURI(); HttpSession session = requ.getSession(true); if(requestPath.endsWith("LoginServlet") || requestPath.endsWith(loginPage)){ chain.doFilter(request, response);//放行请求 return; } if(!"remoa".equals(session.getAttribute("username"))){ requ.getRequestDispatcher(loginPage).forward(request, response); }else { requ.getRequestDispatcher(successPage).forward(request, response); } } public void init(FilterConfig fConfig) throws ServletException { this.config = fConfig; } }
(2)Listener示例:
①GetConnListener.java:使所有的jsp页面都可以通过application获取数据库连接,从而可以非常方便地进行数据库访问。
package com.learn.Listener; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class GetConnListener implements ServletContextListener{ //关闭web应用时,系统调用该方法 @Override public void contextDestroyed(ServletContextEvent sce) { ServletContext application = sce.getServletContext(); Connection conn = (Connection)application.getAttribute("conn"); if(conn != null){ try{ conn.close();//关闭数据库连接 }catch(SQLException e){ System.out.println("Listener关闭数据库连接异常" + e.getMessage()); } } } //启动web应用时,系统调用此方法 @Override public void contextInitialized(ServletContextEvent sce) { InputStream inputStream = GetConnListener.class.getClassLoader().getResourceAsStream("conf.properties"); Properties pro = new Properties(); try { pro.load(inputStream); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { ServletContext application = sce.getServletContext(); String url = pro.getProperty("url"); String user = pro.getProperty("user"); String password = pro.getProperty("password"); String driver = pro.getProperty("driver"); application.setAttribute("url", url); application.setAttribute("user", user); application.setAttribute("password", password); application.setAttribute("driver", driver); Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, password); application.setAttribute("conn", conn); System.out.println("测试成功,监听器建立数据库连接成功!"); } catch (SQLException e) { System.out.println("Listener中获取数据库连接出现异常" + e.getMessage()); } catch (ClassNotFoundException e) { e.printStackTrace(); System.out.println("获取驱动时没有找到响应的类" + e.getMessage()); } } }
②MyServletContextAttributeListener.java:当application范围内的属性被添加、删除、替换时,这些对应的监听器方法将会被触发。
package com.learn.Listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeListener; import javax.servlet.annotation.WebListener; @WebListener public class MyservletContextAttributeListener implements ServletContextAttributeListener { //当程序向application范围添加属性时触发该方法 public void attributeAdded(ServletContextAttributeEvent event) { ServletContext application = event.getServletContext(); String name = event.getName(); Object value = event.getValue(); System.out.println(application + "范围内添加了名为" + name + ",值为" + value + "的属性!"); } //当application范围的属性被替换时触发该方法 public void attributeReplaced(ServletContextAttributeEvent event) { ServletContext application = event.getServletContext(); String name = event.getName(); Object value = event.getValue(); System.out.println(application + "范围内名为" + name + ",值为" + value + "的属性被替换了!"); } //当程序从application范围删除属性时触发该方法 public void attributeRemoved(ServletContextAttributeEvent event) { ServletContext application = event.getServletContext(); String name = event.getName(); Object value = event.getValue(); System.out.println(application + "范围内删除了名为" + name + ",值为" + value + "的属性!"); } }
③RequestListener.java:可以监听到每次请求的创建、销毁。因此Web应用可以通过该监听器来监听访问该应用的每个请求,从而实现系统日志。
package com.learn.Listener; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestAttributeEvent; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpServletRequest; @WebListener public class RequestListener implements ServletRequestListener, ServletRequestAttributeListener { //用户请求结束、被销毁时触发该方法 public void requestDestroyed(ServletRequestEvent sre) { HttpServletRequest request = (HttpServletRequest)sre.getServletRequest(); System.out.println("发向" + request.getRequestURI() + "请求被销毁"); } //当程序向request范围添加属性时触发该方法 public void attributeAdded(ServletRequestAttributeEvent event) { ServletRequest request = event.getServletRequest(); String name = event.getName(); Object value = event.getValue(); System.out.println(request + "范围内添加了名为" + name + ",值为" + value + "的属性!"); } //当程序向request范围删除属性时触发该方法 public void attributeRemoved(ServletRequestAttributeEvent event) { ServletRequest request = event.getServletRequest(); String name = event.getName(); Object value = event.getValue(); System.out.println(request + "范围内删除了名为" + name + ",值为" + value + "的属性!"); } //当request范围的属性被替换时触发该方法 public void attributeReplaced(ServletRequestAttributeEvent event) { ServletRequest request = event.getServletRequest(); String name = event.getName(); Object value = event.getValue(); System.out.println(request + "范围内替换了名为" + name + ",值为" + value + "的属性!"); } //当用户请求到达,被初始化时触发该方法 public void requestInitialized(ServletRequestEvent sre) { HttpServletRequest request = (HttpServletRequest)sre.getServletRequest(); System.out.println("发向" + request.getRequestURI() + "请求被初始化"); } }
④OnlineListener.java:在application范围内的Map记录了当前应用的所有在线用户
package com.learn.Listener; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; @WebListener public class OnlineListener implements HttpSessionListener{ //当用户与服务器之间开始session时触发该方法 public void sessionCreated(HttpSessionEvent se) { HttpSession session = se.getSession(); ServletContext application = session.getServletContext(); String sessionID = session.getId(); if(session.isNew()){ String user = (String)session.getAttribute("user"); user = (user==null) ? "游客" : user;//未登录用户当作游客处理 Map<String, String> online = (Map<String, String>)application.getAttribute("online"); if(online == null){ online = new HashMap<String, String>(); } online.put(sessionID, user); application.setAttribute("online", online); } } //当用户与服务器之间session断开时触发该方法 public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); ServletContext application = session.getServletContext(); String sessionID = session.getId(); Map<String, String> online = (Map<String, String>)application.getAttribute("online"); if(online != null){ online.remove(sessionID);//删除该用户的session在线信息 } application.setAttribute("online", online); } }
package com.learn.Listener; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @WebListener public class MyRequestListener implements ServletRequestListener { private String driver; private String url; private String user; private String password; public MyRequestListener(){ InputStream inputStream = GetConnListener.class.getClassLoader().getResourceAsStream("conf.properties"); Properties pro = new Properties(); try { pro.load(inputStream); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); driver = pro.getProperty("driver"); } //当用户请求结束,被销毁时触发该方法 public void requestDestroyed(ServletRequestEvent sre) { // TODO Auto-generated method stub } //当用户请求到达,被初始化时触发该方法 public void requestInitialized(ServletRequestEvent sre) { HttpServletRequest request = (HttpServletRequest)sre.getServletRequest(); HttpSession session = request.getSession(); String sessionID = session.getId(); String ip = request.getRemoteAddr(); String page = request.getRequestURI(); String user2 = (String)session.getAttribute("user"); user2 = (user2 == null) ? "游客" : user2; Connection conn = DbDao.getConnection(driver, url, user, password); String sql = "select * from dengqinyi where session_id = ?"; PreparedStatement pstmt = null; try { pstmt = conn.prepareStatement(sql); pstmt.setString(1, sessionID); ResultSet rs = pstmt.executeQuery(sql); //如果用户对应的sessionID存在,表明是旧的会话 if(rs.next()){ //更新记录 rs.updateString(4, page);//更新正在访问的资源URI地址 rs.updateLong(5, System.currentTimeMillis());//更新访问时间 rs.updateRow(); rs.close(); }else{ String sql2 = "insert into dengqinyi values(?, ?, ?, ?, ?)"; pstmt.setString(2, user2); pstmt.setString(3, ip); pstmt.setString(4, page); pstmt.setLong(5, System.currentTimeMillis()); pstmt.executeUpdate(sql2); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package com.learn.Listener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class MyOnlineListener implements ServletContextListener { private String driver; private String url; private String user; private String password; public MyOnlineListener(){ InputStream inputStream = GetConnListener.class.getClassLoader().getResourceAsStream("conf.properties"); Properties pro = new Properties(); try { pro.load(inputStream); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); driver = pro.getProperty("driver"); } //应用启动时触发该方法 public void contextInitialized(ServletContextEvent arg0) { //每十秒检查一次 new javax.swing.Timer(1000 * 10, new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { try{ Connection conn = DbDao.getConnection(driver, url, user, password); String sql = "select * from dengqinyi"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); StringBuffer beRemove = new StringBuffer("("); while(rs.next()){ //若距离上次访问时间超过了10分钟 if(System.currentTimeMillis() - rs.getLong(5) > 10 * 60 * 1000){ //将需要删除的sessionID添加进来 beRemove.append("'"); beRemove.append(rs.getString(1)); beRemove.append("' , "); } } //有需要删除的记录 if(beRemove.length() > 0){ beRemove.setLength(0); beRemove.append(")"); String sqlDelete = "delete from dengqinyi where session_id in " + beRemove.toString();//删除所有"超过指定时间未重新请求的记录" stmt.executeUpdate(sqlDelete); } DbDao.closeAll(conn, stmt, rs); }catch(Exception ex){ ex.printStackTrace(); } } }).start(); } //应用关闭时,该方法被调用 public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub } }
package com.learn.Listener; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DbDao { public static Connection getConnection(String driver, String url, String user, String password){ Connection conn = null; try { Class.forName(driver); conn = DriverManager.getConnection(url, user, password); } catch (ClassNotFoundException e) { e.printStackTrace(); }catch (SQLException e) { e.printStackTrace(); } return conn; } public static void closeAll(Connection conn, Statement stmt, ResultSet rs){ if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt != null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }