项目开始
准备工作
写一个db.properties配置文件,并在lib文件夹下面导入各种需要使用的jar包
db.properties配置文件
# 连接数据库的四大组件
driverClassName=com.mysql.jdbc.Driver
username=root
password=root
url=jdbc:mysql:///exam?characterEncoding=utf8
# 参数
initialSize=5
maxActive=50
maxWait=3000
#注意事项
#driverClassName,username,password基本都是固定的
#url的 exam是数据库名称对于不同的数据库是不一样的
1.导入工具包
在tools包里面创建DBUtil类
DBUtil工具类代码
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
//这是一个工具类,使用之前需要先在lib中导入各种jar包
public class DBUtil {
private static DataSource pool; //目的是建立一个私有的连接池对象
static { //静态代码块一般用于初始化数据
Properties pro = new Properties(); //用来读取db.properties配置文件的
//读取db.properties配置文件,为一个流
InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
try {
pro.load(is); //把文件里面的数据加载到项目之中
pool = DruidDataSourceFactory.createDataSource(pro); //为连接池对象赋值,用德鲁伊工厂来创建
} catch (Exception e) {
e.printStackTrace();
}
}
// 提供数据源
public static DataSource getDataSource() { //目的是为了获取连接池对象
return pool;
}
}
2.连接数据库的步骤
我们得知道数据库里面的表连接java是通过一个javaBean类对象来连接的,这个里面的属性就是表里面的字段顺序都一模一样,生成全参,无参,set和get还有toString.
javaBean类对象代码
这里只书写私有属性,对应的全参无参,get,set,还有toString自动补全
private Integer id;
private String name;
private String address;
private String source;
private String phone;
private String level;
写了这个之后我们就可以去dao包里面创建一个连接数据库的接口和接口的实现类,接口是用来定义方法的格式和规范,我们对于数据库了的增删该查都在接口的实现类里面进行的
接口代码
public interface CustomerDao {
// 查询所有客户信息
List<Customer> queryAll() throws SQLException;
// 添加客户信息
void addCustomer(Customer customer);
// 根据id值删除客户信息
void removeCustomer(int c_id);
// 根据id值查询客户信息
Customer queryCustomerById(int c_id);
// 根据id值修改客户信息
void modifyCustomer(Customer customer);
}
接口实现类代码
import com.zhiyou100.exam.pojo.Customer;
import com.zhiyou100.exam.tools.DBUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
public class CustomerDaoImpl implements CustomerDao{
//使用DBUtil根据列连接数据库,链接之后我们接下来只需要些sql语言进行数据库操作就可以了
//这是工具类DBUtil里面的方法,目的是获得一个连接池对象.执行后面的对数据库的增删改查工作
QueryRunner qr=new QueryRunner(DBUtil.getDataSource());
//这是查询数据库表中所有的数据的方法
@Override
public List<Customer> queryAll(){
//先写一个sql语句因为之前已经连接好了数据库这里可以直接用sql语句进行操作
String sql="select * from customer";
//把查询出来的数据放在根据表字段创建好的类对象里面
List<Customer> list = null;
try {
//开始查询运用之前获得的连接池对象.这个有异常需要获取,不能抛出
//BeanListHandler表示查询出来的是一个集合
list = qr.query(sql, new BeanListHandler<Customer>(Customer.class));
return list;//返回我们查询到的list集合对象
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//这是增加的方法
@Override
public void addCustomer(Customer customer) {
//先写一个sql语句因为之前已经连接好了数据库这里可以直接用sql语句进行操作
String sql="insert into customer value(null,?,?,?,?,?)";//这里面五个?表示需要赋值五个,null表示主键会自增所以不用写
try {
//开始查询运用之前获得的连接池对象.这个有异常需要获取,不能抛出,返回受影响的行数.
int count = qr.update(sql, customer.getName(), customer.getAddress(), customer.getSource(), customer.getPhone(), customer.getLevel());
//判断受影响的行数是否大于0,大于0就表示成功
if (count>0){
System.out.println("添加数据成功");
}else {
System.out.println("添加数据失败");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//这是根据id删除的方法
@Override
public void removeCustomer(int c_id) {
//提前预备一个sql语句,之后会使用到
String sql = "delete from customer where id = ?";
try {
//qr是我们上面得到的连接池对象,返回的是受影响的行数
int count = qr.update(sql, c_id);
if (count > 0) {
System.out.println("数据删除成功!");
} else {
System.out.println("数据删除失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
//根据ID查询得到对象
@Override
public Customer queryCustomerById(int c_id) {
//提前准备根骨id查询信息的数据
String sql = "select * from customer where id = ?";
try {
//BeanHandler表示查询出来的是单个对象
Customer customer = qr.query(sql, new BeanHandler<>(Customer.class), c_id);
return customer;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void modifyCustomer(Customer customer) {
//修改数据
String sql = "update customer set name = ?,address = ?,source =?,phone = ?,level = ? where id = ?";
try {
//返回受影响的行数,这里传入的数据就对应上面的?号,就是我们改变之后的数据
int count = qr.update(sql, customer.getName(), customer.getAddress(), customer.getSource(), customer.getPhone()
, customer.getLevel(), customer.getId());
if (count > 0) {
System.out.println("数据修改成功!");
} else {
System.out.println("数据修改失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
值得注意的是,查的时候根据返回的数据不同我们会用到不同的Bean,请注意观察:
//BeanHandler表示查询出来的是单个对象
//BeanListHandler表示查询出来的是一个集合
3.Service层
这个层里面其实和dao层结构几乎一模一样,是在结构很复杂的时候才会使用使得逻辑更为清晰,
Service接口层代码
import com.zhiyou100.exam.pojo.Customer;
import java.util.List;
public interface CustomerService {
// 查询所有客户信息
List<Customer> queryAll();
// 添加客户信息
void addCustomer(Customer customer);
// 根据id值删除客户信息
void removeCustomer(int c_id);
// 根据id值查询客户信息
Customer queryCustomerById(int c_id);
// 根据id值修改客户信息
void modifyCustomerById(Customer customer);
}
Service实现层代码
里面回调用dao实现类里面的对应的方法。
import com.zhiyou100.exam.dao.CustomerDao;
import com.zhiyou100.exam.dao.CustomerDaoImpl;
import com.zhiyou100.exam.pojo.Customer;
import java.util.List;
/**
* @author: admin
* @date: 2021/1/15
*/
public class CustomerServiceImpl implements CustomerService {
// 属性注入
private CustomerDao cd = new CustomerDaoImpl();
@Override
public List<Customer> queryAll() {
return cd.queryAll();
}
@Override
public void addCustomer(Customer customer) {
cd.addCustomer(customer);
}
@Override
public void removeCustomer(int c_id) {
cd.removeCustomer(c_id);
}
@Override
public Customer queryCustomerById(int c_id) {
return cd.queryCustomerById(c_id);
}
@Override
public void modifyCustomerById(Customer customer) {
cd.modifyCustomer(customer);
}
}
4.controller层
这一层里面都是一些Swervlrt类,作用就是接收jsp或者html页面提交上来的数据和请求(比如增删改查),把这些数据和请求,通过方法直接交给dao的实现层去实现(没有service层的情况),在dao的实现曾接收数据并完成请求之后,通过return方法把执行完毕的数据返回给Servlet层,Servlet层再把数据通过转发或者重定向来完成结果向前端页面的传送。
在含有service层的时候,我们是通过在Servlrt类里面的service实现类对象,调用里卖弄的方法,就会映射到dao实现类对象里面的方法-----》这就是三层架构
三层架构图解
增加Servlet代码
import com.zhiyou100.exam.pojo.Customer;
import com.zhiyou100.exam.service.CustomerService;
import com.zhiyou100.exam.service.CustomerServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
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 java.io.IOException;
//这是用域增加数据的方法
@WebServlet("/add") //这是注解,双引号里面的数据和jsp页面。里面form表单的action后面的数据一样,所以表单提交的数据才能准确的传到我们对于的Servlet层
public class AddServlet extends HttpServlet {
// 关联service层
// 属性注入,因为我们Servlet层是要把接收到的数据传到Dao的实现,然而因为我们要使用三层架构,所以我们是创建的Service实现类的对象
// Service实现类的对象就对应了dao实现类的对象,就相当于调用dao里面方法
private CustomerService cs = new CustomerServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); //设置字符编码集避免乱码
response.setContentType("text/html;charset=utf-8"); //设置字符编码集避免乱码
Customer customer = new Customer(); //创建一个新的数据库表单映射类对象
try {
//固定方法BeanUtils.populate()把从form表单接收到的数据,打包成数据库表单映射类的对象:一步到位
BeanUtils.populate(customer, request.getParameterMap());
} catch (Exception e) {
e.printStackTrace();
}
// 调用service层的方法,实际就是关联的dao曾里面的添加数据方法
cs.addCustomer(customer);
// 跳转到查询所有信息的Servlet中----》这是重定向的方法,表示执行完全之后跳转到显示全部数据的页面
// request.getContextPath()+"/queryAll"是路径字符串的拼接---会的到绝对路径有效避免出错
response.sendRedirect(request.getContextPath()+"/queryAll");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
后面的实现类和addServlet类解释都类似不再多做解释
DeleteServlet类
import com.zhiyou100.exam.service.CustomerService;
import com.zhiyou100.exam.service.CustomerServiceImpl;
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 java.io.IOException;
@WebServlet("/delete")
public class DeleteServlet extends HttpServlet {
// 属性注入
private CustomerService cs = new CustomerServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String id = request.getParameter("id");//表示获得删除用户的id
int c_id = Integer.parseInt(id);//把字符串的id转化为int类型的id
cs.removeCustomer(c_id);
// 跳转到查询所有服务中
response.sendRedirect(request.getContextPath()+"/queryAll");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
QueryAllServlet类
import com.zhiyou100.exam.pojo.Customer;
import com.zhiyou100.exam.service.CustomerService;
import com.zhiyou100.exam.service.CustomerServiceImpl;
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 java.io.IOException;
import java.util.List;
@WebServlet("/queryAll")
public class QueryAllServlet extends HttpServlet {
// 属性注入
private CustomerService cs = new CustomerServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 调用service层的方法
List<Customer> list = cs.queryAll();
// 往域中存储值,因为我们后面要循环输出这个list集合里面的数据库表映射类对象,所以要放在域里面
request.getSession().setAttribute("list", list);
// 资源跳转---这是页面之间的跳转
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
UpdateServlet类
import com.zhiyou100.exam.pojo.Customer;
import com.zhiyou100.exam.service.CustomerService;
import com.zhiyou100.exam.service.CustomerServiceImpl;
import org.apache.commons.beanutils.BeanUtils;
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 java.io.IOException;
import java.lang.reflect.InvocationTargetException;
@WebServlet("/update")
public class UpdateServlet extends HttpServlet {
// 属性注入
private CustomerService cs = new CustomerServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
Customer customer = new Customer();
try {
BeanUtils.populate(customer, request.getParameterMap());
} catch (Exception e) {
e.printStackTrace();
}
// 修改客户信息
cs.modifyCustomerById(customer);
// 跳转到查询所有客户信息服务中 /queryAll
response.sendRedirect(request.getContextPath() + "/queryAll");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String id = request.getParameter("id");
int c_id = Integer.parseInt(id);
// 根据id值查询对应的客户信息
Customer customer = cs.queryCustomerById(c_id);
// 回传数据,customer,就会保存在域里面
request.setAttribute("customer", customer);
//带着域里面的数据回传到update修改页面,所以修改页面能使用customer对象
request.getRequestDispatcher("/update.jsp").forward(request, response);
}
}
注意:我们这里写在doGet还是doPost是from表单里面method方法是get还是post决定的
页面代码
add.jsp代码
<%--这是设置页面的编码字符集,不设置就会出现字符乱码现象--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>添加页面</title>
</head>
<body>
<%-- --%>
<form action="${pageContext.request.contextPath}/add" method="post">
<%--这些就是一些框框--%>
<%--name:属性---->试我们在Servlet里面的获取表单数据时候小括号里面的数据 --%>
客户名称:<input type="text" name="name" >
客户地址:<input type="text" name="address" ><br>
客户来源:<input type="text" name="source" >
客户电话:<input type="text" name="phone" ><br>
客户级别:<input type="text" name="level" ><br>
<%--这就是保存能把数据提交到action相同的Servlet里面--%>
<input type="submit" value="保存">
</form>
</body>
</html>
index.jsp代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--设置字符编码集--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%--这里映入标签库是 --%>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<table border="1" align="center" width="600px">
<tr>
<td>客户名称</td>
<td>客户地址</td>
<td>客户来源</td>
<td>客户电话</td>
<td>客户等级</td>
<td>修改操作</td>
<td>删除操作</td>
</tr>
<%--c标签,就是必须导入对应的包上面还需要有对应的taglib--%>
<%-- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> --%>
<%-- 这里表示循环遍历 items--->需要遍历的集合 var--->每次循环取出的元素起一个变量名 varStatus--->表示当前状态 --%>
<c:forEach items="${list}" var="customer" varStatus="status">
<tr>
<%-- 运用对象名.属性名,保证每次下一列的数据都不一样,免得造成查询出来的全是相同的数据 --%>
<td>${customer.name}</td>
<td>${customer.address}</td>
<td>${customer.source}</td>
<td>${customer.phone}</td>
<td>${customer.level}</td>
<td>
<%-- 表示拼接获得绝对路径,就是跳到全面免路径的时候带入的id值是多少,也就是为什么点击那个删除就会修改哪一条数据 --%>
<a href="${pageContext.request.contextPath}/update?id=${customer.id}">修改</a>
</td>
<td>
<%-- 表示拼接获得绝对路径,就是跳到全面免路径的时候带入的id值是多少,也就是为什么点击那个删除就会删除哪一条数据 --%>
<a href="${pageContext.request.contextPath}/delete?id=${customer.id}">删除</a>
</td>
</tr>
</c:forEach>
<tr>
<%-- 表示拼接获得绝对路径 --%>
<td colspan="7"><a href="${pageContext.request.contextPath}/add.jsp">添加用户信息</a></td>
</tr>
</table>
</body>
</html>
update.jsp代码演示
<%--编码字符集--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改页面</title>
</head>
<body>
<%-- 获得绝对路径,之后的Servlet的注解里面的数据是相同的 --%>
<form action="${pageContext.request.contextPath}/update" method="post">
<%-- name:在Servlet里面提取数据里面的就是对应的字符串 --%>
<%-- value:就是展示我们之前相对于的数据,在我们点击修改之后,就会跳到这个页面,我们的数据也是展示的之前的数据 --%>
<%-- 至于后面的name也就是我们提交上去的数据需要获得,就会用到这个name值 --%>
<%-- 这里面能使用customer对象是因为我们在修改的Servlet里面把这个从数据库查询出来的对象,放到域里面并回传给这个页面了 --%>
客户名称:<input type="text" value="${customer.name}" name="name" >
客户地址:<input type="text" value="${customer.address}" name="address" ><br>
客户来源:<input type="text" value="${customer.source}" name="source" >
客户电话:<input type="text" value="${customer.phone}" name="phone" ><br>
客户级别:<input type="text" value="${customer.level}" name="level" ><br>
<%--隐藏的id值--%>
<input type="hidden" name="id" value="${customer.id}">
<input type="submit" value="更新">
</form>
</body>
</html>