回顾
在上篇文章中,讲述了如何建立一个简单的JavaWeb项目,并使用Servlet实现简单的前后端交互
但是还是很不规范的,而且数据也是写死的,今天来集成使用MySQL数据库,从数据库中获取验证数据
项目分层
项目分层的目的是为了增强代码的可维护性,在本次的项目中,分为以下几层
DAO层 操作数据库,建立与数据库的连接,对数据库进行增删改查
DAO层中有impl层,该层主要就是实现DAO层定义的接口中的方法
Entity(Bean)层 实体层,建立各种对象的实体,一般只有属性
Service层 处理业务逻辑,从DAO层获取到数据库增删改查的数据
Service层中有impl层,该层主要就是实现Service层定义的接口中的方法
Servlet层 将Service层处理返回的结果打包好,发送给前端的页面
utils层 提供各种工具类
(个人理解)
分层架构理解
一个项目启动,可以分解为以下步骤
准备工作
Dbutils
在这里会使用一个工具,作用:将JDBC的返回映射成一个对象
主要是封装了JDBC的代码,简化dao层的操作
ORM:Object Relational Mapping
对象关系映射
实体和表示有关系的。
JDBC:
参数、SQL、结果手动处理
Dbutils:半ORM、Mybatis
参数、SQL、自动映射
Hibernate:ORM
啥都不要写
XX.save(new User(“王麻子”,19,11));
需要下载相应的jar包并添加依赖,添加依赖具体步骤参考
https://blog.csdn.net/h1025372645/article/details/89406819
配置文件
在src目录下新建.xml文件,为Dbutils进行配置
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb01</property>
<property name="user">root</property>
<property name="password">123</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>
开始项目
数据库表的建立
create table mydb01.tb_user(
userId varchar(50),
userName varchar(50),
password varchar(50)
);
insert into mydb01.tb_user value ("1","zs","123456");
insert into mydb01.tb_user value ("2","ls","123456");
Entity层
建立操作对象,User类
package com.entity;
public class User {
private String userId;
private String userName;
private String password;
public User() {
}
public User(String userId, String userName, String password) {
this.userId = userId;
this.userName = userName;
this.password = password;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"userId='" + userId + '\'' +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
}
DAO层
建立一个接口,并在impl中实现该接口
引入MySQL包并使用可参考以下链接
https://blog.csdn.net/h1025372645/article/details/89191301
接口:
package com.dao;
import com.entity.User;
import java.util.List;
public interface UserDao {
public User getUserById(String id);
}
实现接口的类,查找对应用户,并返回用户数据:
import com.dao.UserDao;
import com.entity.User;
import com.utils.C3p0Utils;
import com.utils.JDBCUtils;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
public class UserDaoImpl implements UserDao {
@Override
public User getUserById(String id) {
Connection connection =null;
PreparedStatement statement = null;
User user = null;
try {
connection = C3p0Utils.getConnection();
String sql = "select * from tb_user where userId= ?";
Object[] ob = {id};
QueryRunner queryRunner = new QueryRunner();
user = queryRunner.query(connection, sql, new BeanHandler<User>(User.class),ob);
} catch (SQLException e) {
e.printStackTrace();
}
finally {
try {
DbUtils.close(connection);
} catch (SQLException e) {
e.printStackTrace();
}
}
return user;
}
}
Service层
接口:
package com.service;
import com.entity.User;
import java.util.HashMap;
import java.util.List;
public interface UserService {
public HashMap<String,Object> login (String userId,String password);
}
实现接口,处理Servlet传入的数据:
package com.service.impl;
import com.dao.UserDao;
import com.dao.impl.UserDaoImpl;
import com.entity.User;
import com.service.UserService;
import java.util.HashMap;
import java.util.List;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public HashMap<String, Object> login(String userId, String password) {
User user = userDao.getUserById(userId);
HashMap<String, Object> resultMap = new HashMap<>();
if(user ==null){
resultMap.put("code","1");
resultMap.put("msg","用户不存在");
}else if(!user.getPassword().equals(password)) {
resultMap.put("code", "2");
resultMap.put("msg", "密码错误");
}else{
resultMap.put("code", "0");
resultMap.put("msg", "登录成功");
resultMap.put("data", user);
}
return resultMap;
}
}
Servlet层
建立servlet,获取前端传入数据
package com.servlet;
import com.alibaba.fastjson.JSONObject;
import com.service.UserService;
import com.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
public class LoginServlet extends HttpServlet {
UserService userService = new UserServiceImpl();
//当有POST请求时,该函数会执行
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doPost........"); //控制台打印
}
//当有GET请求时,该函数会执行
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet........"); //控制台打印
String userName = request.getParameter("userName");
String password = request.getParameter("password");
System.out.println(userName+"-->"+password);
response.setContentType("text/html;charset=utf-8");
HashMap<String, Object> login = userService.login(userName, password);
PrintWriter writer = response.getWriter();
writer.print(JSONObject.toJSONString(login));
writer.flush();
writer.close();
}
}
前端jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Servlet+MySQL</title>
</head>
<body>
<div>
用户名:<input type="text" name = "userName" id="userName"><br>
密 码:<input type="password" name="password" id="password"><br>
<input type="button" value="提交" id="btn1">
</div>
<div id="data">
</div>
</body>
<script src="lib/jquery-1.9.1.min.js"></script>
<script>
$("#btn1").click(function () {
var userName = $("#userName").val();
var password = $("#password").val();
$.ajax({
url:"loginServlet",
method:"GET",
data:{
userName:userName,
password:password
},
success:function (result) {
result = result || "{}";
var resultObj = JSON.parse(result);
var code = resultObj.code;
if(code==0){
var msg = resultObj.msg;
location.href = "success.jsp";//页面跳转
alert(msg);
}
else{
var msg = resultObj.msg;
alert(msg);
}
},
error:function (result) {
console.log(result);
}
});
});
</script>
</html>
此时运行项目,就可以从数据库中读取并验证数据
源码:提取码:rlhi
连接池
介绍
目前JDBC做法,每次查询、插入数据之前,需要建立连接、数据处理完成之后,有关闭连接。打开连接和关闭连接非常耗费资源,性能。
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
常见的连接池工具框架
1 dbcp
dbcp可能是使用最多的开源连接池,原因大概是因为配置方便,而且很多开源和tomcat应用例子都是使用的这个连接池吧。
这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。这个连接池的配置参见附件压缩包中的:dbcp.xml
使用评价:在具体项目应用中,发现此连接池的持续运行的稳定性还是可以,不过速度稍慢,在大并发量的压力下稳定性
有所下降,此外不提供连接池监控
2 c3p0
c3p0是另外一个开源的连接池,在业界也是比较有名的,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。
这个连接池的配置参见附件压缩包中的:c3p0.xml。
使用评价:在具体项目应用中,发现此连接池的持续运行的稳定性相当不错,在大并发量的压力下稳定性也有一定保证,
此外不提供连接池监控。
3 proxool
proxool这个连接池可能用到的人比较少,但也有一定知名度,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。
这个连接池的配置参见附件压缩包中的:proxool.xml。
使用评价:在具体项目应用中,发现此连接池的持续运行的稳定性有一定问题,有一个需要长时间跑批的任务场景任务,同样的代码
在另外2个开源连接池中成功结束,但在proxool中出现异常退出。
但是proxool有一个优势–连接池监控,这是个很诱人的东西,大概的配置方式就是在web.xml中添加如下定义:
<servlet>
<servlet-name>admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>admin</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
并在应用启动后访问:http://localhost:8080/myapp/admin这个url即可监控
不过proxool本身的包在监测使用中会有编码问题,附件中有一个
解决此问题的包,参见附件压缩包中的:proxool-0.9.0RC3.jar。另外需要jdk1.5以上的环境
数据库连接池详解见下链接
http://blog.songchunmin.com/522.html
Jsq基础知识
Java server page缩写,在JSP里面上可以嵌入java 代码。
它实现了Html语法中的java扩展
JSP三大指令
指令:指导页面编译和加载
Page指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
contentType:页面的类型和字符编码
language:JSP脚本中嵌套的是什么语言
pageEncoding:当前JSP文件的本身编码
import:导入Java的包
errorPage:当前页面如果出错,跳转哪个页面
isErrorPage="true":当前页面是一个处理错误的页面
include指令
页面包含指令,可以将一个JSP页面包含到另外一个JSP页面中
格式:
作用:
(1)不用写重复的代码
(2)代码容易维护。
Taglib指令
在JSP页面中引入标签库(JSTL标签、Struts2标签库)
<%@ taglib prefix="前缀" uri="标签库地址" %>
嵌入Java代码
输出
<%=Java变量或者表达式%> :用户输出在页面上
注释
<%.......%>中使用 // 注释
jsp中使用<%-- --%> 注释