4个技术点
点一
阿里云配置放入配置文件统一管理
1.注入外部配置文件中的配置项的两种方式?
@Value //一个属性一个属性的注入
@ConfigurationProperties //批量将多个属性注入bean对象中
2.两种方式各自的使用场景?
如果属性较少,建议@Value注入
如果属性较多,考虑复用,建议使用
以上是该功能需要背过记住的两个注解★★★
代码如下:
#阿里云OSS //配置文件application.yml
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: java-426-ai
region: cn-beijing
@Component //配置阿里云,后面上传图片放在阿里云OSS上存储 //工具类AliyunOSSOperator
public class AliyunOSSOperator {
@Autowired
private OperatorPropertie operatorPropertie;
//修改一:改成自己的OSS服务器中的bucket对应的域名中
//private String endpoint = "https://oss-cn-beijing.aliyuncs.com";
//修改二:改成自己的OSS服务器中的bucket名称
//private String bucketName = "java-426-ai";
//修改三:改成自己的OSS服务器所属区域
//private String region = "cn-beijing";
/*优化
为了方便统一管理 配置少的时候可以用@Value来读取配置文件中的值
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
@Value("${aliyun.oss.region}")
private String region;
*/
/* 用@configpro注解
需要单独来一个配置类,然后使用get方法获取配置文件中的值
*/
public String upload(byte[] content, String originalFilename) throws Exception {
String endpoint = operatorPropertie.getEndpoint();
String bucketName = operatorPropertie.getBucketName();
String region = operatorPropertie.getRegion();
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。
//获取当前系统日期的字符串,格式为 yyyy/MM
String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM")); //2025/04
//生成一个新的不重复的文件名
String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
String objectName = dir + "/" + newFileName;
// 创建OSSClient实例。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
} finally {
ossClient.shutdown();
}
return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName;
}
}
@Data //处理读取方式的前缀的工具类 OperatorPropertie
@ConfigurationProperties(prefix = "aliyun.oss")//prefix 前缀
@Component
//@ConfigurationProperties 读取方式
public class OperatorPropertie {
private String endpoint;
private String bucketName;
private String region;
}
点二
删除员工数据的功能
1.@RequestParam("形参变量") //只要有参数,就必须加在Controller请求方法的参数上加上这个
2.@Transactional("rollbackFor = Exception.class") //service方法上开启事务管理,一起成功一起失败
3.@Param("形参变量") //只要有参数,就必须在Mapper方法参数上加这个
4. <delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id} //id处是mapper中的删除方法。collection是mapper方法的形参。
</foreach> //item是变量名随便取值 open separator close三个属性需要记住
</delete> //foreach记住!!!
以上是该功能需要背过记住的四个点★★★★★
功能分析

