JavaWeb
JDBC
J: Java
DB: DataBase
C: Connectivity
作用:使用java操作数据库,Java操作数据库的规范,定义了所有操作数据库的一组接口,这组接口就是JDBC;java.sql
注:所有从外面引入的jar包都放入lib文件夹里面
导入驱动jar包
1.新建lib文件夹
2.将驱动包(mysql-connector-java-5.1.6-bin.jar)放入lib文件夹
3.选中驱动文件,右键buildpath–add to path
Statement
具体步骤如下例所示:
1 | //1.注册驱动 |
PreparedStatement
允许占位符
1 | //1.加载驱动 |
Properties文件的获取
1 | properties文件下的的内容: |
1 | //1.得到properties文件路径 |
连接池
常用连接池
德鲁伊 druid 阿里
dbcp apach
c3p0
德鲁伊的使用步骤如下:
1.导入druid-1.0.12.jar到lib文件夹下
2.选中文件,右键buildpath–add to path
1 | 3.如下 |
另外两个创建对象的类
dbcp BasicDataSource()
c3p0 CombopooledDataSource()
开启连接池及归还连接代码
1 | package com.woniu.jdbc.util; |
MVC分层:model view control
JavaEE分三层:
视图(view):
服务层(service):逻辑判断,流程处理
持久层(dao):所有操作数据库
dao层里面存对数据库操作的接口类,在接口里面规定所有对该表的查询方法,查询完成之后,将结果返回给service层,由service层进行判断处理
JavaBean
也就是模型类(实体类)的升级版
1.类必须使用public修饰
2.所有属性私有化,提供get set方法
3.必须提供一个无参构造
4.最好实现序列化接口
增删改查工具类
1.导入commons-dbutils-1.6.jar
2.选中文件,右键buildpath–add to path
使用方式如下:
创建:
QueryRunner qr = new QueryRunner();
查询单个对象:
User user =
qr.query(connection,sql,new BeanHandler
查询所有:
List
qr.query(connection,sql,new BeanListHandler
新增 修改 删除
String sql = “insert into t_user values(?,?)”;
Object[] obj ={“root”,”123456”};
int result = qr.uptate(connection,sql,obj);
注:
1. sql为自定义sql语句字符串,注意两种查询的返回类型不一样
2. ?参数可以使用Object[] obj = {account,password}写入,作 为一个参数
1 | public List<StudentData> getAllFromDataBase() { |
事务
开启事务:
连接名.setAutoCommit(false);//默认为true false为手动事务
例:connection.setAutoCommint(false);
提交事务
连接名.commit();
例:connection.commit();
HTTP协议
位于TCP/IP模型的应用层,主要用来规范前后端数据交互格式
请求:request 客户端发送数据给服务端
响应:response 服务端将处理结果返回给客户端
请求方式
GET:数据会在地址栏,发送文本数据
POST:数据不会出现在地址栏,可以发送任意类型数据
HEAD PUT DELETE OPTION
请求格式
响应格式
状态码
1xx:请求发送成功,服务器在处理
2xx:正常
3xx:重定向
4xx:客户端错误 404:请求的资源不存在
5xx:服务器内部错误
特点
无连接:一次请求,一次连接,请求完成,连接断开
无状态:下一次请求不会去记录上一次请求的数据
服务器
应用程序:根据用户的实时请求找到对应的类进行处理的一个容器使用代码编写的一个应用程序
常见服务器:tomcat:开源,免费 apach ngnix
服务器目录
bin:可执行文件
conf:配置信息
lib:类库
logs:运行日志
temp:临时文件
webapps:项目运行文件
work:jsp文件
例:tomcat目录D:\tomcat\apache-tomcat-8.0.42-windows-x86\apache- tomcat-8.0.42\conf 下的server.xml就可以修改端口
Servlet
实现了Servlet接口的类,用来处理用户请求
生命周期
创建:
请求->映射为Servlet->判断是否实例化(是继续执行,否跳到执行service())
->执行无参构造->执行init()->执行service()->执行destroy()
销毁:
当 Web 容器被关闭,或该应用被关闭,则调用执行 destroy()方法,销毁 Servlet 实例
接收请求的三种方式
Service doGet doPost
1 | public class Test extends HttpServlet{ |
request对象
会将请求头,请求行,请求数据全部封装到request对象中,如下所示:
1 | public class Test extends HttpServlet{ |
中文乱码问题
- 出现原因:
- 当用户通过浏览器提交一个包含 UTF-8 编码格式的两个字的中文请求时,浏览器会将这两个中文字符变为六个字节(一般一个 UTF-8 汉字占用三个字节),即形成六个类似%8E 的字节表示形式,并将这六个字节上传至Tomcat 服务器。Tomcat 服务器在接收到这六个字节后,并不知道它们原始采用的是什么字符编码。而Tomcat默认的编码格式为ISO-8859-1。所以会将这六个字节按照ISO-8859-1的格式进行编码,编码后在控制台显示,所以在控制台会显示乱码。
解决方式如下:
1 | //放在service方法的最开始 |
response对象
用来响应数据到浏览器
设置编码及响应内容:
resp.setContentType(“text/html;charset=utf-8”);
设置响应头信息:
resp.addHeader(“键”,”值”);//键可重复
resp.setHeader(“键”,值);//键不可重复
设置响应编码
resp.sendError(404,”你访问的页面不存在”);
响应数据
resp.getWriter().Write(“内容”);
转发
req.getRequestDispatcher(“/index”).forward(req, resp);
特点:
1.对于浏览器,只发送了一次请求
2.转发发生在服务端
3.浏览器地址栏不会发生改变
4.会造成表单重复提交
重定向
resp.sendRedirect(“index”);
特点:
1.对于浏览器,发送了两次请求
2.跳转发生在浏览器端
2.地址会改变
注意
转发:web应用内部转发,web应用来说,/根目录代表:localhost:8080/项目名/
重定向:是以服务器的根目录:localhost:8080/
转发与重定向区别
1.转发发生在服务端,重定向在浏览器端
2.转发只发送一次请求,地址栏不会改变,重定向发送了两次请求,地址栏会改变
3.转发效率高,重定向效率低
4.转发会造成表单的重复提交
5.转发只能进行内部跳转,重定向可以跳转到外部应用
6.转发可以访问WEB-INF文件夹里面的资源,重定向不可以
会话跟踪
cookie
作用:
解决多次请求需要发送相同的数据
特点:
1.cookie对象在服务端设置
2.cookie是保存在浏览器端
3.cookie的生命周期默认为浏览器关闭失效(保存在浏览器缓存中)
4.cookie保存的数据不能超过4kb
5.一般不要超过20个cookie(不同的网站,不同的cookie)
6.cookie值不要为中文
设置cookie
如下所示:
1 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
获取cookie
1 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
3天免登录
登录成功后添加cookie,cookie里面保存用户id
访问页面时先获取cookie,拿到用户id,经过service层和dao层,判断是否存在,存在则免登陆
session
作用: 共享一个用户的数据
特点: 保存在服务器
创建方式:
1 | protected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException { |
注:getSession():如果没有,就会创建;如果有,直接返回session对象,会将
sesssinid添加到JSSIONID cookie里面去,并且返回到浏览器端
生命周期
默认值为最后一次访问后的30分钟
修改方式 : session.setMaxInactiveInterval(60);//以秒为范围,不建议修改
强制销毁 : session.invalidate();//可以实现安全退出
1 | session 是一个专门用于存放数据的集合,我们一般称这个用于存放数据的内存空间为域属性空间,简称域。HttpSession 中具有三个方法,是专门用于对该域属性空间中数据进行写、读操作的。 |
ServletContext对象
全局上下文对象,存放的数据对所有客户端共享,服务器启动的时候创建,关闭的 时候销毁
获取Servlet对象方式:
1 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
作用
1.全局数据共享
2.获取初始化内容
web.xml里面
1 | <context-param>配置是是一组键值对,比如: |
3.获取webContent文件的绝对路径 getRealPath();
4.获取webContent文件的流对象 getResourceAsStream(“test.txt”);
ServletConfig对象
主要用来获取web.xml里面需要对当前的servlet进行单独配置
WEB配置如下
1 | <servlet> |
java端controler类端
1 | public class Test extends HttpServlet{ |
字符串转JSON
使用方法:
1.放jar包 将 json需用包下全部 放入lib文件夹下
2.JSONObject jUser = JSONObject.fromObject(user)
//user对象重写了toString方法,满足JSON格式
ajax
- Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)
- 当使用结合了这些技术的AJAX模型以后, 网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。
原生HTML实现
web端设置
1 | <input type="text" id="account" placeholder="请输入账号"/> |
java端设置
1 |
|
JQuery实现
1.$.ajax()
post请求:
1 | $.ajax({ |
get请求:
1 | $.ajax({ |
2.$.get()
1 | $.get('fzz.php',{ |
3.$.post()
1 | $.post('fzz.php',{ |
4.实例
- input.jsp
1 | <!--实现效果:不刷新页面查询账号是否存在--> |
- AjaxTest
1 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
调用函数的两种方式
1.配置web.xml,通自定义url名跳转
1 | <servlet> |
2.类名上加注解,加上后就可以通过转发(有/)或重定向跳转(无/),
注意转发和重定向的目录起始点不一样
例:@WebServlet(“/Ajax”)
小结
前言
JavaEE java企业级版本
基础技术
- 已学
- Servlet
- JDBC
- Cookie
- Session
未学
- JSP (Java Server Page) 动态页面组件
- EL
- JSTL
- Filter 过滤器
- Listener 监听器
自定义Web框架
- 知识准备
- 泛型
- 反射
- 注解
框架
- MVC框架
- ORM框架
开发项目
JSP
- 动态页面/静态页面
- 动态页面是指:内容会根据不同的数据发生改变的页面
- 实现方式一 : 前端实现 AJAX+JSON+JS
- 实现方式二 : 后端实现 servlet=>out.write(““)
- 实现方式三 : 后端实现 JSP java(动态性)+html(编写静态的HTML代码)
组成部分
- 指令元素<%@>
- page => 整个页面的配置
- import
- contentType:text/html;charset=utf-8
- language
- pageEncoding 字符编码集
- isErrorPage
- include => 在页面中包含另一个jsp页面
- taglib => 引用标签库(JSTL)
- page => 整个页面的配置
- html元素HTML标签
- 脚本元素 <% %> java代码
- 表达式元素 <%= %> 在页面上输出数据 等价于 out.write(数据) 结尾不能有分号
- 声明元素 <%! %> 声明java方法或属性
- JSP注释元素 <%– 注释内容 –%>
传值
Servlet -> jsp
跳转的两种方式
- 转发 : 服务端转发,共享请求对象
- 重定向
JSP也可以处理网络请求,Servlet可以将请求转发给JSP
request
setAttribute
getAttribute
翻译规则
JSP是后端的页面技术
JSP本质上是Servlet
JSP翻译过后的类 extends HttpJspBase extends HttpServlet
运行过程 : JSP==tomcat翻译==>Java==javac编译==>Class==>JVM运行
翻译 tomcat实现
翻译的规则
- html 原样输出
- 表达式元素 out.print(内容);
- 脚本元素 原样转移到生成类中
- 声明元素 翻译到类体中,作为独立的方法和属性存在
- 查看翻译结果:使用<%=request.getServletContext().getRealPath(“/“)%>在网页上输出路径,再根据路径找到翻译后的内容,例:D:\tomcat\apache-tomcat-8.0.42-windows-x86\apache-tomcat-8.0.42\work\Catalina\localhost\11Week01Day\org\apache\jsp下的文件就是翻译之后的文件
隐式对象
pageContext
request
session HttpSession
application ServletContext
response
out JspWriter
page object
config ServletConfig
exception Throwable
在JSP中无需创建就可以使用的9个对象,它们是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
l out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
l config(ServletConfig):对应“真身”中的ServletConfig;
l page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象;
l pageContext(PageContext):页面上下文对象;
l exception(Throwable):只有在错误页面中可以使用这个对象;
l request(HttpServletRequest):即HttpServletRequest类的对象;
l response(HttpServletResponse):即HttpServletResponse类的对象;
l application(ServletContext):即ServletContext类的对象;
l session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。JSP中除了声明元素,其他都翻译到了service中
内置对象,是jspService方法中的参数或者预先声明赋值的局部变量
四大作用域
pageContext==>request==>session==>application
都有 setAttribute/getAttribute/removeAttribute
可以存取数据,但仅在一定范围内生效,把生效范围称为作用域
- pageContext 一个JSP页面 当前页面有效
- request 同一个请求 同一次请求有效
- session 同一个会话 同一次会话有效
- application 同一个应用 : 服务器启动时创建、服务器关闭时销毁(全局有效)
原则 : 满足需求的情况下,尽量选择小的作用域范围
例:
```java
pageContext作用域:
this.getServletContext().setAttribute(arg0, arg1);
session作用域:
Object sessionToken = req.getSession().getAttribute(“_anti_duplicate_token”);1
2
3
4
5
6
7
8
9
### EL
作用:替代表达式元素,在页面上取值
语法:${变量名},如果有嵌套则使用`.`调用属性
```jsp
${user} ${user.address} ${user.address.city}
取值规则:从四大作用域,从小到大自动获取
补充
- 后端模板引擎 : FreeMarker\velocity\Thymeleaf\Mustache
例:
Java代码(这个例子未用EL)
1 |
|
index.jsp文件内部分代码
1 | <%--得到数据 --%> |
JSTL
Java Standard Taglib java 标准标签库
JSP,引入各种元素 <%> <%= %>
简化页面动态逻辑的编写(干掉<%)
提供一系列的标签库,实现循环、判断、取值等页面逻辑
使用方式
导包:standard.jar jstl.jar
引用核心标签库: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> JSTL格式化标签用来格式化并输出文本、日期、时间、数字(根据需要) <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#### set out remove
- set
- <c:set var="name" value="${'gareen'}" scope="request" />
- 相当于:<%request.setAttribute("name","gareen")%>
- out
- <c:out value="${name}" />
- 相当于: <%=request.getAttribute("name")%>
- remove
- <c:remove var="name" scope="request" />
- 相当于:<c:remove var="name" scope="request" />
- 注:作用域可以是pageContext, request, session, application
#### if else
- JSTL通过<c:if test=""> 进行条件判断,但是JSTL没有<c:else,所以常用的办法是在<c:if的条件里取反
- 配合if使用的还有通过empty进行为空判断
empty可以判断对象是否为null,字符串长度是否为0,集合长度是否为0
例:
```xml
<c:if test="${hp<5}">
<p>这个英雄要挂了</p>
</c:if>
<c:if test="${!(hp<5)}">
<p>这个英雄觉得自己还可以再抢救抢救</p>
</c:if>
<c:if test="${empty weapon}">
<p>没有装备武器</p>
</c:if>
choose
虽然JSTL没有提供else标签,但是提供了一个else功能的标签
1 | <c:choose> |
forEach
可以在JSP中使用for循环,但是其可读性很差。 借助JSTL的c:forEach标签,可以改善可读性
1 | //items="${stu }" 表示遍历的集合 |
fmt:formatDate 格式化日期
<fmt:formatDate value=”${now}” pattern=”yyyy-MM-dd HH:mm:ss”/>
例:
1
2<% Date now = new Date(); pageContext.setAttribute("now",now); %>
<td><mt:formatDate value="${now }" pattern="yyyyMMdd"/></td>
过滤器Filter
针对于具备多个servlet共有的系统功能提供的过滤机制
使用方法
实现接口javax.servlet.Filter
实现doFilter方法,最后写filterChain.doFilter(req.resp);
添加配置
- web.xml
- filter
- filter-name
- filter-class
- filter-mapping
- filter-name
- url-pattern
- filter
- 注解(@WebFilter(“*”)或)@WebFilter(urlPatterns={“”,””})
- web.xml
public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)sreq; HttpServletResponse resp = (HttpServletResponse)sresp; chain.doFilter(sreq, sresp); System.out.println("已进入过滤器......"); }
1
2
3
4
5
6
7
8
9
10
```xml
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>com.woniu.test.类名</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
doFilter方法的request和response可以向下转型
HttpServletRequest req = (HttpServletRequest)sreq; HttpServletResponse resp =(HttpServletResponse)sresp;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
### 设置编码
- ![mark](http://pybd8px2l.bkt.clouddn.com/blog/20190924/RbFIamVrqu52.png?imageslim)
- ![mark](http://pybd8px2l.bkt.clouddn.com/blog/20190924/CQsf4G3KVCMj.png?imageslim)
- ![mark](http://pybd8px2l.bkt.clouddn.com/blog/20190924/JoCQ5xhVJaoH.png?imageslim)
### 获取用户输入参数
- ```java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//设置编码
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;utf-8");
//获取数据
StringBuilder sb = new StringBuilder();
Map<String, String[]> parameterMap = request.getParameterMap();
for(Map.Entry<String, String[]> entry:parameterMap.entrySet()) {
sb.append(entry.getKey());
sb.append(":");
if(entry.getValue()!=null&&entry.getValue().length==1) {
sb.append(entry.getValue()[0]);
}else {
sb.append(Arrays.toString(entry.getValue()));
}
}
String uri = ((HttpServletRequest)request).getRequestURI();
System.out.println("请求"+uri+"的参数为:"+sb.toString());
chain.doFilter(request, response);
}
防重复提交
访问login.jsp,先经过过滤器,生成一个随机数,放入jsp的表单中
jsp响应返回到浏览器
先经过过滤器,过滤器验证提交的随机数是否为之前生成的token,一致就放行,并且清空
用户重复提交,先经过过滤器,过滤器验证提交随机数不符合,不放行,跳转到提示页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- ```xml
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="MainUI" method="post">
<input type="hidden" name="_anti_duplicate_token" value="${_anti_duplicate_token }"/>
请输入账号:<input type="text" name="name">
请输入密码:<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //设置编码 request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html;utf-8"); HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse resp = (HttpServletResponse)response; //获取前端传来的的参数(之前保存) String parameterToken = request.getParameter("_anti_duplicate_token"); //判断是否为第一次进入login.jsp if(parameterToken!=null) { //获取用户现在进入时的参数 Object sessionToken = req.getSession().getAttribute("_anti_duplicate_token"); //不是第一次,则判断网页保存的参数和用户进入时的参数是否相等 if(parameterToken.equals(sessionToken)) { System.out.println("两值相等"); //移除用户的参数 req.getSession().removeAttribute("_anti_duplicate_token"); chain.doFilter(request, response); return; }else { System.out.println("两值不相等"); //重复提交,跳转到页面上去 req.getRequestDispatcher("/repeateLogin").forward(request, response); } }else { System.out.println("parameterToken == null"); //是第一次进入网页login.jsp,生成token String token = UUID.randomUUID().toString(); req.getSession().setAttribute("_anti_duplicate_token", token); chain.doFilter(request, response); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
注:火狐浏览器会自动防止用户重复提交,意思就是,服务器未响应之前,用户的点击操作,不会进入过滤器(大坑)
### 登录验证
- 登录成功后,放入session标识
- 登录过滤器
- ```java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
//得到用户输入地址
String requestURI = req.getRequestURI();
//当用户输入界面为登录界面的时候,直接通过此滤器,不进行验证
//当进行登录操作时,也直接通过过滤器 if(requestURI.endsWith("index.jsp")||requestURI.endsWith("loginServlet")) {
System.out.println("requestURI.endsWith(\"index.jsp\")");
chain.doFilter(request, response);
return;
}
System.out.println(requestURI);
//判断用户登录状态
//得到用户登录状态
String attribute = (String)req.getSession().getAttribute("LoginFlag");
if(null == attribute) {
System.out.println("null == attribute");
//当过滤器发现没有登录过时,直接跳转到登录后的界面
req.getRequestDispatcher("index.jsp").forward(request, response);
return;
}
System.out.println("到这里,说明我该睡");
//到这里,说明我该睡了
chain.doFilter(request, response);
}
//注可以定义:
private static final List<String> EXCLUDE_URL_LIST =
Arrays.asList("index.jsp","login"."register.jsp");
if(EXCLUDE_URL_LIST.contains(path)){
//使用Arrays.asList将多个String转化成List集合
//这样就可以统一判断
}
上面的将资源文件也拦截了,应该将对应资源文件也放行
监听器 Listener
- javaEE中,用于处理特定事件的组件,在特定的系统事件发生时会调用相应的监听来处理
- 事件有:应用启动、销毁、请求创建、销毁等等
- 事件列表
- ServletContext相关
- ServletContextListener => 生命周期监听、创建、销毁
- ServletContextAttributeListener => 属性监听 属性创建、销毁、修改
- HttpSession相关
- HttpSessionListener =>生命周期 生命周期监听、创建、销毁
- HttpSessionAttributeListener => 属性监听 属性创建、销毁、修改
- HttpSessionActivationListener => 会话活化监听器
- HttpSessionBindingListener => 会话绑定监听器
- ServletRequest相关
- ServletRequestListener => 生命周期监听、创建、销毁
- ServletRequestAttributeListener => 属性监听 属性创建、销毁、修改
- 内存=>硬盘(钝化) 硬盘=>内存(活化)
- ServletContext生命周期时间:ServletContextEvent
- ServletContext相关
更加合理的方式:
1 | <base href="http://localhost:8080/emall/" />可以修改默认相对的路径 |
实例
未用注解
xml文件里
1
2
3<listener>
<listner-class>包名.类名</listner-class>
</listner>
使用注解
@WebListener public class AppLifecycleListener implements ServletContextListener{ @Override public void contextDestroyed(ServletContextEvent arg0) { System.out.println("应用关闭"); } @Override public void contextInitialized(ServletContextEvent arg0) { System.out.println("应用启动"); } }
1
2
3
4
5
6
### 获得访问次数及在线人数
- ```xml
总访问次数:<a>${inline_num }</a><br/>
当前在线人数:<a>${online_num }</a>
1 | //以下是实现统计在线人数的主要代码,有30分钟延迟销毁在线人数bug |
数据库的下划线问题解决
具体出现原因:数据库的字段名使用下划线,造成beanListHandler无法成功读取,可以通过加参数的方式解决,如下所示
RowProcessor pro = new BasicRowProcessor(new GenerousBeanProcessor()); BeanListHandler<Product> beanListHandler = new BeanListHandler<product>(Product.class,pro);