尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Day47(17)-F:\硕士阶段\Java\课程代码\后端\web-ai-code\web-ai-project02

Day47(17)-F:\硕士阶段\Java\课程代码\后端\web-ai-code\web-ai-project02
📅 发布时间:2026/6/21 1:48:02

文件上传

服务器搭建

image-20251124131949006

云服务

image-20251124132052428

image-20251124132218894

image-20251124132551370

LTAI5t5hEbLq6RPAc5ihjWEH
vY9VD0hh9q7TcFU2H9AP9x8FPEA8hr
配置环境变量
set OSS_ACCESS_KEY_ID=LTAI5t5hEbLq6RPAc5ihjWEH
set OSS_ACCESS_KEY_SECRET=vY9VD0hh9q7TcFU2H9AP9x8FPEA8hr
设置使其生效
setx OSS_ACCESS_KEY_ID "%OSS_ACCESS_KEY_ID%"
setx OSS_ACCESS_KEY_SECRET "%OSS_ACCESS_KEY_SECRET%"
验证是否生效
echo %OSS_ACCESS_KEY_ID%
echo %OSS_ACCESS_KEY_SECRET%

阿里云搭建相关视频在107集

image-20251124142322620

image-20251124142401623

package com.itheima.utils;import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;@Component
public class AliyunOSSOperator {private String endpoint = "https://oss-cn-beijing.aliyuncs.com";private String bucketName = "java-ai-01-david";private String region = "cn-beijing";public String upload(byte[] content, String originalFilename) throws Exception {// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。//获取当前系统日期的字符串,格式为 yyyy/MMString dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));//生成一个新的不重复的文件名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;}}
package com.itheima.controller;import com.itheima.pojo.Result;
import com.itheima.utils.AliyunOSSOperator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.util.UUID;@Slf4j
@RestController
public class UploadController {
//    /**
//     * 本地磁盘存储,不推荐
//     * @param name
//     * @param age
//     * @param file
//     * @return
//     * @throws IOException
//     */
//    @PostMapping("/upload")
//    public Result upload(String name, Integer age, MultipartFile file) throws IOException {
//        log.info("接收的参数:{},{},{}",name,age,file);
//        //获取原始文件名
//        String originalFilename = file.getOriginalFilename();
//        //新的文件名
//        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//        String newFileName = UUID.randomUUID().toString() + extension;
//        //保存文件
//        //file.transferTo(new File("F:/images/"+originalFilename));
//        file.transferTo(new File("F:/images/"+newFileName));
//        return Result.success();
//    }@Autowiredprivate AliyunOSSOperator aliyunOSSOperator;@PostMapping("/upload")public Result upload(MultipartFile file) throws Exception {log.info("文件上传:{}",file.getOriginalFilename());//将文件交给OSS存储管理String url = aliyunOSSOperator.upload(file.getBytes(), file.getOriginalFilename());log.info("文件上传到OSS,url:"+url);return Result.success(url);}
}

image-20251124151437001

image-20251124151642118

#阿里云OSS
aliyun:oss:endpoint: https://oss-cn-beijing.aliyuncs.combucketName: java-ai-01-davidregion: cn-beijing
package com.itheima.utils;import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;@Component
public class AliyunOSSOperator {//    private String endpoint = "https://oss-cn-beijing.aliyuncs.com";
//    private String bucketName = "java-ai-01-david";
//    private String region = "cn-beijing";@Value("${aliyun.oss.endpoint}")private String endpoint ;@Value("${aliyun.oss.bucketName}")private String bucketName ;@Value("${aliyun.oss.region}")private String region ;public String upload(byte[] content, String originalFilename) throws Exception {// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。//获取当前系统日期的字符串,格式为 yyyy/MMString dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));//生成一个新的不重复的文件名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;}}

image-20251124152520710

image-20251124152632534

image-20251124153020232

package com.itheima.utils;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOSSProperties {private String endpoint;private String bucketName;private String region;
}
package com.itheima.utils;import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;@Component
public class AliyunOSSOperator {//    private String endpoint = "https://oss-cn-beijing.aliyuncs.com";
//    private String bucketName = "java-ai-01-david";
//    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 ;//方式二:@Autowiredprivate AliyunOSSProperties aliyunOSSProperties;public String upload(byte[] content, String originalFilename) throws Exception {String endpoint = aliyunOSSProperties.getEndpoint();String bucketName = aliyunOSSProperties.getBucketName();String region = aliyunOSSProperties.getRegion();// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Object完整路径,例如202406/1.png。Object完整路径中不能包含Bucket名称。//获取当前系统日期的字符串,格式为 yyyy/MMString dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM"));//生成一个新的不重复的文件名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;}}

image-20251124153707914

删除员工

image-20251124154052815

@DeleteMapping
public  Result delete(@RequestParam List<Integer> ids){log.info("批量删除员工:{}", ids);empService.delete(ids);return Result.success();
}
@Transactional(rollbackFor = {Exception.class})
@Override
public void delete(List<Integer> ids) {//删除员工的基本信息empMapper.deleteByIds(ids);//删除员工的工作经历信息empExprMapper.deleteByEmpIds(ids);}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpExprMapper">
<!--    批量保存员工工作经历foreach:collection:遍历的集合item:遍历出来的元素的名字separator:每次循环之间的分隔符
--><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><delete id="deleteByEmpIds">delete from emp_expr where emp_id in<foreach collection="empIds" item="Id" separator="," open="(" close=")">#{Id}</foreach></delete>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--    批量删除员工的基本信息--><delete id="deleteByIds">delete from emp where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete><select id="list" resultType="com.itheima.pojo.Emp">select e.*,d.name deptName from emp e left join dept d on e.dept_id = d.id<where><if test="name != null and name != ''">e.name like concat('%',#{name},'%')</if><if test="gender != null">and e.gender = #{gender}</if><if test="begin != null and end != null">and entry_date between #{begin} and #{end}</if></where>order by e.update_time desc</select>
</mapper>

Spring 对List类型的参数,无论参数名是否一致,都必须显式添加@RequestParam注解才能完成绑定,不存在 “省略注解也能生效” 的情况。下面详细拆解原因和修正方案。

一、为什么这段代码不加注解会失效?

  1. Spring 的参数绑定规则限制

    Spring 的无注解自动绑定仅支持基本类型、包装类、String、数组等「简单类型」,而List是集合容器类型,不在自动绑定的范围内。即使参数名names与前端传入的参数名完全一致,Spring 也无法识别 “将请求中的names参数封装为List<String>”,最终入参names会是null。

  2. 实际运行的表现

    若执行这段代码,前端请求/list?names=张三&names=李四,后端接收到的names值为null,返回结果会是List参数:null,而非预期的List参数:[张三, 李四]。

二、正确的写法(必须加@RequestParam)

想要让List<String> names正确绑定前端参数,必须显式添加@RequestParam注解,这是唯一的正确方式:java运行

@GetMapping("/list")
public String getList(@RequestParam List<String> names) {return "List参数:" + names;
}

此时前端请求/list?names=张三&names=李四,后端才能正确接收并封装为List<String>,返回List参数:[张三, 李四]。

三、容易混淆的 “例外情况”:数组类型可省略注解

如果将入参改为数组类型String[] names,则可以省略@RequestParam,因为数组属于 Spring 的「简单类型」,支持无注解自动绑定:java运行

// ✅ 数组类型:参数名一致,可省略@RequestParam,绑定正常
@GetMapping("/list")
public String getList(String[] names) {return "数组参数:" + Arrays.toString(names);
}

前端请求/list?names=张三&names=李四,会返回数组参数:[张三, 李四],这是数组与 List 的核心区别,也是最容易产生误解的点。

image-20251124163513366

修改员工

  1. 查询回显
  2. 修改数据

image-20251124165159019

image-20251124170829269

image-20251124171233043

image-20251124171613175

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--    批量删除员工的基本信息--><delete id="deleteByIds">delete from emp where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete><select id="list" resultType="com.itheima.pojo.Emp">select e.*,d.name deptName from emp e left join dept d on e.dept_id = d.id<where><if test="name != null and name != ''">e.name like concat('%',#{name},'%')</if><if test="gender != null">and e.gender = #{gender}</if><if test="begin != null and end != null">and entry_date between #{begin} and #{end}</if></where>order by e.update_time desc</select><!--    定义resultMap--><resultMap id="empResultMap" type="com.itheima.pojo.Emp"><id column="id" property="id"/><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"/><!--        封装工作经历--><collection property="exprList" ofType="com.itheima.pojo.EmpExpr"><id column="ee_id"  property="id"/><result column="ee_empid"  property="empId"/><result column="ee_begin"  property="begin"/><result column="ee_end"  property="end"/><result column="ee_company"  property="company"/><result column="ee_job"  property="job"/></collection></resultMap>
<!--    根据ID查询员工的基本信息和员工基本工作经历信息--><select id="getById" resultMap="empResultMap">selecte.*,ee.id ee_id,ee.emp_id ee_empid,ee.begin ee_begin,ee.end ee_end,ee.company ee_company,ee.job ee_jobfrom emp e left join emp_expr ee on e.id = ee.emp_idwhere e.id =#{id};</select>
</mapper>

image-20251124173549125

image-20251124174309563

@PutMapping
public Result update(@RequestBody Emp emp){log.info("修改员工:{}",emp);empService.update(emp);return Result.success(emp);
}
/*** 修改员工* @param emp*/
@Transactional(rollbackFor = {Exception.class})
@Override
public void update(Emp emp) {//1.根据ID修改员工的基本信息emp.setUpdateTime(LocalDateTime.now());empMapper.updateById(emp);//2.根据ID修改员工的工作经历信息//2.1先根据员工ID删除原有的工作经历empExprMapper.deleteByEmpIds(Arrays.asList(emp.getId()));//2.2再添加List<EmpExpr> exprList = emp.getExprList();if (!CollectionUtils.isEmpty(exprList)){exprList.forEach(empExpr -> {empExpr.setEmpId(emp.getId());});empExprMapper.insertBatch(exprList);}
}

优化

动态SQL

image-20251124181325226

<!--    根据ID更新员工基本工作经历信息-->
<!--    set标签:mybatis中动态标签:自动生成set关键字;会自动删除掉更新字段后多余的逗号--><update id="updateById">UPDATE emp<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="job != null">job = #{job},</if><if test="salary != null">salary = #{salary},</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标签

  1. :自动删掉多余逗号;自动生成set关键字
  2. :自动删掉and和or

image-20251124182757416

异常管理

信息统计

相关新闻

  • 2025年本地好评恒温恒湿箱品牌TOP10,砂尘试验箱/盐水喷雾试验箱及各种老化房/恒温恒湿试验箱/高低温交变量热试验箱恒温恒湿箱公司推荐
  • 2025年11月GEO服务商推荐评测报告:从稳定性到AI能力的解决方案剖析
  • 2025年11月GEO优化服务商推荐报告:从稳定性到AI能力的解决方案剖析

最新新闻

  • 如何快速实现智能音频转文字:Faster-Whisper-GUI 终极指南 [特殊字符]
  • 终极隐身指南:3分钟学会在英雄联盟和无畏契约中完美隐身,重新掌控你的游戏社交
  • 2026哈尔滨防水补漏避坑指南:卫生间/厨房/阳台/屋顶/地下室漏水检测维修全攻略,正规施工+透明报价+口碑榜靠谱服务商推荐 - 安佳防水
  • d2s-editor:如何用Web技术重塑暗黑破坏神2存档编辑体验?
  • 如何用Python构建高效的Bilibili评论爬虫系统:从零到批量采集实战指南
  • 3分钟终极指南:Windows和Office一键智能激活解决方案

日新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号