具体实现代码如下:
/**
* 三、批量删除 员工请求 Controller
* @param ids
* @return
*/
@DeleteMapping("/emps")
public Result deleteEmp(@RequestParam("ids") List<Integer> ids)
{ //数组 集合都行
empService.deleteEmp(ids);
return Result.success();
}
/**
* 批量删除员工的业务功能 Service
* impl
* @param ids
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void deleteEmp(List<Integer> ids) {
//删除员工基本信息
empMapper.deleteByIds(ids);
//删除员工工作经历
empExprMapper.deleteByEmpIds(ids);
}
/**
* 删除员工数据 Mapper
* @param ids interface
*/
void deleteByIds(@Param("ids") List<Integer> ids);
//ExprMapper
void deleteByEmpIds(@Param("ids") List<Integer> ids);
<delete id="deleteByIds"> //emp.xml
delete from emp where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<delete id="deleteByEmpIds"> //empexpr.xml
delete from emp_expr where emp_id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
点三
修改员工数据的功能
1.员工数据用emp和emp_expr俩表存储的,员工信息用Emp实体类返回而员工经历需要特殊处理(实体封装的集合)
<resultMap id="baseEmpMap" type="com.itheima.pojo.Emp">
<id column="id" property="id"/> //员工信息可以用实体类Emp中的基本属性来接收
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="name" property="name"/>
<result column="gender" property="gender"/>
<result column="phone" property="phone"/>
<result column="job" property="job"/>
<result column="salary" property="salary"/>
<result column="image" property="image"/>
<result column="entry_date" property="entryDate"/>
<result column="dept_id" property="deptId"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
//员工经历则需要用Emp中的exprList集合来接收
<collection property="exprList" ofType="com.itheima.pojo.EmpExpr">
<id column="ee_id" property="id"/>
<result column="ee_company" property="company"/>
<result column="ee_job" property="job"/>
<result column="ee_begin" property="begin"/>
<result column="ee_end" property="end"/>
<result column="ee_empid" property="empId"/>
</collection>
</resultMap>
<select id="getEmpWithEmpExprById" resultMap="baseEmpMap">
SELECT e.*, //(俩表)有些属性对不上:故记住mybatis提供的方案:属性的特殊处理resultMap★★★
ee.id ee_id,
ee.emp_id ee_emp_id,
ee.begin ee_begin,
ee.end ee_end,
ee.company ee_company,
ee.job ee_job
FROM emp e
LEFT JOIN emp_expr ee ON ee.emp_id = e.id
WHERE e.id = #{id}
</select>
@注解可以抽出请求路径更方便
@PathVariable("") //接收路径参数的注解 ★
2.修改员工数据
动态sql的标签,动态sql能够让对应的功能更加灵活扩展性高
<!-- 修改员工信息 -->
<update id="updateById">
update emp
<!-- 优化修改功能: 只修改几个时用if来判断一些情况让修改功能更加灵活更有扩展性 -->
<!-- set标签的作用是: 消除sql语句中的, -->
<set>
<if test="username != null and username !=''">username=#{username},</if>
<if test="password != null and password !=''">password=#{password},</if>
<if test="name != null and name !=''">name=#{name},</if>
<if test="gender != null">gender=#{gender},</if>
<if test="phone != null and phone !=''">phone=#{phone},</if>
<if test="salary != null">salary=#{salary},</if>
<if test="job != null">job=#{job},</if>
<if test="image != null and image !=''">image=#{image},</if>
<if test="entryDate != null">entry_date=#{entryDate},</if>
<if test="deptId != null">dept_id=#{deptId},</if>
<if test="updateTime != null">update_time=#{updateTime},</if>
</set>
where id=#{id}
</update>
注意: 当mapper中的方法上没有加sql注解来操作数据库的话
就需要在mapper.xml文件中配置sql语句(一般处理较复杂的情况)
小技巧: 点mapper方法左侧的小鸟即可快速移动到mapper.xml修改属性的方法名(文件太多时不容易乱)
以上是总结今天修改功能学到的两个点和遇到的问题小技巧
下面是功能的具体实现:
/** Controller
* 四、修改员工信息 ->1.数据回显(映射回显)
* @param id
* @return
*/
@GetMapping("/emps/{id}")
public Result getByID(@PathVariable Integer id){
Emp emp = empService.getEmpWithExprById(id);
return Result.success(emp);
}
//2.修改请求->修改
@PutMapping("/emps")
public Result updateEmp(@RequestBody Emp emp) throws Exception {
empService.updateEmp(emp);
return Result.success();
}
/**
* 修改员工信息:
* 一次性把员工基本信息和员工工作经历都查询出来
*
* @param id
* @return
*/
@Override
public Emp getEmpWithExprById(Integer id) {
return empMapper.getEmpWithEmpExprById(id);
}
/**
* 修改员工信息:
* 修改的逻辑->先删除后新增
*
* @param emp
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void updateEmp(Emp emp) {
//1.更新员工的基本信息
emp.setUpdateTime(LocalDateTime.now());
empMapper.updateById(emp);
//2.删除此员工的工作经历
Integer id = emp.getId();
empExprMapper.deleteByEmpIds(Arrays.asList(id));
//3.新增此员工的工作经历
if (!CollectionUtils.isEmpty(emp.getExprList())) {
emp.getExprList().forEach(empExpr -> empExpr.setEmpId(id));
empExprMapper.insertBatch(emp.getExprList());
}
}
//映射回显 empmapper
Emp getEmpWithEmpExprById(Integer id);
//简单回显
// @Select("select * from emp where id=#{id}")
// Emp getById(Integer id);
void updateById(Emp emp);
<!-- 修改员工信息 empmapper.xml-->
<update id="updateById">
update emp
<!-- 优化修改功能: 单个修改时更加灵活更有扩展性 -->
<!-- set标签的作用是: 消除sql语句中的, -->
<set>
<if test="username != null and username !=''">username=#{username},</if>
<if test="password != null and password !=''">password=#{password},</if>
<if test="name != null and name !=''">name=#{name},</if>
<if test="gender != null">gender=#{gender},</if>
<if test="phone != null and phone !=''">phone=#{phone},</if>
<if test="salary != null">salary=#{salary},</if>
<if test="job != null">job=#{job},</if>
<if test="image != null and image !=''">image=#{image},</if>
<if test="entryDate != null">entry_date=#{entryDate},</if>
<if test="deptId != null">dept_id=#{deptId},</if>
<if test="updateTime != null">update_time=#{updateTime},</if>
</set>
where id=#{id}
</update>
修改-的回显功能还有第二种方法更简单一些,具体可以对比一下想用哪个都行
动态sql方法

俩sql的方法
[![]
功能思路

点四项目异常
@RestControllerAdvice //加在类上 加强异常。和下面注解一起使用
@ExceptionHandler(Exception.class) //加在方法上,每个方法可以精准的处理对应的异常
具体代码实现:
@RestControllerAdvice
public class GlobalExceptionAdvice { //写一个异常处理器,注意放在启动类同级目录下
@ExceptionHandler(Exception.class)
public Result allException(Exception e){ //所有异常
e.printStackTrace(); //报错打印到后台
return Result.error("服务器异常,请联系管理员"); //Result统一数据格式
}
@ExceptionHandler(DuplicateKeyException.class)
public Result allException(DuplicateKeyException e){ //有重复值的异常
e.printStackTrace(); //报错打印到后台
if (e.getMessage().contains("emp.username")){
return Result.error("您新增的用户名已存在");
}
if (e.getMessage().contains("emp.phone")){
return Result.error("对应手机号的用户已存在");
}
if (e.getMessage().contains("emp.image")){
return Result.error("对应手已存在");
}
return Result.error("数据已存在"); //Result统一数据格式
}
}
效果如下:

注意点:
全局异常处理器的包要 和启动类同级才能扫描到
推荐阅读:






文章有(0)条网友点评