首先说一下怎样实现登陆功能吧,昨天我们在一个类里面实现了登陆功能,但是这是因为功能很少,一旦功能很多的情况下其实是需要分类去写的我这里说一下思路:
首先分层出基本架构:
dao层:(数据访问层:数据库中的增删改查操作)
通过用户名查询用户对象, 返回用户对象
1. 获取数据库连接
2. 定义sql语句
3. 预编译
4. 设置参数
5. 执行查询,返回结果集
6. 判断并分析结果集
7. 关闭资源
po层:定义实体类,生成get/set方法
service层:(业务逻辑层:参数判断、业务逻辑处理)
uril层:需要用到的工具包,比如数据库连接
vo层:封装返回结果对象,比如状态码这些
web层:也是servlet层,(控制层:接收参数、响应数据)
一:然后具体代码解析一下,首先我们创建好基本框架1后,先写po层,用户实体类最好写了哈哈:
package com.ftz.Demo.po;
import lombok.Getter;
import lombok.Setter;
/**
* @author ${范涛之}
* @Description
* @create 2021-12-08 10:20
*/
@Getter
@Setter
public class User {
private Integer id;
private String username;
private String password;
public void id(Integer userId) {
this.id = userId;
}
}
二:然后写数据库连接层,这一层也就是固定步骤:util里面的DButil:
package com.ftz.Demo.util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* @author ${范涛之}
* @Description
* @create 2021-12-08 10:08
*/
public class DBUtil {
/**
* 得到配置文件对象
*/
private static Properties properties = new Properties();
static {
try {
//加载配置文件(输入流)
InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");
// 通过load()方法将数日六的内容加载到配置文件对象中
properties.load(in);
// 通过配置文件对象的getProperty()方法获取驱动名,拿到驱动名之后加载驱动
Class.forName(properties.getProperty("jdbcName"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
* @return
*/
public static Connection getConnection(){
Connection connection = null;
try {
//得到数据库链接的相关性息
String dbUrl = properties.getProperty("dbUrl");
String dbName = properties.getProperty("dbName");
String dbPwd = properties.getProperty("dbPwd");
connection = DriverManager.getConnection(dbUrl,dbName,dbPwd);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
/**
* 关闭资源
* @param resultSet
* @param preparedStatement
* @param connection
*/
public static void close(ResultSet resultSet,
PreparedStatement preparedStatement,
Connection connection){
//判断资源对象如果不为空则关闭
try {
if (resultSet != null) {
resultSet.close();
}
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
}catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
三:接下来就开始写vo层,返回一些特定标识,让我们1知道该使用什么功能这样:
package com.ftz.Demo.vo;
import lombok.Getter;
import lombok.Setter;
/**
* @author ${范涛之}
* @Description
* @create 2021-12-08 10:21
*/
@Getter
@Setter
public class ResultInfo<T> {
private Integer code; //状态码
private String msg; // 提示信息
private T result; // 返回的对象(字符串、JavaBean、集合、Map等)
}
四:然后是dao层:根据上面的固定步骤:最后返回查询到的user对象
通过用户名查询用户对象, 返回用户对象
1. 获取数据库连接
2. 定义sql语句
3. 预编译
4. 设置参数
5. 执行查询,返回结果集
6. 判断并分析结果集
7. 关闭资源
1. 获取数据库连接
connection = DBUtil.getConnection();
2. 定义sql语句
String sql = "select * from user where username = ?";
3. 预编译
preparedStatement = connection.prepareStatement(sql);
4. 设置参数,这里的1代表sql语句里面的第一个问号,后面是传的值
preparedStatement.setString(1,userName);
5.执行查询,返回结果集
resultSet = preparedStatement.executeQuery();
6. 判断并分析结果集
if (resultSet.next()){
user = new User();
user.id(resultSet.getInt("id"));
user.setUsername(userName);
user.setPassword(resultSet.getString("password"));
}
7. 关闭资源:
DBUtil.close(resultSet,preparedStatement,connection);
返回结果:
return user;
全部代码:
package com.ftz.Demo.dao;
import com.ftz.Demo.po.User;
import com.ftz.Demo.util.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author ${范涛之}
* @Description
* @create 2021-12-08 10:21
*/
public class UserDao {
public User queryUserByName(String userName){
User user = null;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = DBUtil.getConnection();
String sql = "select * from user where username = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,userName);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
user = new User();
user.id(resultSet.getInt("id"));
user.setUsername(userName);
user.setPassword(resultSet.getString("password"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
DBUtil.close(resultSet,preparedStatement,connection);
}
return user;
}
}
五:接下来写service层,同样也是根据上面的思路:
Service层:(业务逻辑层:参数判断、业务逻辑处理)
1. 判断参数是否为空
如果为空
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
2. 如果不为空,通过用户名查询用户对象
3. 判断用户对象是否为空
如果为空
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
4. 如果用户对象不为空,将数据库中查询到的用户对象的密码与前台传递的密码作比较 (将密码加密后再比较)
如果密码不正确
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
5. 如果密码正确
设置ResultInfo对象的状态码和提示信息
6. 返回resultInfo对象
1 判断参数是否为空
如果为空
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
/**
* 判断参数为空
*/
if (StrUtil.isBlank(username) || StrUtil.isBlank(userPwd)){
resultInfo.setCode(0);
resultInfo.setMsg("用户名或密码不能为空!");
return resultInfo;
}
2:如果不为空,通过用户名查询用户对象
User user = userDao.queryUserByName(username);
3. 判断用户对象是否为空
如果为空
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
/**
* 如果user为空,设置ResultInfo对象状态码和提示信息
*/
if (user == null){
resultInfo.setCode(0);
resultInfo.setMsg("该用户不存在");
return resultInfo;
}
4. 如果用户对象不为空,将数据库中查询到的用户对象的密码与前台传递的密码作比较 (将密码加密后再比较)
如果密码不正确
设置ResultInfo对象的状态码和提示信息
返回resultInfo对象
// 4. 如果用户对象不为空,将数据库中查询到的用户对象的密码与前台传递的密码作比较
if (!userPwd.equals(user.getPassword())){
resultInfo.setCode(0);
resultInfo.setMsg("用户密码不正确!");
return resultInfo;
}
5. 如果密码正确
设置ResultInfo对象的状态码和提示信息
resultInfo.setCode(1);
resultInfo.setResult(user);
6. 返回resultInfo对象:
return resultInfo;
全部代码:
package com.ftz.Demo.service;
import cn.hutool.core.util.StrUtil;
import com.ftz.Demo.dao.UserDao;
import com.ftz.Demo.po.User;
import com.ftz.Demo.vo.ResultInfo;
/**
* @author ${范涛之}
* @Description
* @create 2021-12-08 10:21
*/
public class UserService {
/**
* 用户登陆
*/
private UserDao userDao = new UserDao();
public ResultInfo<User> userLogin(String username,String userPwd){
ResultInfo<User> resultInfo = new ResultInfo<>();
/**
* 判断参数为空
*/
if (StrUtil.isBlank(username) || StrUtil.isBlank(userPwd)){
resultInfo.setCode(0);
resultInfo.setMsg("用户名或密码不能为空!");
return resultInfo;
}
// 2. 如果不为空,通过用户名查询用户对象
User user = userDao.queryUserByName(username);
/**
* 如果user为空,设置ResultInfo对象状态码和提示信息
*/
if (user == null){
resultInfo.setCode(0);
resultInfo.setMsg("该用户不存在");
return resultInfo;
}
// 4. 如果用户对象不为空,将数据库中查询到的用户对象的密码与前台传递的密码作比较
if (!userPwd.equals(user.getPassword())){
resultInfo.setCode(0);
resultInfo.setMsg("用户密码不正确!");
return resultInfo;
}
resultInfo.setCode(1);
resultInfo.setResult(user);
return resultInfo;
}
}
六:写web层:也就是controller层
Web层:(控制层:接收参数、响应数据)
1. 获取参数 (姓名、密码)
2. 调用Service层的方法,返回ResultInfo对象
3. 判断是否登录成功
如果失败
将resultInfo对象设置到request作用域中
请求转发跳转到登录页面
如果成功
将用户信息设置到session作用域中
判断用户是否选择记住密码(rem的值是1)
如果是,将用户姓名与密码存到cookie中,设置失效时间,并响应给客户端
如果否,清空原有的cookie对象
重定向跳转到index页面
1:获取参数 (姓名、密码)
// 1. 获取参数 (姓名、密码)
String userName = request.getParameter("userName");
String userPwd = request.getParameter("userPwd");
2:调用Service层的方法,返回ResultInfo对象
ResultInfo<User> resultInfo = userService.userLogin(userName, userPwd);
3. 判断是否登录成功
if (resultInfo.getCode() == 1) { // 如果成功
response.sendRedirect("hello.jsp");
} else { // 失败
request.getRequestDispatcher("false.jsp").forward(request, response);
}
实现截图:
最后再简单说一下个人总结吧:其实我们这个分层最最大的就是三大块:dao层 service层 和web层,这三层一层调用一层,web层调用service层,service层调用dao层,在dao层中我们建立了与数据库的连接,将循环查询到数据的对应的数据库中数据存放在返回的user中,然后service层去调用dao层中获得的数据库数据用来和前台传过来的数据做比较也就是业务逻辑在这里体现,最后昨晚1判断后返回状态码,接下来web层调用service层传过来的状态码来实现具体操作!
下面是全部代码包括前端:
链接:https://pan.baidu.com/s/186v108Btj1oY3003s3Zjhw
提取码:r1dr
--来自百度网盘超级会员V3的分享