无论进入哪个网站,用户注册是必不可少的一部分,用户注册所需要的时间是影响用户体验最重要的一环,今天我们我们的任务就是以用户注册为例,使用servlet监听器对用户注册速度进一步优化

用户注册,也就是将用户数据写入到数据库,我们优化注册速度,也就是对后端操作数据库进行优化,像我这种小白用java写注册程序时,每当有用户注册时,就会先连接数据库,然后执行操作语句,最后关闭,多个用户注册时,就是上面流程的循环,我们知道,连接数据库也是需要时间的,所以,这样就有大把的时间都浪费在了连接数据库上,所以我们可以结合监听器来解决这个问题(都是很基础的东西)

先贴两张优化之前和优化之后的用户注册速度对比图

优化之前:

优化之后:

用户注册优化思路:既然时间大多都花在连接数据库上,那我们可以让用户在注册时省去连接数据库这个步骤,并不是不用连接数据库,而是不在用户注册时连接,我们可以提前创建好连接对象,然后用户注册时可以直接调用这个连接对象,那我们什么时候创建连接对象呢?我们可以在服务器启动时就创建好连接对象,那怎样实现在服务器启动时就创建连接对象呢?这就可以借助我们的监听器了,服务器启动时就会创建servlet上下文对象,而监听器可以监听servlet上下文对象的状态,包括何时被初始化,何时被摧毁,以及上下文对象里面存放的数据的变化,这样我们就可以利用监听器的这些功能来完成我们的设想

项目结构

其中Listener.java是监听器接口的实现类

代码部分

AddInfoDao.java部分

