总纲:项目开发逻辑
1.项目流程
确定需求->代码编码(数据库创建,创建项目-(包结构,工具类,工具包,逻辑代码编写))->测试阶段->上线
2. 包的主要结构
bean 存放实体类
dao 接口包
dao.impl 接口的实现类包,存放操作数据库的方法
service 接口包
service.impl 接口的实现类包,存放业务逻辑代码
web/servlet 定义servlet处理类
util 自定义的工具包
3.包结构的调取关系
servlet 调取service ,service 调取dao, dao操作bean
4.包的填充
填充顺序:bean, dao, impl, service, service.impl, servlet
(1) bean(实体类包):用来和数据库表做对应关系的
代码编写规范:类名=表名,列名=属性名
属性的类型建议使用包装类
(2)dao包:用来定义操作数据库的方法
命名规范:bean实体类+Dao
(3)dao.impl包:定义dao的实现类
命名规范:接口名+Impl
(4)service包:用来定义业务逻辑的方法
命名规范:bean实体类+Service
(5)service.impl包:定义service的实现类
命名规范:接口名+Impl
(6)web/servlet包:定义处理请求的servlet
命名规范版本1:功能名+Servlet,示例:InsertUsersServlet,DeleteUsersServlet
ps:数据库中的一条数据==java中的一个对象
service接口层的代码在javaweb开发期间,和dao层的接口是一样的
将项目中所用到的jar包放到tomcat的lib文件夹下
新建的项目,记得把项目路径改成/
5.准备工作:创建数据表,导入jar包,实体类,工具类,配置好连接数据库的属性文件
数据表
导入jar包
连接数据库的属性文件
url=jdbc:mysql://localhost:3306/mydemo1?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
uname=root
upass=1380341
driverClass=com.mysql.cj.jdbc.Driver
实体类
最初的实体类,后续还有很多更改
package bean;
public class Users {
//属性
private Integer userid;
private String username;
private Integer age;
private String sex;
private String password;
//无参
public Users() {
}
//全参
public Users(Integer userid, String username, Integer age, String sex, String password) {
this.userid = userid;
this.username = username;
this.age = age;
this.sex = sex;
this.password = password;
}
//重写toString(),get(),set()方法
@Override
public String toString() {
return "Users{" +
"userid=" + userid +
", username='" + username + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", password='" + password + '\'' +
'}';
}
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
工具类 DBUtilsPlus
package util;
import com.alibaba.druid.pool.DruidDataSource;
import java.sql.*;
import java.util.List;
import java.util.ResourceBundle;
// BaseDao 将链接数据库的步骤进行封装,简化后续JDBC操作
public class DBUtilsPlus {
// 德鲁伊 数据库连接池
private static DruidDataSource dataSource;
//1.定义常用的工具类(Protected修饰的属性或方法可以在子类中被调用)
protected Connection connection;
protected PreparedStatement pps;
protected ResultSet resultSet;
static {
dataSource=new DruidDataSource();
ResourceBundle db = ResourceBundle.getBundle("jdbc");
dataSource.setUrl(db.getString("url"));
dataSource.setDriverClassName(db.getString("driverclass"));
dataSource.setUsername(db.getString("uname"));
dataSource.setPassword(db.getString("upass"));
//设置链接数量
// dataSource.setInitialSize(30);
dataSource.setMaxActive(8);
}
//3.得到链接对象
protected Connection getConnection(){
try {
connection = dataSource.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
//4.创建通道
protected PreparedStatement getPps(String sql){
getConnection();
try {
pps = connection.prepareStatement(sql);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return pps;
}
//5.绑定占位符的值 insert into A(sid,sname,sex,age .... ) values(?,?,?,?)
//List 参数存储的是给占位符所赋的值
//setParameter(new ArrayList())
public void setParameter(List list){
try {
if (list != null&&list.size()>0) { //对List集合进行有效性验证
for (int i=0;i<list.size();i++) {
pps.setObject(i+1,list.get(i));
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//6.执行sql-增删改
protected int updateDB(String sql,List list){
int i = 0;
try {
getPps(sql);//sql
setParameter(list);//list-绑定的是占位符的参数
i = pps.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return i;
}
//7.执行sql-查询
protected ResultSet selectDB(String sql,List list){
try {
getPps(sql);//sql
setParameter(list);//list-绑定的是占位符的参数
resultSet=pps.executeQuery();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return resultSet;
}
//8.关闭资源
public void closeAll(){
try {
if (resultSet != null) {
resultSet.close();
}
if (pps != null) {
pps.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
6.编程思路
写完实体类后Users之后
(1)根据逻辑,dao操作bean,我们想到接下来是在dao包定义Users类的UsersDao接口类
(2)定义了UsersDao接口类,我们又需要UsersDaoImpl实现类。
(3)根据逻辑,service调取dao,我们创建UsersService接口类。
(4)同理,定义了UsersService接口类,我们又需要UsersServiceImpl实现类。
(5)根据逻辑servlet 调取service,我们每一个功能,都需要创建一个servlet类
比如登录功能,我们就需要一个LoginServlet类,由他开始调取 UsersService,再由UsersService调取UsersDao,UsersDao来操作Users
模块一:登录退出功能的实现
实现流程图
1.登录功能代码实现
思路:页面请求—>servlet处理类调取service ,service 调取dao, dao操作bean
编程思路:1.根据请求创建页面实例
1.首先有了请求,我们先将index.jsp动态页面,建成一个登陆界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>登录</h1>
<form action="/login" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="userpass"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
2创建LoginServlet处理类
2.有了请求之后根据调取逻辑,首先是servlet调取service,所以要创建LoginServlet处理类,继承HttpServlet 类重写service方法。
这里先加入了接收参数部分
package web;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.接参数
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");//要和表单的name值相同
String userpass =req.getParameter("userpass");
//写逻辑
//返结果
return null;
}
}
3.配置web.xml文件
有了servlet之后,我们需要同时在web.xml文件中配置servlet
<servlet>
<servlet-name>loginuser</servlet-name>
<servlet-class>
web.LoginServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginuser</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
登录是我们的第一个功能,我们先按照根据调用逻辑开始写一个登录的方法
servlet 调取service ,service 调取dao, dao操作bean
4.UsersService与UsersDao的Login方法
UsersService的Login方法
public Users Login(String username,String pass);
UsersDao的Login方法
public Users Login(String username,String pass);
这两个Login方法一模一样,
但 UsersDao接口是用来定义操作数据库的方法的
而UsersService接口是用来定义业务逻辑方法的
二者有本质区别,具体表现在他们各自的实现类上。
UsersService的实现类UsersServiceImpl,就是返回一个调取UsersDao的login方法的方法
service 调取dao
5.UsersServiceImpl实现业务调用逻辑
package service.impl;
import bean.Users;
import dao.UsersDao;
import dao.impl.UsersDaoImpl;
import service.UsersService;
public class UsersServiceImpl implements UsersService {
UsersDao usersDao=new UsersDaoImpl();
@Override
public Users Login(String username, String pass) {
return usersDao.Login(username,pass);
}
}
而 UsersDao的实现类UsersDaoImpl则需要实现具体的方法
要实现登录方法,我们就需要查询数据库的username,password数据,找的用户名密码相匹配的数据,因此需要用到DBUtilsPlus中的selectDB(sql,params)这个方法。
编程思路:首先继承工具类 DBUtilsPlus,因为我们需要使用它的selectDB(sql,params)方法操作数据库,而selectDB(sql,params);方法有两个参数,分别是sql与params,而我们的代码就是 要想办法获取这两个参数。
6. UsersDaoImpl实现操作数据库的逻辑
@Override
public Users Login(String username, String pass) {
Users u1 = null;
try {
String sql="select * from users where username=? and password=?";
List params=new ArrayList();
params.add(username);
params.add(pass);
resultSet=selectDB(sql,params);
//将结果集的内容拿到java对象中(当结果集有数据时,就会进入得到循环中,每一次循环都会拿到数据库的中一行数据)
while(resultSet.next()){
u1=new Users();
u1.setUserid(resultSet.getInt("userid"));
u1.setAge(resultSet.getInt("age"));
u1.setPassword(resultSet.getString("password"));
u1.setSex(resultSet.getString("sex"));
u1.setUsername(resultSet.getString("username"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeAll();
}
return u1;
}
现在操作逻辑,业务逻辑都有了,我们可以补齐LoginServlet代码了,LoginServlet接收用户名密码参数后,首先调用LoginService逻辑,最后返回结果成功or失败给页面。
7.完善LoginOutServlet代码
package web;
import bean.Users;
import service.UsersService;
import service.impl.UsersServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
public class LoginServlet extends HttpServlet {
//重写方法时 二选一
//1重写Service()
//2重写doget()与dopost()方法
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.接参数
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");//要和表单的name值相同
String userpass =req.getParameter("userpass");
//写逻辑:面向接口编程
UsersService usersService=new UsersServiceImpl();
Users u = usersService.Login(username, userpass);
//3.返结果
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
if (u==null){
//登录失败(在后端给前端返回一个弹窗-若用js,就不要再用重定向或转发跳页面了否则405错误)
//location.href是属于重定向跳转页面
writer.print("<script type='text/javascript'>alert('用户名或密码不正确');location.href='index.jsp'</script>");
}else {
//登录成功
HttpSession session = req.getSession();
session.setAttribute("u1",u);
writer.print("<script type='text/javascript'>alert('登录成功');location.href='success.jsp'</script>");
}
}
}
8.返回结果页面
如果登录成功,我们又需要一个成功页面
<%@ page import="bean.Users" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
Users u1 =(Users) session.getAttribute("u1");
%>
<h1>
success.jsp,<%=u1.getUsername()%>欢迎您:
</h1>
</body>
</html>
做完成功页面,我们的第一个功能,登录功能就完成了
2.测试登录功能
使用maven之后,在这里运行Tomcat
程序启动之后在控制台点击链接,可以直接跳转页面
养成没实现一个功能就测试一次的习惯
输入正确的用户明密码
错误的用户名密码
然后回到页面
3.项目踩坑
第一个坑:maven不会导jar包。
解决方案
删除掉之前lib的设置,打开https://mvnrepository.com/网站,按照jar包关键字,搜索jar包,再将其坐标发送到pom.xml文件中。
详细经过
点击复制,再打开 pom.xml文件
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
第二个坑:sevlet版本过低,这里自带的2.3
解决方案
首先修改pom文件
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
然后在web.xml文件中修改新的头文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
第三个坑,找不到jdbc,其中三处错误
错误一:属性文件名叫db.properties,而工具类的 文件名却是jdbc
解决方案:修改静态代码块,与错误三一起修改
错误二:属性文件需要在resources包下,而不是直接在项目包下
解决方案:在mian/java包下新建一个resources包,把db.properties复制过去
错误三:driverClass没有生效,原因是jdbc工具类中,driverclass没有按照小驼峰规范,用了小写
解决方案:修改静态代码块
static {
dataSource=new DruidDataSource();
ResourceBundle db = ResourceBundle.getBundle("db");
dataSource.setUrl(db.getString("url"));
dataSource.setDriverClassName(db.getString("driverClass"));
dataSource.setUsername(db.getString("uname"));
dataSource.setPassword(db.getString("upass"));
//设置链接数量
// dataSource.setInitialSize(30);
dataSource.setMaxActive(8);
}
ps:新的项目需要改tomcat路径
完成第一个功能,接着完成第二个功能,退出
思路:页面请求—>servlet处理类调取service ,service 调取dao, dao操作bean
跟登录功能的思路大体相同。
4.退出功能代码实现
编程思路:1.有了退出请求,我们先将success.jsp动态页面,建成一个退出的按钮
<a href="/loginout">退出</a>
我