注:这是视频学习笔记
尝试做一个运行示意图:
简单的生鲜管理系统
一、考察的知识点
(1)servlet知识
(2)cookie和session的使用
(3)jsp的三大指令,四大作用域,以及jstl标签
(4)过滤器filter的简单使用
(5)管理类的使用
(6)请求转发与重定向
(7)数据库的CRUD操作
(8)用户注册与登录,账号保存
完整的目录文件(左是src目录,右是web目录)
二、详细过程
1.准备工作:
(1)安装JDK-8u71版
(2)下载安装apache-tomcat-8.5.60
(3)下载安装idea,本次实验使用的是IntelliJ IDEA 2018.1.6
(4)下载mysql-connector-java-8.0.14.jar(数据库连接jar包)
(5)下载安装jakarta-taglibs-standard-1.1.2(标签库)
(6)下载安装MySQL8.0版
(7)下载安装数据库的操作工具:Navicat
所有所需文件
2.创建项目和配置项目
(1)创建项目和配置项目
aa.已经打开之前的项目的情况下:file ------> new ------> project
bb.未打开项目的情况下直接点击:create new Project
进入到如下界面:
注意:如果在安装intellij idea 时已经配置了jdk,就不用再配置(要配置也可以,我这里的图片就是重新又配置了一遍,所以有(1)这样的显示),Tomcat也一样,java EE的版本应该与idea以及jdk和Tomcat相匹配
cc.项目以及model的名称和保存位置设置
dd.点击finish进入到项目界面(左图),然后创建对应的项目结构,同时把素材文件复制到对应的文件目录之下,(将c3p0-config.xml)配置文件复制粘贴到src目录下(与com.study同级目录)
ee.配置项目以及配置文件的修改
说明:图1,项目结构图;图2,标签库配置;图3,数据库连接配置;图4-13,Tomcat server服务器配置过程(首次配置过程)
(2)创建数据库
aa.打开Navicat,连接mysql8.0
bb.新建数据库:fresh10,新建两张表:user和category
cc.给category添加数据
3.后端代码编写
(1)bean部分代码编写:
<1> User类:私有数据域:private int id/String name/String password/String email,创建其getter和setter方法即可
<2> User类:私有数据域:private int id/String name/String password/String email,创建其getter和setter方法即可
<3> User类:私有数据域:private int id/String name/String password/String email,创建其getter和setter方法即可
(2)管理类代码编写
package com.study.web;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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;
import java.lang.reflect.Method;
/**
* 管理代码工具类
*/
@WebServlet(name = "BaseServlet")
public class BaseServlet extends HttpServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
try {
//统一设置请求页面的编码格式,防止乱码
req.setCharacterEncoding("utf-8");
//1.获取前端页面名为method的值
String method = req.getParameter("method");
//2.获取字节码
Class clazz=this.getClass();
//3.获取对象字节码的方法
Method method1 = clazz.getMethod(method, HttpServletRequest.class, HttpServletResponse.class);
//4.执行方法
method1.invoke(this,req,res);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
(3)用户注册与登录代码编写(执行顺序依次为:UserServlet---> UserService---> UserDao)
<1> UserServlet类
package com.study.web;
import com.study.bean.User;
import com.study.service.UserService;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.Map;
/**
* 用户登陆注册类
* /user表示表单提交到后端的Servlet类
* 该类继承管理类BaseServlet,通过父类调用其方法
*/
@WebServlet(name = "UserServlet",urlPatterns = "/user")
public class UserServlet extends BaseServlet {
public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//获取前端相关参数map集合
Map<String, String[]> parameterMap = request.getParameterMap();
User user=new User();
//封装user
BeanUtils.populate(user,parameterMap);
//调用userService的查找用户登陆方法,并返回结果user
UserService userService=new UserService();
user=userService.queryLoginUser(user);
if(user !=null){//用户不为空,说明用户查找到了,可以进行登陆操作
//获取记住密码的参数值
String remember = request.getParameter("remember");
if(remember !=null && "yes".equals(remember)){//勾选表示记住账号,保存用户名和密码
//使用cookie保存账号信息
Cookie nameCookie =new Cookie("name",user.getName());
Cookie passwordCookie = new Cookie("password",user.getPassword());
//设置cookie保存时间
nameCookie.setMaxAge(60*20);
passwordCookie.setMaxAge(60*20);
//发送给客户端浏览器
response.addCookie(nameCookie);
response.addCookie(passwordCookie);
}
//将user封装信息设置到session中,用于过滤检查品类操作页面是否是用户在登陆的情况下操作
request.getSession().setAttribute("user",user);
//重定向到品类列表页面(category是表示提交到CategoryServlet,method=getCategoryList表示执行CategoryServlet下的getCategoryList方法
response.sendRedirect(request.getContextPath()+"/category?method=getCategoryList");
}else{
//设置响应客户端浏览器显示内容的编码格式
response.setContentType("text/html;charset=utf-8");
//登陆失败显示提示信息
response.getWriter().write("登录失败!");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//获取封装信息
Map<String, String[]> parameterMap = request.getParameterMap();
User user=new User();
BeanUtils.populate(user,parameterMap);
//调用实现方法
UserService userService=new UserService();
boolean register=userService.registerUser(user);
if(register){//注册成功
//重定向到登陆页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
}else{
//设置响应客户端浏览器显示内容的编码格式
response.setContentType("text/html;charset=utf-8");
//注册失败显示登陆信息
response.getWriter().write("注册失败!");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
<2> UserService类
package com.study.service;
import com.study.bean.User;
import com.study.dao.UserDao;
import java.sql.SQLException;
public class UserService {
/**
* 查找登陆用户是否存在,存在返回登陆用户封装信息
* @param user 封装登陆用户信息
* @return 返回查找结果user
* @throws SQLException
*/
public User queryLoginUser(User user) throws SQLException {
UserDao userDao=new UserDao();
return userDao.queryLoginUser(user);
}
/**
* 注册用户
* @param user 封装登陆用户信息
* @return 返回注册结果:布尔值
* @throws SQLException
*/
public boolean registerUser(User user) throws SQLException {
UserDao userDao=new UserDao();
//获取注册用户信息是否已经注册过
boolean checkUser=userDao.checkUser(user);
if(checkUser){
//没有注册过,调用注册用户方法并返回注册结果,布尔值
return userDao.registerUser(user);
}
//用户已经注册返回布尔值false
return false;
}
}
<3> UserDao类
package com.study.dao;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.study.bean.User;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.sql.SQLException;
public class UserDao {
/**
* 查找登陆用户,并返回结果
* @param user
* @return 返回查找结果
* @throws SQLException
*/
public User queryLoginUser(User user) throws SQLException {
//连接数据库
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//创建数据库操作类对象
QueryRunner queryRunner = new QueryRunner(dataSource);
//数据查找语句
String sql="select * from user where name=? and password=?";
//调用数据库操作类查找单个类信息的方法并返回查找结果,user或null
return queryRunner.query(sql,new BeanHandler<User>(User.class),user.getName(),user.getPassword());
}
/**
* 检查注册用户名是否已经注册过并返回结果布尔值
* @param user
* @return
* @throws SQLException
*/
public boolean checkUser(User user) throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql="select * from user where name=?";
User query = queryRunner.query(sql, new BeanHandler<User>(User.class), user.getName());
//三元表达式:如果用户为空则没有注册过,返回true,否则返回false
return query == null ? true : false;
}
/**
* 注册用户并返回注册结果布尔值
* @param user
* @return
* @throws SQLException
*/
public boolean registerUser(User user) throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql="insert into user values(null,?,?,?)";
//调用数据库操作类的更新方法并得到一个int值的结果,大于0表示数据添加成功,否则失败
int register = queryRunner.update(sql, user.getName(), user.getPassword(), user.getEmail());
return register > 0 ? true : false;
}
}
(4)生鲜类代码编写
<1> CategoryServlet类:
package com.study.web;
import com.study.bean.Category;
import com.study.bean.Page;
import com.study.service.CategoryService;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.Date;
import java.util.Map;
@WebServlet(name = "CategoryServlet",urlPatterns = "/category")
public class CategoryServlet extends BaseServlet {
/**
* 获取显示列表信息并转发到显示列表
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void getCategoryList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
int currentPage=1;//设置当前页初始值是1
int currentCount=10;//设置当前页总数目初始值是10
//分别获取前端当前页和当前页总数目的String值
String s1=request.getParameter("currentPage");
String s2=request.getParameter("currentCount");
if(s1 !=null) {//表示获取得到
currentPage = Integer.parseInt(s1);//转为int值
if (currentPage == 0) {
currentPage = 1;//设置当前页初始值是1
}
}
if(s2 !=null) {//表示获取得到
currentCount = Integer.parseInt(s2);//转为int值
if (currentCount == 0) {
currentCount = 10;//设置当前页总数目初始值是10
}
}
//创建CategoryService对象调用获取页面品类列表封装对象信息
CategoryService categoryService=new CategoryService();
Page page=categoryService.getPageCategory(currentPage,currentCount);
if(page !=null) {//页面信息不为空
request.setAttribute("page", page);//设置到request域中,这样在对应的请求转发页面就可以获取该信息
}
//将获取的页面信息转发到category-list.jsp页面(jsp实质上是Servelet类)
request.getRequestDispatcher(request.getContextPath()+"/category-list.jsp").forward(request,response);
}catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 添加生鲜品类
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void addCategory(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Map<String, String[]> parameterMap = request.getParameterMap();
Category category=new Category();
BeanUtils.populate(category,parameterMap);
category.setCreatetime(new Date());
CategoryService categoryService=new CategoryService();
boolean add=categoryService.addCategory(category);
if(add){
response.setStatus(201);//表示添加成功,重定向到生鲜列表页面
response.sendRedirect(request.getContextPath()+"/category?method=getCategoryList");
}else{
response.setStatus(600);//表示添加失败,重定向到本页
response.sendRedirect(request.getContextPath()+"/category-add.jsp");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 修改生鲜品类
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void updateCategory(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Map<String, String[]> parameterMap = request.getParameterMap();
Category category=new Category();
BeanUtils.populate(category,parameterMap);
category.setCreatetime(new Date());
CategoryService categoryService=new CategoryService();
boolean update=categoryService.updateCategory(category);
if(update){
response.setStatus(201);//表示更新成功,重定向到生鲜列表页面
response.sendRedirect(request.getContextPath()+"/category?method=getCategoryList");
}else{
response.setStatus(600);//表示更新失败,重定向到本页
response.sendRedirect(request.getContextPath()+"/category-update.jsp");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 删除生鲜品类
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void deleteCategory(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Map<String, String[]> parameterMap = request.getParameterMap();
Category category=new Category();
BeanUtils.populate(category,parameterMap);
CategoryService categoryService=new CategoryService();
boolean delete=categoryService.deleteCategory(category);
if(delete){//表示删除成功,重定向到生鲜列表页面
response.sendRedirect(request.getContextPath()+"/category?method=getCategoryList");
}else{//表示删除失败,显示提示信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("删除失败!");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
<2> CategoryService类:
package com.study.service;
import com.study.bean.Category;
import com.study.bean.Page;
import com.study.dao.CategoryDao;
import java.sql.SQLException;
import java.util.List;
public class CategoryService {
public Page getPageCategory(int currentPage, int currentCount) throws SQLException {
CategoryDao categoryDao=new CategoryDao();
int totalCount=categoryDao.queryCount();//获取生鲜品类总数目
int totalPage=(int)Math.ceil(1.0*totalCount/currentCount);//获取生鲜品类总页数
int startPosition=(currentPage-1)*currentCount;//获取每一页生鲜品类的起始位置(不包括该数)
List<Category> categories=categoryDao.queryPageCategoryList(startPosition,currentCount);//获取指定范围的生鲜品类的集合
//封装到page对象中
Page page=new Page();
page.setCurrentPage(currentPage);
page.setTotalPage(totalPage);
page.setCurrentCount(currentCount);
page.setTotalCount(totalCount);
page.setList(categories);
return page;
}
public boolean addCategory(Category category) throws SQLException {
//添加生鲜品类
CategoryDao categoryDao=new CategoryDao();
return categoryDao.addCategory(category);
}
public boolean updateCategory(Category category) throws SQLException {
//修改生鲜品类
CategoryDao categoryDao=new CategoryDao();
return categoryDao.updateCategory(category);
}
public boolean deleteCategory(Category category) throws SQLException {
//删除生鲜品类
CategoryDao categoryDao=new CategoryDao();
return categoryDao.deleteCategory(category);
}
}
<3> CategoryDao类:
package com.study.dao;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.study.bean.Category;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.SQLException;
import java.util.List;
public class CategoryDao {
/**
* 查找生鲜品类总数目
* @return 返回一个int值
* @throws SQLException
*/
public int queryCount() throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql="select count(*) from category";
Long query = queryRunner.query(sql, new ScalarHandler<>());
return query.intValue();
}
/**
* 查找指定范围生鲜品类集合
* @return 返回一个生鲜品类对象集合
* @throws SQLException
*/
public List<Category> queryPageCategoryList(int startPosition, int currentCount) throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql="select * from category limit ?,?";
return queryRunner.query(sql, new BeanListHandler<Category>(Category.class),startPosition,currentCount);
}
/**
* 根添加生鲜品类
* @return 返回一个布尔值,表示是否添加成功
* @throws SQLException
*/
public boolean addCategory(Category category) throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql="insert into category values(null,?,?,?,?)";
int add = queryRunner.update(sql, category.getC_name(), category.getPlace(), category.getCreatetime(), category.getType());
return add > 0 ? true : false;
}
/**
* 根据c_id修改对应的生鲜品类
* @return 返回一个布尔值,表示是否修改成功
* @throws SQLException
*/
public boolean updateCategory(Category category) throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql="update category set c_name=?,place=?,createtime=?,type=? where c_id=?";
int update = queryRunner.update(sql,category.getC_name(), category.getPlace(), category.getCreatetime(), category.getType(),category.getC_id());
return update > 0 ? true : false;
}
/**
* 根据c_id删除对应的生鲜品类
* @return 返回一个布尔值,表示是否删除成功
* @throws SQLException
*/
public boolean deleteCategory(Category category) throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
QueryRunner queryRunner = new QueryRunner(dataSource);
String sql="delete from category where c_id=?";
int delete = queryRunner.update(sql,category.getC_id());
return delete > 0 ? true : false;
}
}
(5)过滤器UserFilter类
package com.study.filter;
import com.study.bean.User;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* /category 表示对CategoryServlet类下的所有操作进行用户登陆过滤检查
*/
@WebFilter(filterName = "UserFilter",urlPatterns = "/category")
public class UserFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//转换类型
HttpServletRequest request= (HttpServletRequest) req;
HttpServletResponse response= (HttpServletResponse) resp;
//获取session
HttpSession session = request.getSession();
//获取UserServlet类中login方法中设置的session属性值
User user = (User) session.getAttribute("user");
if(user==null){//表示用户没有登录,重定向到login.jsp页面,同时结束方法
response.sendRedirect(request.getContextPath()+"/login.jsp");
return;
}
//表示放行,用户已经登录,可以正常的提交页面信息
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
(6)素材前端页面的修改处如下:
(7)演示过程(点击之前配置的Tomcat server即可,就是Tomcat Server配置第一步点击处哪里寻找),这里是用做好的test10项目进行演示:
javaweb项目生鲜管理系统简易版演示.mp4
三、简单总结与拓展
1.简述添加生鲜品类的后端执行过程(其它类似)
(1)前端注册信息通过表单提交到UserServlet类,该类没有执行方法的入口,但是它的父类BaseServlet有,于是转到父类寻找执行方法入口,父类执行service()方法,该方法体通过反射获取其子类的方法并执行(因为前端表单在提交时同时提交了method的属性值,该值决定了执行子类的具体方法,这就要求前端的属性值和后端的方法名必须对应一致,否则无法使用BaseServletdi)
(2)首先通过UserServlet的register方法中request的getParameterMap()方法获取前端注册页面的注册信息,接着通过将信息封装到user对象中,调用UserService对象的registerUser()方法,在检测用户没有注册的情况下提交用户注册信息到数据库中,并且返回注册结果,注册成功则重新定向到登陆界面,否则给出提示信息,注册失败
(3)前端提交登陆界面信息后,后端调用UserServlet中login方法,同样先获取前端数据封装到对象user中,然后去数据库中查找有没有该用户,如有则获取前端记住密码的属性值,如果是“yes”则通过Cookie保存账号信息,否则不保存,同时将user对象设置到session对象的属性值中,这样UserFilter过滤器才能获取到user对象用于对生鲜品类界面操作判断用户是否已经登录;如果数据库中没有该用户,则提示登录失败。登录成功后,将挈带method参数值页面重定向到生鲜列表界面
(4)进入生鲜列表界面之前,首先判断用户是否已经登录,如果没有登录,则重定向到登陆界面login.jsp,如果已经登录,则先进入到BaseServlet中进行方法的调用,根据获取挈带的method值决定CategoryServlet的getCategoryList方法。
(5)首先给显示页面设置初始值,默认显示第1页,每页数量10条。这个通过获取前端属性值可以进行初值判断并且设置(如果不进行null值判断可能会报错)。此时我们可以通过一个封装类Page,将页面所有信息进行封装。通过数据库可以获取所有品类的总数,然后可以计算出总页数,当前页和当前页的数目通过前端设置获取;通过数据库还可以获取指定范围数目的生鲜品类信息的集合。所有这些都封装到page对象中,如果返回的page对象不是空值,则将其设置到request域中,通过request的请求转发将结果返回到前端页面。前端页面再根据其结果将数据显示出来
(6)当我们进行添加生鲜品类时,前端提交表单会先进入UserFilter判断是否有用户登陆,如果没有,则重定向到登陆界面,否则就会进入正常提交表单数据操作:先是通过request的getParameterMap()方法获取表单数据,并且通过工具类封装到category对象中,然后调用对应的service和dao方法讲数据添加到数据库中,并且返回结果,如果成功,则向客户端发送一个成功的状态码,同时重新定向到生鲜列表显示界面(通过method挈带属性值重复(4)(5)步)
2.自己改写的简单工具类:
(1)db.properties替换c3p0-config.xml
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/fresh10?serverTimezone=GMT&useSSL=false
name=root
password=YCF500095
(2)数据库连接
package com.study.utils;
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 java.net.URL;
//连接数据库
public class DataSources {
private static String driver;
private static String URL;
private static String USER;
private static String PASSWORD;
static {
try {
ClassLoader classLoader=DataSources.class.getClassLoader();
//URL resources=classLoader.getResource ("db.properties");
InputStream resources=classLoader.getResourceAsStream("db.properties");
Properties properties=new Properties();
properties.load(resources);
//properties.load (new FileReader (resources.getPath ()));
driver=properties.getProperty("driver");
URL=properties.getProperty("url");
USER=properties.getProperty("name");
PASSWORD=properties.getProperty("password");
//System.out.println(driver+"\t"+URL+"\t"+USER+"\t"+PASSWORD);
} catch (IOException e) {
e.printStackTrace();
}
}
public Connection getConnection(){
Connection con=null;
try {
//注册驱动
Class.forName(driver);
//连接数据库
con=DriverManager.getConnection(URL,USER,PASSWORD);
} catch (ClassNotFoundException e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
} catch (SQLException e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
return con;
}
}
(3)数据库操作
package com.study.utils;
import java.lang.reflect.InvocationTargetException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
//数据库处理
@SuppressWarnings("unused")
public class QueryRunner {
DataSources dataSources;
public QueryRunner(DataSources dataSources) {
this.dataSources = dataSources;
}
/**
* 查找对象的集合
* @param sql
* @param beanListHandler
* @param params
* @return 返回一个对象集合
* @throws SQLException
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public List query(String sql, BeanListHandler beanListHandler, Object... params) throws SQLException {
List list = new ArrayList();
try {
//连接数据库
Connection con = dataSources.getConnection();
//调用查询方法
PreparedStatement preparedStatement = con.prepareStatement(sql);
//使用不确定参数,解决参数类型和参数个数未定的问题
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject((i + 1), params[i]);
}
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
//需要set方法,属性类型,属性名称
list.add(beanListHandler.reflectMethod(resultSet));
}
//关闭资源
resultSet.close();
preparedStatement.close();
con.close();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return list;
}
/**
* 查找一个对象
* @param sql
* @param beanHandler
* @param params
* @return 返回一个对象
* @throws SQLException
*/
public Object query(String sql, BeanHandler beanHandler, Object... params) throws SQLException{
Object obj=null;
try {
//连接数据库
Connection con = dataSources.getConnection();
//调用查询方法
PreparedStatement preparedStatement = con.prepareStatement(sql);
//使用不确定参数,解决参数类型和参数个数未定的问题
for (int i = 0; i < params.length; i++) {
preparedStatement.setObject((i + 1), params[i]);
}
ResultSet resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
obj=beanHandler.reflectMethod(resultSet);
}
//关闭资源
resultSet.close();
preparedStatement.close();
con.close();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return obj;
}
/**
* 查找表的统计数据
* @param sql
* @param scalarHandler
* @param params
* @return 返回一个long值
* @throws SQLException
*/
public Long query(String sql, ScalarHandler scalarHandler, Object...params) throws SQLException {
//连接数据库
Connection con=dataSources.getConnection();
//调用查询方法
PreparedStatement preparedStatement=con.prepareStatement(sql);
//使用不确定参数,解决参数类型和参数个数未定的问题
for(int i=0;i<params.length;i++) {
preparedStatement.setObject((i+1), params[i]);
}
ResultSet resultSet=preparedStatement.executeQuery();
Long num=scalarHandler.getObjectRows(resultSet);
//关闭资源
resultSet.close();
preparedStatement.close();
con.close();
return num;
}
//添加、修改、删除数据
public int update(String sql,Object...params) {
int row=0;
try {
Connection con=dataSources.getConnection();
//使用preparedStatement防止SQL注入
PreparedStatement preparedStatement=con.prepareStatement(sql);
//使用不确定参数,解决参数类型和参数个数未定的问题
for(int i=0;i<params.length;i++) {
preparedStatement.setObject((i+1), params[i]);
}
//返回添加结果,结果是一个整数
row =preparedStatement.executeUpdate();
//关闭资源
preparedStatement.close();
//con.close();
}catch (SQLException e) {
e.printStackTrace();
}
return row;
}
}
(4)工具类BeanUtils:将前端相应参数值封装到对应对象中
package com.study.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 将前端相应参数封装到对象中
*/
public class BeanUtils{
public static void populate(Object obj,Map<String,String[]> parameterMap) throws InvocationTargetException, IllegalAccessException{
//得到字节码文件
Class cls = obj.getClass();
//获取对象字节码对象的所有方法
Method[] mt = cls.getDeclaredMethods();
//获取前端得到的键的集合
Set<String> keySet = parameterMap.keySet();
//使用迭代器读取
for (Method e : mt) {
//用下面这个方法,前提如下:对象封装类的void方法只有set方法
if (e.getReturnType().equals(Void.TYPE)) {//获取封装对象的所有void方法
//获取void setter()方法名字名称部分:如public void setSum(int sum){this.sum=sum;}得到“setSum”中的“Sum”
String str = getMethodParameterName(e.getName());
if (str != null) {
Iterator<String> it = keySet.iterator();
while (it.hasNext()) {//读取前端得到的键名,即属性名称
String key = it.next();//得到属性名
String[] value = parameterMap.get(key);//获取对应键名(即属性名)的键值
System.out.println(str+";;;"+key+";;;"+value[0]);
if (key.equals(str)) {//如果方法名和键名对应,则执行对应方法
if(e.getParameterTypes()[0].getTypeName().equals("java.lang.String")) {//参数类型判断
//指定方法赋值,即调用setter方法,(即如调用了public void setSum(int sum){this.sum=sum;})
e.invoke(obj, value[0]);
}else{//数值类型转换为int型,当然可以把所有的数据类型列出来
e.invoke(obj, Integer.parseInt(value[0]));
}
break;
}
}
}
}
}
}
public static String getMethodParameterName(String ss) {
/**
* 例:public void setSum(int sum){this.sum=sum;}
* ss就是对应void型方法,只对set方法进行操作;
* ss.substring(3,ss.length()).substring(0,1).toLowerCase(): 得到s
* ss.substring(4,ss.length()):得到um
* 拼起来就是sum(即得到了私有数据域private int sum的变量名称,和前端的属性名称是对应)
*/
if(ss.substring(0,3).equals("set")) {
return ss.substring(3, ss.length()).substring(0, 1).toLowerCase() + ss.substring(4, ss.length());
}
return null;
}
}
(5)具体执行方法
package com.study.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 集合操作
* @param <T>
*/
public class BeanListHandler<T>{
@SuppressWarnings("rawtype")
Class obj;
//带字节码对象参数的构造方法
public BeanListHandler(Class obj){
this.obj=obj;//获得类名
}
public T reflectMethod(ResultSet resultSet) throws NoSuchMethodException, IllegalAccessException, InstantiationException, SQLException, InvocationTargetException {
T t=(T) obj.newInstance();//实例化对象
Method[] mt=obj.getDeclaredMethods();//获取本类所有的方法
for(Method e:mt) {
//找对象封装类的void类型的set方法
if(e.getReturnType().equals(Void.TYPE)) {
Method met=obj.getDeclaredMethod(e.getName(), e.getParameterTypes()[0]);//获取指定类的方法
//通过void类型的set方法获取封装对象私有域变量名称
String str=this.getMethodParameterName(e.getName());
if(str !=null) {
if(e.getParameterTypes()[0].getTypeName().equals("java.util.Date")){
//执行该setter方法,不支持Date方法
met.invoke(t, resultSet.getDate(str));
}else{
//执行该setter方法,不支持Date方法
met.invoke(t, resultSet.getObject(str, e.getParameterTypes()[0]));
}
}
}
}
return t;
}
public String getMethodParameterName(String ss) {
if(ss.substring(0,3).equals("set")) {
//得到私有域变量名称
return ss.substring(3, ss.length()).substring(0, 1).toLowerCase() + ss.substring(4, ss.length());
}
return null;
}
}
package com.study.utils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 单类操作
* @param <T>
*/
public class BeanHandler<T> {
@SuppressWarnings("rawtypes")
Class clazz;
//带字节码对象参数的构造方法
public BeanHandler(Class obj){
this.clazz=obj;//获得类名
}
public T reflectMethod(ResultSet resultSet) throws SQLException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
T t = (T) clazz.newInstance();//实例化对象
Method[] mts = clazz.getDeclaredMethods();//获取本类所有的方法
for (Method e : mts) {
//找对象封装类的void类型的set方法
if (e.getReturnType().equals(Void.TYPE)) {
//获取指定类的方法
Method met = clazz.getMethod(e.getName(), e.getParameterTypes()[0]);
//通过void类型的set方法获取封装对象私有域变量名称
String str = this.getMethodParameterName(e.getName());
if (str != null) {
//执行该setter方法
met.invoke(t, resultSet.getObject(str, e.getParameterTypes()[0]));
}
}
}
System.out.println(t.getClass());
return t;
}
public String getMethodParameterName(String ss) {
if(ss.substring(0,3).equals("set")) {
//得到私有域变量名称
return ss.substring(3, ss.length()).substring(0, 1).toLowerCase() + ss.substring(4, ss.length());
}
return null;
}
}
package com.study.utils;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 统计数据操作
* @param <T>
*/
public class ScalarHandler<T> {
Object obj;
public ScalarHandler(){
}
public ScalarHandler(Object obj){
this.obj=obj;
}
public Long getObjectRows(ResultSet resultSet) throws SQLException {
long num=0;
while (resultSet.next()){
num=resultSet.getInt(1);
}
return num;
}
}
四、学习过程遇到的问题
1.配置文件连接数据库的问题
(1)driver驱动:根据不同版本的数据库连接包,其配置也不相同。例如在该例子中:我使用的是:mysql-connector-java-8.0.14.jar,所以其driver配置就为:
com.mysql.cj.jdbc.Driver(如果你是用db.properties文件,则为:driver=com.mysql.cj.jdbc.Driver),版本低就不要加“cj."
(1)url:根据不同版本的数据库连接包,其配置也不相同。例如在该例子中,我的配置就为:
jdbc:mysql://localhost:3306/fresh10?serverTimezone=GMT%2B8&useSSL=false
(如果你是用db.properties文件,则为:jdbc:mysql://localhost:3306/fresh10?serverTimezone=GMT%2B8&useSSL=false)
2.数据库操作的问题
注意不要写错sql语句和参数