做一个用户登录&管理功能
需求:
1、用户登录
2、展现用户列表
3、修改密码
实现过程
1)搭建平台
springboot版本2.6.1
java版本1.8
IDE:IDEA 2019.3.3
这里注意要将java版本改为1.8,否则报错
2)整合mybatis-plus
1、application.properties配置数据库连接池
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
2、引入mybatisplus及lombok依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
<scope>provided</scope>
</dependency>
3、mysql新建表
其中id为自增主键
username唯一
这里有问题,由于username是唯一索引,后面执行update语句时会报错,后来把唯一索引去了,就不报错了。
4、新建User实体类
@TableName("user")//mybatisplus注解,当类名与表名不一致时,用于指定表名
@Data//lombk注解,用于生成getter和setter方法
@AllArgsConstructor//lombok注解,用于生成有参构造
@NoArgsConstructor//lombok注解,用于生成无参构造
public class User {
private int id;
private String username;
private String password;
}
5、新建UserMapper接口,配置扫描路径
public interface UserMapper extends BaseMapper<User> {
}
BaseMapper也是Mybatisplus的接口,它包含了一些基本的增删改查接口,继承后便不用再写。
配置Mapper扫描路径
3)编写前端页面(login.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="/login" method="post">
用户名: <input type="text" name="username"><br>
密码: <input type="text" name="password"><br>
<button type="submit" name="action" value="login">登录</button>
<button type="submit" name="action" value="register">注册</button>
</form>
</body>
</html>
<script>
const form = document.querySelector('form');
const loginButton = form.querySelector('button[value="login"]');
const registerButton = form.querySelector('button[value="register"]');
loginButton.addEventListener('click', function(event) {
event.preventDefault();
form.action = '/login';
form.method = 'post';
form.submit();
});
registerButton.addEventListener('click', function(event) {
event.preventDefault();
form.action = '/register';
form.method = 'post';
form.submit();
});
</script>
效果
4)编写controller
UerController
@Autowired
UserMapper userMapper;
@GetMapping("/")
public String test(){
return "login";
}
@PostMapping("/register")
@ResponseBody
public String register(@RequestParam("username") String username,@RequestParam("password") String password){
if(username == null || password == null || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) return "错误,用户名或密码不能为空";
User user = new User();
user.setUsername(username);
user.setPassword(password);
return userMapper.insert(user) > 0 ? "success":"fail";
}
@PostMapping("/login")
@ResponseBody
public String login2(@RequestParam("username") String username,@RequestParam("password") String password){
if(username == null || password == null || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) return "错误,用户名或密码不能为空";
List<User> userList = userMapper.selectList(null);
for(User user : userList){
if(user.getUsername().equals(username) && user.getPassword().equals(password)) return"success";
}
return "fail";
}
5)测试controller
登录
因为这个账号没有注册过,所以失败了
注册
表中多了这条记录,说明功能测试正确。
6)完善前的准备
首先,上面结果返回的都是json格式的数据,现在需要进行真正的业务实现,首先,在用户注册或者登录成功时,将当前用户数据放进session中,随后进入展示用户列表的页面。
@PostMapping("/register")
@ResponseBody
public String register(@RequestParam("username") String username,@RequestParam("password") String password){
if(username == null || password == null || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) return "错误,用户名或密码不能为空";
User user = new User();
user.setUsername(username);
user.setPassword(password);
return userMapper.insert(user) > 0 ? "success":"fail";
}
以上的代码无法获取user自增Id,所以第一步要做的就是获取插入的用户的id,可以通过select @@IDENTITY实现,具体代码如下:
public interface UserMapper extends BaseMapper<User> {
@Select("select @@IDENTITY")
int searchId();//返回类型 方法名
}
其次,再自定义一个通过username查找用户的方法
@Select("select count(*) from user where username = #{username} ")
int searchByName(@Param("username") String username);
编写一个展示用户列表的界面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html>
<head>
<title>用户列表</title>
</head>
<body>
<header>
<h1>用户列表</h1>
<div>
当前用户: <span th:text="${username}"></span>
<button id="change-password">修改密码</button>
</div>
</header>
<table>
<thead>
<tr>
<th>用户名</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${userList}">
<td><span th:text="${user.username}"></span></td>
</tr>
</tbody>
</table>
<script>
document.getElementById("change-password").addEventListener("click", function() {
window.location.href = "http://localhost:8080/change"
});
</script>
</body>
</html>
效果
虽然丑但是能用
7)完善登录&注册功能
1、注册部分
@PostMapping("/register")
//@ResponseBody
public String register(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model,
HttpServletResponse response){
//非空验证
if(username == null || password == null ||
StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
model.addAttribute("errorInfo","错误,用户名或密码不能为空");
return "error";
}
User user = new User();
user.setUsername(username);
user.setPassword(password);
//查询有没有相同用户名
int n = userMapper.searchByName(username);
if(n > 0){
model.addAttribute("errorInfo","该用户已存在");
return "error";
}
int res = userMapper.insert(user);
int id = userMapper.searchId();
user.setId(id);
if(res > 0){
//把ID放入cookie中
Cookie cookie = new Cookie("userId",id+"");
cookie.setMaxAge(60 * 60 * 24 * 7);//7天有效
response.addCookie(cookie);
return "redirect:/userList";
}else{
model.addAttribute("errorInfo","注册失败");
return "error";
}
}
2、登录部分
@PostMapping("/login")
//@ResponseBody
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model,
HttpServletResponse response){
//非空验证
if(username == null || password == null ||
StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
model.addAttribute("errorInfo","错误,用户名或密码不能为空");
return "error";
}
List<User> userList = userMapper.selectList(null);
//取出每一个user与输入进行对比
for(User user : userList){
if(user.getUsername().equals(username) && user.getPassword().equals(password)) {
Cookie cookie = new Cookie("userId",user.getId()+"");
cookie.setMaxAge(60 * 60 * 24 * 7);
response.addCookie(cookie);
return "redirect:/userList";
}
}
model.addAttribute("errorInfo","用户名或密码错误,登陆失败");
return "error";
}
以上代码运行没有问题,但是效率地下,因为他把每个Cookie取出对比了一遍,后期可以考虑优化。
改造过程中遇到最多的问题就是重定向后,session会失效,所以将用户的Id存在Cookie中,而Cookie不会失效
8)修改密码功能
首先点击修改密码,跳转到新界面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
用户名: <input type="text" readonly = true th:value="${username}" id="username"><br>
原密码: <input type="password" id="prePassword"><br>
密码: <input type="password" id="password"><br>
<button onclick="submitCredentials()">修改</button>
<script>
function submitCredentials() {
var username = document.getElementById("username").value;
var prePassword = document.getElementById("prePassword").value;
var password = document.getElementById("password").value;
$.ajax({
type: "POST",
url: "http://localhost:8080/changeword",
data: { username: username, prePassword: prePassword, password: password },
success: function(response) {
window.alert("修改成功");
window.location.href = "http://localhost:8080/";
// 处理成功响应的回调函数
},
error: function(xhr, status, error) {
window.alert("修改失败");
window.location.href = "http://localhost:8080/";
// 处理错误响应的回调函数
}
});
}
</script>
</body>
</html>
将修改后的密码以POST方式返回给后端
修改密码模块
@GetMapping("/change")
public String change(HttpServletRequest request,
Model model){
Cookie[] cookies = request.getCookies();
int userId = 0;
for(Cookie cookie : cookies){
if(cookie.getName().equals("userId")){
userId = Integer.parseInt(cookie.getValue());
User user = userMapper.selectById(userId);
model.addAttribute("username",user.getUsername());
return "change";
}
}
return "error";
}
@PostMapping("/changeword")
@ResponseBody
public String changepwd(@RequestParam("prePassword") String prePassword,
@RequestParam("password") String password,
HttpServletRequest request,
Model model){
Cookie[] cookies = request.getCookies();
for(Cookie cookie : cookies){
if(cookie.getName().equals("userId")){
int userId = Integer.parseInt(cookie.getValue());
User user = userMapper.selectById(userId);
if(!prePassword.equals(user.getPassword())){
return "原密码输入错误,请重试";
}
if(prePassword.equals(password)){
return "修改后的密码不能与原密码相同,请重试";
}
user.setPassword(password);
int res = userMapper.updateById(user);
//修改成功
if(res > 0){
cookie.setMaxAge(0);//让之前的Cookie失效
return "success";
}else{
return "error";
}
}
}
return "error";
}
9)功能测试
注册
图片插不进了,之后测试正常