package dao;import java.sql.*;import java.util.Iterator;import java.util.Map;import javax.servlet.ServletContext;import javax.servlet.http.HttpServletRequest;public class AddInfoDao {private static Connection conn = null;private static PreparedStatement pst = null;public static boolean addinfo(String a,String b,String c,String d,HttpServletRequest request) {boolean result = false;//创建servlet上下文对象ServletContext application = request.getServletContext();//获取上下文对象中存放的Map@SuppressWarnings("unchecked")Map<Connection, Boolean> allconn = (Map<Connection, Boolean>) application.getAttribute("allconn");Iterator<Connection> keys = allconn.keySet().iterator();//从Map中获取连接对象while (keys.hasNext()) {//判断连接对象是否正在被使用,如果为true,表示可以使用,如果为false,表示正在被使用if (allconn.get(keys.next()) == true) {conn = keys.next();//使用一个连接对象时,将此连接对象的使用状态标识为falseallconn.put(conn, false);//因为我们正在使用一个连接对象,所以我们要将此连接对象的状态更新到servlet上下文中,这样其他用户才可以知道此连接对象已被使用application.setAttribute("allconn", allconn);break;}}try {//执行添加数据的SQL语句pst = conn.prepareStatement("insert into demo values (?,?,?,?)");pst.setString(1, a);pst.setString(2, b);pst.setString(3, c);pst.setString(4, d);pst.executeUpdate();result = true;} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {//当我们执行完sql语句不再使用连接对象时,将连接对象的表示状态改为true,表示其他用户可以使用此连接对象allconn.put(conn, true);//改变完连接对象的状态后,要更新到上下文中,这样其他用户才可以知道application.setAttribute("allconn", allconn);}return result;}}

GetInfoServlet.java部分

package getinfo;import java.io.IOException;import java.util.Date;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import dao.AddInfoDao;@WebServlet("/GetInfoServlet")public class GetInfoServlet extends HttpServlet {private static final long serialVersionUID = 1L;   public GetInfoServlet() {super();// TODO Auto-generated constructor stub}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");String a = request.getParameter("a");String b = request.getParameter("b");String c = request.getParameter("c");String d = request.getParameter("d");Date time1 = new Date();boolean result = AddInfoDao.addinfo(a, b, c, d, request);Date time2 = new Date();System.out.println("用户注册用时为:  " + (time2.getTime()-time1.getTime()) + "毫秒");if (result == true) {System.out.println("添加成功");}else {System.out.println("添加失败");}}}

Listener.java部分

package listener;import java.sql.*;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import javax.servlet.ServletContext;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import util.SqlServerConnection;// 实现ServletContextListener接口,监听servlet上下文的状态public class Listener implements ServletContextListener {private Connection conn = null;//创建Map用来存放数据库连接对象  Map中的键用来存放数据库连接对象 值用来标识此连接对象是否被使用Map<Connection, Boolean> allconn = new HashMap<Connection, Boolean>();//servlet上下文初始化时执行此方法public void contextInitialized(ServletContextEvent sce) {//创建10个连接对象for (int i = 0; i < 10; i++) {conn = SqlServerConnection.sql_connection();System.out.println("创建数据库连接对象  " + conn);allconn.put(conn, true);}//将存放连接对象的Map存放在servlet上下文中,从服务器启动到服务器关闭期间可以随时随地使用sce.getServletContext().setAttribute("allconn", allconn);}//servlet上下文被摧毁时执行此方法public void contextDestroyed(ServletContextEvent sce) {//创建Servlet上下文对象,生命周期从服务器启动到服务器关闭ServletContext application = sce.getServletContext();//获取存放数据库连接对象的map@SuppressWarnings("unchecked")Map<Connection, Boolean> allconn = (Map<Connection, Boolean>) application.getAttribute("allconn");//获取所有数据库连接对象  连接对象我们存放在了Map的键中 所以我们要获取Map中所有的键Iterator<Connection> it = allconn.keySet().iterator();//循环关闭所有数据库连接对象while (it.hasNext()) {Connection connection = (Connection) it.next();try {connection.close();System.out.println("关闭数据库连接对象   " + connection);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

SqlServerConnection.java部分

package util;import java.sql.*;public class SqlServerConnection {static Connection conn;static String drive = "com.microsoft.sqlserver.jdbc.SQLServerDriver";static String url = "jdbc:sqlserver://localhost:1433;DatabaseName=ShopSystem";static String username = "sa";static String password = "sa";public static Connection sql_connection() {try {//注册驱动Class.forName(drive);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {//创建连接对象conn = DriverManager.getConnection(url,username,password);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();System.out.println("连接失败");}return conn;}public static void main(String[] args) {// TODO Auto-generated method stubsql_connection();}}

web.xml部分

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">  <display-name>WebTest</display-name>  <welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file><welcome-file>default.html</welcome-file><welcome-file>default.htm</welcome-file><welcome-file>default.jsp</welcome-file>  </welcome-file-list>  <listener>  <listener-class>listener.Listener</listener-class>  </listener></web-app>

index.html部分

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title></head><body><center><form action="GetInfoServlet" method="post"><input type="text" name="a"><br/><input type="text" name="b"><br/><input type="text" name="c"><br/><input type="text" name="d"><br/><input type="submit"></form></center></body></html>

jar包获取地址:https://pan.baidu.com/s/1XvJf2bWmLoQPNU8VCjBfgQ
提取码:q0bl

©著作权归作者所有:来自51CTO博客作者SmallSweets的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 【博客大赛】【实战】k8s中长连接服务负载不均衡问题分析
  2. 痞子衡嵌入式:揭秘i.MXRT600的ISP模式下用J-Link连接后PC总是停在
  3. Java面试题,Java面试题及答案,2021最新的,都整理好了
  4. PO BO VO DTO POJO DAO概念及其作用(附转换图)
  5. 【DB笔试面试591】在Oracle中,什么是星型连接(Star Join)?
  6. Vue开发中可以使用的ES6新特征
  7. JavaScript从作为函数实参的对象中提取数据
  8. Spring Data开发手册|Java持久化API(JPA)需要了解到什么程度呢?
  9. 动态资源技术JSP|Java与Html的美好相遇

随机推荐

  1. android xml 常用控件介绍
  2. android 创建动态创建菜单(钩子)
  3. android 开启本地相册选择图片并返回显示
  4. 如何解决:Android中 Error generating fin
  5. Android横竖屏切换解决方案
  6. Android的安装和配置【Z】
  7. Android生成keystore是报错拒绝访问
  8. Received status code 400 from server:
  9. Android helloword demo程序不能运行
  10. Android(安卓)RecyclerView简单运用