在 Web 后端开发领域,实现复杂业务功能是开发者的核心任务之一。本文将围绕 Tlias 系统的员工管理模块,详细介绍新增员工、事务管理以及文件上传功能的开发过程,通过实际代码示例帮助读者深入理解相关技术要点。
一、新增员工功能实现
新增员工功能涉及员工基本信息和工作经历信息的存储。在数据库设计上,使用emp表存储员工基本信息,emp_expr表存储员工工作经历信息。
(一)需求与接口设计
接口用于添加员工信息,请求路径为/emps,请求方式为POST,参数格式为application/json。参数包括用户名、姓名、性别等,其中用户名、姓名为必填项。
| 参数名称 | 类型 | 是否必须 | 备注 |
|---|---|---|---|
| username | string | 是 | 用户名,2 - 20 个字 |
| name | string | 是 | 姓名,2 - 10 个字 |
| gender | number | 非必须 | 性别,1 代表男,2 代表女 |
| image | string | 非必须 | 图像 |
| deptId | number | 非必须 | 部门 id |
| entryDate | string | 非必须 | 入职日期 |
| job | number | 非必须 | 职位,1 班主任,2 讲师,3 学工主管,4 教研主管,5 咨询师 |
| salary | number | 非必须 | 薪资 |
| exprList | object[] | 非必须 | 工作经历列表 |
(二)代码实现
- Controller 层:接收请求参数并调用 Service 方法。
@RestController
@RequestMapping("/emps")
public class EmpController {
@Autowired
private EmpService empService;
@PostMapping
public Result save(@RequestBody Emp emp) {
log.info("请求参数emp: {}", emp);
empService.save(emp);
return Result.success();
}
}
- Service 层:补全基础属性并调用 Mapper 方法保存员工基本信息和工作经历信息。
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Autowired
private EmpExprMapper empExprMapper;
@Override
public void save(Emp emp) {
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
empMapper.insert(emp);
Integer empId = emp.getId();
List<EmpExpr> exprList = emp.getExprList();
if (!CollectionUtils.isEmpty(exprList)) {
exprList.forEach(empExpr -> empExpr.setEmpId(empId));
empExprMapper.insertBatch(exprList);
}
}
}
- Mapper 层:定义 SQL 语句插入数据。
@Mapper
public interface EmpMapper {
@Insert("insert into emp(username, name, gender, phone, job, salary, image, entry_date, dept_id, create_time, update_time) values (#{username},#{name},#{gender},#{phone},#{job},#{salary},#{image},#{entryDate},#{deptId},#{createTime},#{updateTime})")
void insert(Emp emp);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpExprMapper">
<insert id="insertBatch">
insert into emp_expr (emp_id, begin, end, company, job) values
<foreach collection="exprList" item="expr" separator=",">
(#{expr.empId}, #{expr.begin}, #{expr.end}, #{expr.company}, #{expr.job})
</foreach>
</insert>
</mapper>
二、事务管理
事务是一组操作的集合,要么全部成功,要么全部失败。在新增员工功能中,若保存员工基本信息成功但保存工作经历失败,会导致数据不一致,因此需要事务管理。
(一)事务概念与操作
事务控制主要包括开启事务、提交事务和回滚事务。在 MySQL 中,默认事务是自动提交的,可使用start transaction或begin开启事务,commit提交事务,rollback回滚事务。
(二)Spring 事务管理
- @Transactional 注解:用于将方法交给 Spring 进行事务管理。可添加在业务层的方法、类或接口上。方法执行前开启事务,成功执行完毕提交事务,出现异常回滚事务。
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Autowired
private EmpExprMapper empExprMapper;
@Transactional
@Override
public void save(Emp emp) {
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
empMapper.insert(emp);
int i = 1 / 0;
Integer empId = emp.getId();
List<EmpExpr> exprList = emp.getExprList();
if (!CollectionUtils.isEmpty(exprList)) {
exprList.forEach(empExpr -> empExpr.setEmpId(empId));
empExprMapper.insertBatch(exprList);
}
}
}
- 事务传播行为:控制一个事务方法被另一个事务方法调用时的事务控制方式。常见传播行为如
REQUIRED(默认,有事务则加入,无则创建新事务)、REQUIRES_NEW(总是创建新事务)等。
三、文件上传功能
文件上传是将本地文件上传到服务器的过程,在项目中应用广泛。
(一)基于 HTML 和 Spring Boot 的文件上传
前端通过form表单上传文件,设置enctype="multipart/form-data"。后端在 Controller 层接收文件。
<form action="/upload" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="name"><br>
年龄: <input type="text" name="age"><br>
图像: <input type="file" name="file"><br>
<input type="submit" value="上传文件" name="submit">
</form>
@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result handleFileUpload(String name, Integer age, MultipartFile file) {
log.info("文件上传:{}", file);
return Result.success();
}
}
(二)本地存储文件
将接收到的文件存储在本地磁盘目录,需保证文件名唯一。
private static final String UPLOAD_DIR = "D:/upload/";
@PostMapping("/upload")
public Result handleFileUpload(MultipartFile file) throws Exception {
log.info("文件上传:{}", file);
String uniqueFileName = generateUniqueFileName(file.getOriginalFilename());
file.transferTo(new File(UPLOAD_DIR + uniqueFileName));
return Result.success();
}
private String generateUniqueFileName(String originalFilename) {
String randomStr = UUID.randomUUID().toString().replaceAll("-", "");
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
return randomStr + extension;
}
(三)阿里云 OSS 存储文件
- 使用步骤:注册阿里云并实名认证,充值,开通对象存储服务(OSS),创建 bucket,获取并配置 AccessKey,参照官方 SDK 编写代码。
- 代码实现:引入阿里云 OSS 文件上传工具类,在 Controller 层实现上传接口。
@Autowired
private AliyunOSSOperator aliyunOSSOperator;
@PostMapping("/upload")
public Result upload(MultipartFile file) throws Exception {
log.info("文件上传:{}", file);
String url = aliyunOSSOperator.upload(file.getBytes(), file.getOriginalFilename());
return Result.success(url);
}
配置文件注入参数,可使用@Value或@ConfigurationProperties注解。
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: java-ai
// 使用@Value注解
@Component
public class AliyunOSSOperator {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
// ... 省略
}
// 使用@ConfigurationProperties注解
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOSSProperties {
private String endpoint;
private String bucketName;
}
@Component
public class AliyunOSSOperator {
@Autowired
private AliyunOSSProperties aliyunOSSProperties;
public String upload(byte[] content, String originalFilename) throws Exception {
String endpoint = aliyunOSSProperties.getEndpoint();
String bucketName = aliyunOSSProperties.getBucketName();
// ... 省略
}
}
通过以上对新增员工、事务管理和文件上传功能的开发介绍,希望读者能掌握 Web 后端开发中这些关键功能的实现方法,为实际项目开发提供有力支持。
1776

被折叠的 条评论
为什么被折叠?



