1. 环境的准备
数据库
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(60) DEFAULT NULL COMMENT '员工姓名',
`salary` double(10,2) DEFAULT NULL COMMENT '员工工资',
`birthday` datetime DEFAULT NULL COMMENT '员工生日',
`photo` varchar(200) DEFAULT NULL COMMENT '头像路径',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(40) DEFAULT NULL COMMENT '用户名',
`realname` varchar(60) DEFAULT NULL COMMENT '真实姓名',
`password` varchar(40) DEFAULT NULL COMMENT '密码',
`gender` tinyint(1) unsigned DEFAULT NULL COMMENT '性别',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SET FOREIGN_KEY_CHECKS = 1;
1.1 引入依赖
pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
application.yaml
1) thymeleaf的设置
spring:
thymeleaf:
cache: false # 关闭缓存
prefix: classpath:/templates/ #指定模板位置
suffix: .html #指定后缀
注意:thymeleaf 必须添加上:xmlns:th="http://www.thymeleaf.org">
<html lang="en" xmlns:th="http://www.thymeleaf.org">
2) 路径配置:
server:
port: 9999
servlet:
context-path: /ems-thymeleaf
3) spring 相关配置
spring:
thymeleaf:
cache: false
prefix: classpath:/templates/
suffix: .html
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ems-thymeleaf?characterEncoding=UTF-8
username: root
password: 1234
web:
resources:
static-locations: classpath:/static/,file:${photo.file.dir} #暴露哪些资源可以通过项目名访问
4) mybatis
mybatis:
mapper-locations: classpath:com/baizhi/mapper/*.xml
type-aliases-package: com.baizhi.entity
- 注意:在 resource下面创建”com/baizhi/mapper/*.xml“时候,一点要用“/”, 不能用“.”
- type-aliases-package:给实体类别取别名,之前的在mybatis中,每次都需要com.xx.Student, 这里这样可以统一默认别名设置。
- 可以在主程序上面添加
@MapperScan("com.baizhi.dao")
来统一设置 Mapper;或者在Mapper上添加 @Mapper来实现
1. Dao层
x.2 用户登录
创建 UserController 类,专门用于处理 User相关的请求。
@Controller
@RequestMapping("/user")
public class UserController {
}
验证码
// 生成验证码
@RequestMapping("/generateImageCode")
public void generateImageCode(HttpSession session, HttpServletResponse response) throws IOException {
// 1. 生成 4 位的随机数
String code = VerifyCodeUtils.generateVerifyCode(4);
//2.保存到session作用域
session.setAttribute("code",code);
// 4.设置相应类型
response.setContentType("image/png");
// 相应
ServletOutputStream os = response.getOutputStream();
VerifyCodeUtils.outputImage(220,60,os,code);
}
在 regist.html 中添加验证码
<img id="num" src="@{/user/generateImageCode}" />
同时添加可以换图片的功能:
验证码:
<img id="num" th:src="@{/user/generateImageCode}" />
<a href="javascript:;" onclick="changeImageCode()">换一张</a>
<script>
function changeImageCode(){
document.getElementById('num').src = '[[@{/user/generateImageCode}]]?'+(new Date()).getTime()
}
</script>
注册
在 UserController 中, 设置 regist:
//用户注册
@RequestMapping("/regist")
public String regist(User user, String code, HttpSession session){
//Ctrl + Alt + t
// 1. 判断用户的输入的验证码和session中的一致
try {
String sessionCode = session.getAttribute("code").toString();
if( !sessionCode.equalsIgnoreCase(code))
throw new RuntimeException("验证码错误");
// 如果验证码一致,就正常注册
userServiceImp.register(user);
} catch (RuntimeException e) {
e.printStackTrace();
// 重返 regist 界面
return "redirect:/regist";
}
// 注册成功, 返回 login 界面
return "redirect:/login";
}
登录
在UserController里面:
//用户登录
@RequestMapping("/toLogin")
public String login(String username, String password, HttpSession session){
try {
// 1. 调用Service 层进行登录
User user = userServiceImp.login(username, password);
// 2. 保存用户信息
session.setAttribute("user", user);
} catch (Exception e) {
e.printStackTrace();
// 登录失败
return "redirect:/login";
}
// 跳转到显示界面
return "redirect:/employee/lists";
}
在Service层里面:
public User login(String username, String password) {
//1. 查询用户
User user = userMapper.findByUserName(username);
System.out.println(username);
if( ObjectUtils.isEmpty(user))
throw new RuntimeException("用户名不正确");
// 2. 比较密码
String s = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
if( !user.getPassword().equals(s))
throw new RuntimeException("密码错误");
return user;
}
x.3 员工信息
展示所有员工信息:
@Controller
@RequestMapping("employee")
public class EmployeeController {
@Autowired
private EmployeeServiceImp employeeService;
// 员工列表
@RequestMapping("lists")
public String list(Model model){
List<Employee> allEmployees = employeeService.getAllEmployees();
model.addAttribute("employeeList", allEmployees);
return "emplist";
}
}
文件上传
在数据库中,图片保存的是地址;
- 首先在项目下创建 photo 目录,用于保存上传的图片
在 yaml 文件中配置文件夹的路径信息:
photo: file: dir: # photo的绝对路径
一般项目无法直接访问 photo目录,可以利用spring.web.resources.static-locations 来保留该文件夹:
spring: web: resources: static-locations: classpath:/static/,file:${photo.file.dir} #暴露哪些资源可以通过项目名访问
- 文件时候,在 form表单还需满足:1)提交的方法method为post, 2)enctype提交方式为multipart/form-data
- 在EmployeeController 中,保存员工的信息为
// 保存员工信息
// Employee 用来接受员工的信息,MultipartFile用来接受图形的变量
@RequestMapping("/save")
public String saveEmployee(Employee employee, MultipartFile img) throws IOException {
String originalFilename = img.getOriginalFilename();
// 1. 处理头像文件的上传和修改文件名称
String fileNamePrefix = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
String fileNameSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
String newFileName = fileNamePrefix + fileNameSuffix;
img.transferTo(new File(realPath, newFileName));
// 2. 保存
employee.setPhoto(newFileName);
employeeService.save(employee);
return "redirect:/employee/lists";
}
前端页面显示,可以:
<img th:src="@{/}+ ${employee.photo}" width="60">
更新员工列表
在所有员工的列表中去跳转:
// 修改更新
@RequestMapping("/toUpdateEmployee")
public String toUpdateEmployee(int id,Model model){
// 1. 根据 id 查询
Employee employee = employeeService.getById(id);
// 2. 保存在
model.addAttribute("employee", employee);
return "updateEmp";
}
其中,前端传参,可以使用 thymeleaf的语法:
<a th:href="@{/employee/toUpdateEmployee(id=${employee.id})}">更新</a>
在toUpdateEmployee后面括号里面加上各种参数,thymeleaf会自动拼接。
在updateEmp中,表单数据提交到 /employee/update的请求中去:
// 接受Employee的信息和 头像的信息
@RequestMapping("/update")
public String update(Employee employee, MultipartFile img) throws IOException {
//1. 首先判断头像是否为空
if( !img.isEmpty() ){ // 加入用户更新头像
// 先删除旧的头像
String oldPhotoPath = employeeService.getById(employee.getId()).getPhoto();
File file = new File(realPath, oldPhotoPath);
if ( file.exists()){
file.delete(); // 如果存在首先先删除
}
// 2. 处理新的图片
String prefix = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
String suffix = img.getOriginalFilename().substring(img.getOriginalFilename().lastIndexOf("."));
String newFileName = prefix + suffix;
img.transferTo(new File(realPath, newFileName));
// 修改名称
employee.setPhoto(newFileName);
}
// 更新员工表
employeeService.updateEmployee(employee);
return "redirect:/employee/lists"; // 查询成功,跳转到员工列表
}
逻辑为:
1)先判断头像图片,即:img.isEmpty() 来判断图片更新的问题。
2)如果有图片先删除以前的图片,在更新现在的图片
3)去update
在updateEmp界面中:首先保证method为post,enctype为multipart/form-data:
<form th:action="@{/employee/update}" method="post" enctype="multipart/form-data">
同时设置隐藏域:
<input type="hidden" name="id" th:value="${employee.id}">
<input type="text" class="inputgri" name="name" th:value="${employee.name}"/>
<input type="hidden" th:value="${employee.photo}" name="photo">
用来提交表单数据。
更新删除
// 删除员工
@RequestMapping("/delete")
public String delete(Integer id){
// 首先查询到 photo
String photo = employeeService.getById(id).getPhoto();
//删除
employeeService.deleteEmployee(id);
//
File file = new File(realPath, photo);
if ( file.exists())
file.delete();
return "redirect:/employee/lists";
}
- 如果要删除员工,就要同时删除数据库里面的记录和服务器上的图片
安全退出
主要清除Session:
// 安全退出
@RequestMapping("/logout")
public String logout(HttpSession session){
session.invalidate();
return "redirect:/login";
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。