环境搭建:
开发规范
接口风格-Restful:
统一响应结果-Result:
开发流程:
第一步应该根据需求定义表结构和定义接口文档
注意:
本文代码从上往下一直添加功能,后面的模块下的代码包括前面的模块,并不是某个模块中的代码只有当前功能。
部门管理
查询部门:
思路:
代码:
Dept实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
private int id;
private String name;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
Controller层:
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@GetMapping("/depts")
public Result list() {
log.info("查询全部部门信息");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
}
(注解@Slf4j后可以直接使用log.info输出日志信息)
Service层:
接口:
public interface DeptService {
List<Dept> list();
}
实现类:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
return deptMapper.list();
}
}
Mapper层:
@Mapper
public interface DeptMapper {
@Select("select * from dept")
List<Dept> list();
}
Postman测试结果:
删除部门:
思路:
代码:
Controller层:
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
@GetMapping("/depts")
public Result list() {
log.info("查询全部部门信息");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @return
*/
@DeleteMapping("/depts/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除id为" + id +"的部门");
deptService.delete(id);
return Result.success();
}
}
Service层:
接口:
public interface DeptService {
/**
* 查询部门信息
* @return
*/
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
void delete(Integer id);
}
实现类:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
/**
* 查询部门信息
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根据id删除部门
* @param id
*/
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);
}
}
Mapper层:
@Mapper
public interface DeptMapper {
/**
* 查询部门信息
* @return
*/
@Select("select * from dept")
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
@Delete("delete from dept where id = #{id}")
void deleteById(Integer id);
}
Postman测试结果:
新增部门:
思路:
代码:
Controller层:
@Slf4j
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
@GetMapping("/depts")
public Result list() {
log.info("查询全部部门信息");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @return
*/
@DeleteMapping("/depts/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除id为" + id +"的部门");
deptService.delete(id);
return Result.success();
}
/**
* 新增部门
* @param dept
* @return
*/
@PostMapping("/depts")
public Result insert(@RequestBody Dept dept) {
log.info("添加部门:" + dept);
deptService.add(dept);
return Result.success();
}
}
Service层:
接口:
public interface DeptService {
/**
* 查询部门信息
* @return
*/
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
void delete(Integer id);
/**
* 新增部门
* @param dept
*/
void add(Dept dept);
}
实现类:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
/**
* 查询部门信息
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根据id删除部门
* @param id
*/
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);
}
/**
* 新增部门
* @param dept
*/
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
}
Mapper层:
@Mapper
public interface DeptMapper {
/**
* 查询部门信息
* @return
*/
@Select("select * from dept")
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
@Delete("delete from dept where id = #{id}")
void deleteById(Integer id);
/**
* 新增部门
* @param dept
*/
@Insert("insert into dept(name,create_time,update_time) values (#{name},#{createTime}, #{updateTime})")
void insert(Dept dept);
}
Postman测试结果:
优化代码:
Controller层优化:
路径中/depts每次都出现,可以将它提取出来
优化后代码:
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
@GetMapping
public Result list() {
log.info("查询全部部门信息");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除id为" + id +"的部门");
deptService.delete(id);
return Result.success();
}
/**
* 新增部门
* @param dept
* @return
*/
@PostMapping
public Result insert(@RequestBody Dept dept) {
log.info("添加部门:" + dept);
deptService.add(dept);
return Result.success();
}
}
根据id查找部门:
代码:
Controller层:
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
@GetMapping
public Result list() {
log.info("查询全部部门信息");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除id为" + id +"的部门");
deptService.delete(id);
return Result.success();
}
/**
* 新增部门
* @param dept
* @return
*/
@PostMapping
public Result insert(@RequestBody Dept dept) {
log.info("添加部门:" + dept);
deptService.add(dept);
return Result.success();
}
/**
* 根据id查找部门
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
log.info("查询id为"+ id + "的部门信息");
Dept dept = deptService.get(id);
return Result.success(dept);
}
}
Service层:
接口:
public interface DeptService {
/**
* 查询部门信息
* @return
*/
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
void delete(Integer id);
/**
* 新增部门
* @param dept
*/
void add(Dept dept);
/**
* 根据id查找部门
* @param id
*/
Dept get(Integer id);
}
实现类:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
/**
* 查询部门信息
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根据id删除部门
* @param id
*/
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);
}
/**
* 新增部门
* @param dept
*/
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
/**
* 根据id查找部门
* @param id
*/
@Override
public Dept get(Integer id) {
return deptMapper.getById(id);
}
}
Mapper层:
@Mapper
public interface DeptMapper {
/**
* 查询部门信息
* @return
*/
@Select("select * from dept")
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
@Delete("delete from dept where id = #{id}")
void deleteById(Integer id);
/**
* 新增部门
* @param dept
*/
@Insert("insert into dept(name,create_time,update_time) values (#{name},#{createTime}, #{updateTime})")
void insert(Dept dept);
/**
* 根据id查找部门
* @param id
* @return
*/
@Select("select * from dept where id = #{id}")
Dept getById(Integer id);
}
Postman测试结果:
修改部门:
代码:
Controller层:
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
@GetMapping
public Result list() {
log.info("查询全部部门信息");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除id为" + id +"的部门");
deptService.delete(id);
return Result.success();
}
/**
* 新增部门
* @param dept
* @return
*/
@PostMapping
public Result insert(@RequestBody Dept dept) {
log.info("添加部门:" + dept);
deptService.add(dept);
return Result.success();
}
/**
* 根据id查找部门
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
log.info("查询id为"+ id + "的部门信息");
Dept dept = deptService.get(id);
return Result.success(dept);
}
/**
* 修改部门
* @param dept
* @return
*/
@PutMapping
public Result update(@RequestBody Dept dept) {
log.info("修改部门:" + dept);
deptService.update(dept);
return Result.success();
}
}
Service层:
接口:
public interface DeptService {
/**
* 查询部门信息
* @return
*/
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
void delete(Integer id);
/**
* 新增部门
* @param dept
*/
void add(Dept dept);
/**
* 根据id查找部门
* @param id
*/
Dept get(Integer id);
/**
* 修改部门
* @param dept
*/
void update(Dept dept);
}
实现类:
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
/**
* 查询部门信息
* @return
*/
@Override
public List<Dept> list() {
return deptMapper.list();
}
/**
* 根据id删除部门
* @param id
*/
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);
}
/**
* 新增部门
* @param dept
*/
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
/**
* 根据id查找部门
* @param id
*/
@Override
public Dept get(Integer id) {
return deptMapper.getById(id);
}
/**
* 修改部门
* @param dept
*/
@Override
public void update(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
}
Mapper层:
@Mapper
public interface DeptMapper {
/**
* 查询部门信息
* @return
*/
@Select("select * from dept")
List<Dept> list();
/**
* 根据id删除部门
* @param id
*/
@Delete("delete from dept where id = #{id}")
void deleteById(Integer id);
/**
* 新增部门
* @param dept
*/
@Insert("insert into dept(name,create_time,update_time) values (#{name},#{createTime}, #{updateTime})")
void insert(Dept dept);
/**
* 根据id查找部门
* @param id
* @return
*/
@Select("select * from dept where id = #{id}")
Dept getById(Integer id);
/**
* 修改部门
* @param dept
*/
@Update("update dept set name = #{name},create_time = #{createTime},update_time = #{updateTime} where id = #{id}")
void update(Dept dept);
}
Postman测试结果:
员工管理:
分页查询:
思路:
代码:
Emp实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer id;
private String username;
private String password;
private String name;
private Short gender;
private String image;
private Short job;
private LocalDate entryDate;
private Integer deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
Controller层:
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
@GetMapping
public Result getPage(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize) {
log.info("每页记录数:{},查询页码:{}",pageSize,page);
PageBean pb = empService.getPage(page,pageSize);
return Result.success(pb);
}
}
Service层:
接口:
public interface EmpService {
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
PageBean getPage(Integer page, Integer pageSize);
}
实现类:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
/**
* 分页查询,获取列表数据
* @param page
* @param pageSize
* @return
*/
@Override
public PageBean getPage(Integer page, Integer pageSize) {
Long total = empMapper.getTotal();
Long start = (long) ((page - 1) * pageSize);
List<Emp> rows = empMapper.getRows(start,pageSize);
PageBean pageBean = new PageBean(total,rows);
return pageBean;
}
}
Mapper层:
@Mapper
public interface EmpMapper {
/**
* 获取总记录数
* @return
*/
@Select("select count(*) from emp;")
Long getTotal();
/**
* 分页查询,获取列表数据
* @param start
* @param pageSize
* @return
*/
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time\n" +
"from emp limit #{start},#{pageSize}")
List<Emp> getRows(Long start, Integer pageSize);
}
Postman测试结果:
分页插件-PageHelper:
由下图可以看到原始方式分页查询步骤固定,而且代码繁琐,我们可以使用PageHelper插件简化代码。
代码演示:
导入依赖:
<!--PageHelper分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
修改代码:
Mapper层:
@Mapper
public interface EmpMapper {
// /**
// * 获取总记录数
// * @return
// */
// @Select("select count(*) from emp")
// Long getTotal();
//
// /**
// * 分页查询,获取列表数据
// * @param start
// * @param pageSize
// * @return
// */
// @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time\n" +
// "from emp limit #{start},#{pageSize}")
// List<Emp> getRows(Long start, Integer pageSize);
/**
* 使用PageHelper插件来进行分页查询
*/
@Select("select * from emp")
List<Emp> list();
}
Service层:
实现类:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
// /**
// * 分页查询,获取列表数据
// * @param page
// * @param pageSize
// * @return
// */
// @Override
// public PageBean getPage(Integer page, Integer pageSize) {
// Long total = empMapper.getTotal();
// Long start = (long) ((page - 1) * pageSize);
// List<Emp> rows = empMapper.getRows(start,pageSize);
// PageBean pageBean = new PageBean(total,rows);
// return pageBean;
// }
/**
* 使用PageHelper分页插件进行分页查询
*/
@Override
public PageBean getPage(Integer page, Integer pageSize) {
//1.设置分页参数
PageHelper.startPage(page, pageSize);
//2.执行查询
List<Emp> empList = empMapper.list();
Page<Emp> p = (Page<Emp>) empList;
//3.封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
}
分页条件查询:
措施:
代码:
Controller层:
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
@GetMapping
public Result getPage(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
log.info("每页记录数:{},查询页码:{}",pageSize,page);
PageBean pb = empService.getPage(page,pageSize,name,gender,begin,end);
return Result.success(pb);
}
}
Service层:
接口:
public interface EmpService {
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);
}
实现类:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
// /**
// * 分页查询,获取列表数据
// * @param page
// * @param pageSize
// * @return
// */
// @Override
// public PageBean getPage(Integer page, Integer pageSize) {
// Long total = empMapper.getTotal();
// Long start = (long) ((page - 1) * pageSize);
// List<Emp> rows = empMapper.getRows(start,pageSize);
// PageBean pageBean = new PageBean(total,rows);
// return pageBean;
// }
/**
* 使用PageHelper分页插件进行分页查询
*/
@Override
public PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
//1.设置分页参数
PageHelper.startPage(page, pageSize);
//2.执行查询
List<Emp> empList = empMapper.list(name,gender,begin,end);
Page<Emp> p = (Page<Emp>) empList;
//3.封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
}
Mapper层:
@Mapper
public interface EmpMapper {
// /**
// * 获取总记录数
// * @return
// */
// @Select("select count(*) from emp")
// Long getTotal();
//
// /**
// * 分页查询,获取列表数据
// * @param start
// * @param pageSize
// * @return
// */
// @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time\n" +
// "from emp limit #{start},#{pageSize}")
// List<Emp> getRows(Long start, Integer pageSize);
/**
* 使用PageHelper插件来进行分页查询
*/
//动态SQL
List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
}
动态SQL:
xml文件:
<?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.han.mapper.EmpMapper">
<select id="list" resultType="com.han.pojo.Emp">
select id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time
from emp
<where>
<if test="name != null and name != ''">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time DESC
</select>
</mapper>
Postman测试结果:
删除员工:
代码:
Controller层:
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
@GetMapping
public Result getPage(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
log.info("每页记录数:{},查询页码:{}",pageSize,page);
PageBean pb = empService.getPage(page,pageSize,name,gender,begin,end);
return Result.success(pb);
}
/**
* 批量删除员工
* @param ids
* @return
*/
@DeleteMapping("/{ids}")
public Result delete(@PathVariable("ids") List<Short> ids) {
log.info("批量删除操作ids:{}",ids);
empService.delete(ids);
return Result.success();
}
}
Service层:
接口:
public interface EmpService {
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
}
实现类:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
// /**
// * 分页查询,获取列表数据
// * @param page
// * @param pageSize
// * @return
// */
// @Override
// public PageBean getPage(Integer page, Integer pageSize) {
// Long total = empMapper.getTotal();
// Long start = (long) ((page - 1) * pageSize);
// List<Emp> rows = empMapper.getRows(start,pageSize);
// PageBean pageBean = new PageBean(total,rows);
// return pageBean;
// }
/**
* 使用PageHelper分页插件进行分页查询
*/
@Override
public PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
//1.设置分页参数
PageHelper.startPage(page, pageSize);
//2.执行查询
List<Emp> empList = empMapper.list(name,gender,begin,end);
Page<Emp> p = (Page<Emp>) empList;
//3.封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
/**
* 批量删除员工
* @param ids
*/
@Override
public void delete(List<Short> ids) {
empMapper.delete(ids);
}
}
Mapper层:
@Mapper
public interface EmpMapper {
// /**
// * 获取总记录数
// * @return
// */
// @Select("select count(*) from emp")
// Long getTotal();
//
// /**
// * 分页查询,获取列表数据
// * @param start
// * @param pageSize
// * @return
// */
// @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time\n" +
// "from emp limit #{start},#{pageSize}")
// List<Emp> getRows(Long start, Integer pageSize);
//动态SQL
/**
* 使用PageHelper插件来进行分页查询
*/
List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
}
动态SQL:
xml文件:
<?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.han.mapper.EmpMapper">
<select id="list" resultType="com.han.pojo.Emp">
select id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time
from emp
<where>
<if test="name != null and name != ''">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time DESC
</select>
<delete id="delete">
delete
from emp
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
</mapper>
Postman测试结果:
文件上传:
本地存储(不推荐):
使用MultipartFile类型接收文件,再使用下面的方法
阿里云OSS存储(推荐):
用户上文中图像的上传
代码演示:
工具类:
/**
* 阿里云 OSS 工具类
*/
@RestController
public class AliOSSUtils {
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws ClientException, IOException {
InputStream inputStream = file.getInputStream();
// 以华东1(杭州)的外网Endpoint为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-beijing.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "web-talias-test";
// 填写Object完整路径,例如exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + objectName.substring(objectName.lastIndexOf("."));
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream);
// 上传文件。
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 设置请求头。
Map<String, String> headers = new HashMap<String, String>();
/*// 指定Object的存储类型。
headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
// 指定ContentType。
headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/
// 设置用户自定义元数据。
Map<String, String> userMetadata = new HashMap<String, String>();
/*userMetadata.put("key1","value1");
userMetadata.put("key2","value2");*/
URL signedUrl = null;
// 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
// 生成签名URL。
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, fileName);
// 设置过期时间。
request.setExpiration(expiration);
// 将请求头加入到request中。
request.setHeaders(headers);
// 添加用户自定义元数据。
request.setUserMetadata(userMetadata);
// 通过HTTP PUT请求生成签名URL。
signedUrl = ossClient.generatePresignedUrl(request);
// 返回签名URL。
ossClient.shutdown();
return signedUrl.toString().split("\\?")[0];
}
}
文件上传Controller层:
@Slf4j
@RestController
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
@PostMapping("/upload")
public Result upload(MultipartFile image) throws IOException, ClientException {
log.info("接收到文件:{}",image.getOriginalFilename());
String url = aliOSSUtils.upload(image);
log.info("已将文件存储到阿里云OSS,url:{}",url);
return Result.success(url);
}
}
修改员工
1.查询回显:
代码:
Controller层:
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
@GetMapping
public Result getPage(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
log.info("每页记录数:{},查询页码:{}",pageSize,page);
PageBean pb = empService.getPage(page,pageSize,name,gender,begin,end);
return Result.success(pb);
}
/**
* 批量删除员工
* @param ids
* @return
*/
@DeleteMapping("/{ids}")
public Result delete(@PathVariable("ids") List<Short> ids) {
log.info("批量删除操作ids:{}",ids);
empService.delete(ids);
return Result.success();
}
/**
* 新增员工
* @param emp
* @return
*/
@PostMapping
public Result add(@RequestBody Emp emp) {
log.info("新增员工:{}",emp);
empService.add(emp);
return Result.success();
}
/**
* 根据id查询员工
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
log.info("查询id为:{}的员工",id);
Emp emp = empService.getById(id);
return Result.success(emp);
}
}
Service层:
接口:
public interface EmpService {
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
/**
* 新增员工
* @param emp
*/
void add(Emp emp);
/**
* 根据id查询员工
* @return
*/
Emp getById(Integer id);
}
实现类:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
// /**
// * 分页查询,获取列表数据
// * @param page
// * @param pageSize
// * @return
// */
// @Override
// public PageBean getPage(Integer page, Integer pageSize) {
// Long total = empMapper.getTotal();
// Long start = (long) ((page - 1) * pageSize);
// List<Emp> rows = empMapper.getRows(start,pageSize);
// PageBean pageBean = new PageBean(total,rows);
// return pageBean;
// }
/**
* 使用PageHelper分页插件进行分页查询
*/
@Override
public PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
//1.设置分页参数
PageHelper.startPage(page, pageSize);
//2.执行查询
List<Emp> empList = empMapper.list(name,gender,begin,end);
Page<Emp> p = (Page<Emp>) empList;
//3.封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
/**
* 批量删除员工
* @param ids
*/
@Override
public void delete(List<Short> ids) {
empMapper.delete(ids);
}
/**
* 新增员工
* @param emp
*/
@Override
public void add(Emp emp) {
emp.setUpdateTime(LocalDateTime.now());
emp.setCreateTime(LocalDateTime.now());
empMapper.add(emp);
}
/**
* 根据id查询员工
* @return
*/
@Override
public Emp getById(Integer id) {
Emp emp = empMapper.get(id);
return emp;
}
}
Mapper层:
@Mapper
public interface EmpMapper {
// /**
// * 获取总记录数
// * @return
// */
// @Select("select count(*) from emp")
// Long getTotal();
//
// /**
// * 分页查询,获取列表数据
// * @param start
// * @param pageSize
// * @return
// */
// @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time\n" +
// "from emp limit #{start},#{pageSize}")
// List<Emp> getRows(Long start, Integer pageSize);
//动态SQL
/**
* 使用PageHelper插件来进行分页查询
*/
List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
/**
* 新增员工
* @param emp
*/
@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
"values (#{username},#{name},#{gender},#{image},#{job},#{entryDate},#{deptId},#{createTime},#{updateTime})")
void add(Emp emp);
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time " +
"from emp where id = #{id}")
Emp get(Integer id);
}
Postman测试结果:
2.修改员工:
代码:
Controller层:
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
@GetMapping
public Result getPage(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
log.info("每页记录数:{},查询页码:{}",pageSize,page);
PageBean pb = empService.getPage(page,pageSize,name,gender,begin,end);
return Result.success(pb);
}
/**
* 批量删除员工
* @param ids
* @return
*/
@DeleteMapping("/{ids}")
public Result delete(@PathVariable("ids") List<Short> ids) {
log.info("批量删除操作ids:{}",ids);
empService.delete(ids);
return Result.success();
}
/**
* 新增员工
* @param emp
* @return
*/
@PostMapping
public Result add(@RequestBody Emp emp) {
log.info("新增员工:{}",emp);
empService.add(emp);
return Result.success();
}
/**
* 根据id查询员工
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
log.info("查询id为:{}的员工",id);
Emp emp = empService.getById(id);
return Result.success(emp);
}
/**
* 修改员工
* @param emp
* @return
*/
@PutMapping
public Result update(@RequestBody Emp emp) {
log.info("修改员工:{}",emp);
empService.update(emp);
return Result.success();
}
}
Service层:
接口:
public interface EmpService {
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
/**
* 新增员工
* @param emp
*/
void add(Emp emp);
/**
* 根据id查询员工
* @return
*/
Emp getById(Integer id);
void update(Emp emp);
}
实现类:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
// /**
// * 分页查询,获取列表数据
// * @param page
// * @param pageSize
// * @return
// */
// @Override
// public PageBean getPage(Integer page, Integer pageSize) {
// Long total = empMapper.getTotal();
// Long start = (long) ((page - 1) * pageSize);
// List<Emp> rows = empMapper.getRows(start,pageSize);
// PageBean pageBean = new PageBean(total,rows);
// return pageBean;
// }
/**
* 使用PageHelper分页插件进行分页查询
*/
@Override
public PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
//1.设置分页参数
PageHelper.startPage(page, pageSize);
//2.执行查询
List<Emp> empList = empMapper.list(name,gender,begin,end);
Page<Emp> p = (Page<Emp>) empList;
//3.封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
/**
* 批量删除员工
* @param ids
*/
@Override
public void delete(List<Short> ids) {
empMapper.delete(ids);
}
/**
* 新增员工
* @param emp
*/
@Override
public void add(Emp emp) {
emp.setUpdateTime(LocalDateTime.now());
emp.setCreateTime(LocalDateTime.now());
empMapper.add(emp);
}
/**
* 根据id查询员工
* @return
*/
@Override
public Emp getById(Integer id) {
Emp emp = empMapper.get(id);
return emp;
}
@Override
public void update(Emp emp) {
emp.setUpdateTime(LocalDateTime.now());
empMapper.update(emp);
}
}
Mapper层:
@Mapper
public interface EmpMapper {
// /**
// * 获取总记录数
// * @return
// */
// @Select("select count(*) from emp")
// Long getTotal();
//
// /**
// * 分页查询,获取列表数据
// * @param start
// * @param pageSize
// * @return
// */
// @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time\n" +
// "from emp limit #{start},#{pageSize}")
// List<Emp> getRows(Long start, Integer pageSize);
//动态SQL
/**
* 使用PageHelper插件来进行分页查询
*/
List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
/**
* 新增员工
* @param emp
*/
@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
void add(Emp emp);
/**
* 根据id查询员工
* @param id
* @return
*/
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time " +
"from emp where id = #{id}")
Emp get(Integer id);
/**
* 修改员工
* @param emp
*/
void update(Emp emp);
}
动态SQL:
xml文件:
<?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.han.mapper.EmpMapper">
<select id="list" resultType="com.han.pojo.Emp">
select id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time
from emp
<where>
<if test="name != null and name != ''">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time DESC
</select>
<delete id="delete">
delete
from emp
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
<update id="update">
update emp
<set>
<if test="image != null and image !=''">
image = #{image},
</if>
<if test="username != null and image !=''">
username = #{username},
</if>
<if test="name != null and image !=''">
name = #{name},
</if>
<if test="gender != null">
gender = #{gender},
</if>
<if test="job != null">
job = #{job},
</if>
<if test="entrydate != null">
entrydate = #{entrydate},
</if>
<if test="deptId != null">
dept_id = #{deptId},
</if>
update_time = #{updateTime}
</set>
where id = #{id}
</update>
</mapper>
Postman测试结果:
配置文件:
1.参数配置化
因为将文件上传阿里云OSS,总是需要endpoint和bucketName,但是这些还是固定的,所以直接将它们存储在配置文件中
代码演示:
配置文件applicat-properties:
#自定义的阿里云OSS配置信息
aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com
aliyun.oss.bucketName=web-talias-test
工具类:
/**
* 阿里云 OSS 工具类
*/
@RestController
public class AliOSSUtils {
// 以华东1(杭州)的外网Endpoint为例,其它Region请按实际情况填写。
@Value("${aliyun.oss.endpoint}")
private String endpoint;
// 填写Bucket名称,例如examplebucket。
@Value("${aliyun.oss.bucketName}")
private String bucketName;
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws ClientException, IOException {
InputStream inputStream = file.getInputStream();
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Object完整路径,例如exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + objectName.substring(objectName.lastIndexOf("."));
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream);
// 上传文件。
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 设置请求头。
Map<String, String> headers = new HashMap<String, String>();
/*// 指定Object的存储类型。
headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
// 指定ContentType。
headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/
// 设置用户自定义元数据。
Map<String, String> userMetadata = new HashMap<String, String>();
/*userMetadata.put("key1","value1");
userMetadata.put("key2","value2");*/
URL signedUrl = null;
// 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
// 生成签名URL。
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, fileName);
// 设置过期时间。
request.setExpiration(expiration);
// 将请求头加入到request中。
request.setHeaders(headers);
// 添加用户自定义元数据。
request.setUserMetadata(userMetadata);
// 通过HTTP PUT请求生成签名URL。
signedUrl = ossClient.generatePresignedUrl(request);
// 返回签名URL。
ossClient.shutdown();
return signedUrl.toString().split("\\?")[0];
}
}
2.(推荐)yml(yaml)配置文件:
常见配置文件格式对比:
yml基本语法:
数据格式:
代码演示:
将下面application.properties文件改写成application.yml文件
application.properties:
spring.application.name=tlias
#驱动器名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/tlias
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456
#配置mybatis的日志,指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启mybatis的驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true
#自定义的阿里云OSS配置信息
aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com
aliyun.oss.bucketName=web-talias-test
application.yml:
spring:
application:
name: tlias
#数据库连接信息
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/tlias
username: root
password: 123456
#文件上传的配置
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
#mybatis配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
#阿里云OSS配置
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: web-talias-test
3.ConfigurationProperties
与@Value的区别:
应用场景:
如果需要注解的属性只有一两个,而且只需要注解一次,那么使用@Value注解,如果需要注解的属性较多,而且需要多次注解,就使用@ConfigurationProperties注解。
代码演示:
AliOSSProperties:
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
private String endpoint;
private String bucketName;
}
AliOSSUtils:
/**
* 阿里云 OSS 工具类
*/
@RestController
public class AliOSSUtils {
// // 以华东1(杭州)的外网Endpoint为例,其它Region请按实际情况填写。
// @Value("${aliyun.oss.endpoint}")
// private String endpoint;
// // 填写Bucket名称,例如examplebucket。
// @Value("${aliyun.oss.bucketName}")
// private String bucketName;
@Autowired
private AliOSSProperties aliOSSProperties;
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws ClientException, IOException {
String endpoint = aliOSSProperties.getEndpoint();
String bucketName = aliOSSProperties.getBucketName();
InputStream inputStream = file.getInputStream();
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Object完整路径,例如exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + objectName.substring(objectName.lastIndexOf("."));
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream);
// 上传文件。
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 设置请求头。
Map<String, String> headers = new HashMap<String, String>();
/*// 指定Object的存储类型。
headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
// 指定ContentType。
headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/
// 设置用户自定义元数据。
Map<String, String> userMetadata = new HashMap<String, String>();
/*userMetadata.put("key1","value1");
userMetadata.put("key2","value2");*/
URL signedUrl = null;
// 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
// 生成签名URL。
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, fileName);
// 设置过期时间。
request.setExpiration(expiration);
// 将请求头加入到request中。
request.setHeaders(headers);
// 添加用户自定义元数据。
request.setUserMetadata(userMetadata);
// 通过HTTP PUT请求生成签名URL。
signedUrl = ossClient.generatePresignedUrl(request);
// 返回签名URL。
ossClient.shutdown();
return signedUrl.toString().split("\\?")[0];
}
}
登录功能:
基础登录功能代码:
Controller层:
@Slf4j
@RestController
public class LoginController {
@Autowired
EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp) {
log.info("用户尝试登录,登录信息:{}",emp);
Boolean result = empService.login(emp);
/*if(result){
return Result.success();
} else {
return Result.error("用户名或密码错误!");
}*/
return result == true ? Result.success() : Result.error("用户名或密码错误!");
}
}
Service层:
接口:
public interface EmpService {
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
/**
* 新增员工
* @param emp
*/
void add(Emp emp);
/**
* 根据id查询员工
* @return
*/
Emp getById(Integer id);
void update(Emp emp);
Boolean login(Emp emp);
}
实现类:
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
// /**
// * 分页查询,获取列表数据
// * @param page
// * @param pageSize
// * @return
// */
// @Override
// public PageBean getPage(Integer page, Integer pageSize) {
// Long total = empMapper.getTotal();
// Long start = (long) ((page - 1) * pageSize);
// List<Emp> rows = empMapper.getRows(start,pageSize);
// PageBean pageBean = new PageBean(total,rows);
// return pageBean;
// }
/**
* 使用PageHelper分页插件进行分页查询
*/
@Override
public PageBean getPage(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
//1.设置分页参数
PageHelper.startPage(page, pageSize);
//2.执行查询
List<Emp> empList = empMapper.list(name,gender,begin,end);
Page<Emp> p = (Page<Emp>) empList;
//3.封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
/**
* 批量删除员工
* @param ids
*/
@Override
public void delete(List<Short> ids) {
empMapper.delete(ids);
}
/**
* 新增员工
* @param emp
*/
@Override
public void add(Emp emp) {
emp.setUpdateTime(LocalDateTime.now());
emp.setCreateTime(LocalDateTime.now());
empMapper.add(emp);
}
/**
* 根据id查询员工
* @return
*/
@Override
public Emp getById(Integer id) {
Emp emp = empMapper.get(id);
return emp;
}
@Override
public void update(Emp emp) {
emp.setUpdateTime(LocalDateTime.now());
empMapper.update(emp);
}
@Override
public Boolean login(Emp emp) {
Short count = empMapper.getByUsernameAndPassword(emp);
if(count == 1){
return true;
} else {
return false;
}
}
}
Mapper层:
@Mapper
public interface EmpMapper {
// /**
// * 获取总记录数
// * @return
// */
// @Select("select count(*) from emp")
// Long getTotal();
//
// /**
// * 分页查询,获取列表数据
// * @param start
// * @param pageSize
// * @return
// */
// @Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time\n" +
// "from emp limit #{start},#{pageSize}")
// List<Emp> getRows(Long start, Integer pageSize);
//动态SQL
/**
* 使用PageHelper插件来进行分页查询
*/
List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除员工
* @param ids
*/
void delete(List<Short> ids);
/**
* 新增员工
* @param emp
*/
@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
void add(Emp emp);
/**
* 根据id查询员工
* @param id
* @return
*/
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time " +
"from emp where id = #{id}")
Emp get(Integer id);
/**
* 修改员工
* @param emp
*/
void update(Emp emp);
@Select("select count(*) from emp where username = #{username} and password = #{password}")
Short getByUsernameAndPassword(Emp emp);
}
Postman测试结果:
问题:
使用上面的基础登录功能代码运行程序会有一些问题,比如直接访问接口路径浏览器会直接跳到对应的接口网址页面,而不需要登录操作。为了解决这一问题我们需要进行登录校验
登录校验:
会话技术:
会话跟踪方案:
1.Cookie:
2.Session
3★.令牌技术(推荐)
JWT令牌:
使用场景:
最广泛的使用场景:登录认证
JWT生成:
导入依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
代码演示:
/**
* 生成JWT令牌
*/
@Test
void testJwt() {
Map<String, Object> claims = new HashMap<>();
claims.put("username", "admin");
claims.put("password", "123456");
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, "hann")//签名算法
.setClaims(claims)//自定义内容(载荷)
.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置有效期1h
.compact();
System.out.println(jwt);
}
/**
* 解析JWT令牌
*/
@Test
void testParseJwt(){
Claims claims = Jwts.parser()
.setSigningKey("hann")//指定签名密钥
.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9" +
".eyJwYXNzd29yZCI6IjEyMzQ1NiIsImV4cCI6MTcxNzQwNTg3NywidXNlcm5hbWUiOiJhZG1pbiJ9" +
".iup_46wg3STPq6Dffbt36IYKTbN8cwiRcOm_8uI_slY")//解析令牌
.getBody();
System.out.println(claims);
}
注意事项:
接下来通过jwt令牌进行登录校验。
改写登录功能:
思路:
1.生成JWT令牌
代码演示:
这里我发现之前基础的登录功能只返回一个布尔类型的值,是只能获取到用户名和密码的,但是在生成JWT令牌是自定义内容写用户名和密码是可以被解码的,这样信息就不安全,所以我把登录的一系列接口和方法返回的类型改成Emp实体类了
JWT令牌工具类:
public class JwtUtils {
private static String signKey = "hann";
private static Long expirationTime = 43200000L;
/**
* 获得JWT令牌
*/
public static String getJwt(Map<String, Object> claims) {
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, signKey)//签名算法
.setClaims(claims)//自定义内容(载荷)
.setExpiration(new Date(System.currentTimeMillis() + expirationTime))//设置有效期12h
.compact();
return jwt;
}
}
Controller层:
@Slf4j
@RestController
public class LoginController {
@Autowired
EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp) {
log.info("用户尝试登录,登录信息:{}",emp);
Emp e = empService.login(emp);
if(e != null){
//登录成功
Map<String, Object> map = new HashMap<>();
map.put("id", e.getId());
map.put("name", e.getName());
map.put("username", e.getUsername());
String jwt = JwtUtils.getJwt(map);
return Result.success(jwt);
} else {
return Result.error("用户名或密码错误!");
}
}
}
Postman测试结果:
2.统一校验JWT令牌
①过滤器Filter:
使用方法:
注解@WebFilter中urlPatterns = "/*"表示拦截所有路径。
执行流程:
拦截路径:
过滤器链:
登录校验流程:
代码:
pom.xml:
引入依赖用于将Result对象转为JSON格式
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
Filter:
@Slf4j
@WebFilter
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
//1.获取url
String url = req.getRequestURL().toString();
//2.判断url中是否包含login,如果有直接放行,如果没有需要再判断
if(url.contains("login")) {
log.info("登录操作,放行");
filterChain.doFilter(servletRequest, servletResponse);
return;
}
//3.获取请求头中的令牌
String jwt = req.getHeader("token");
//4.判断令牌是否存在,若存在继续判断,不存在则返回未登录信息
if(!StringUtils.hasLength(jwt)) {
log.info("请求头token为空,返回未登录信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象->JSON 格式 利用阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//令牌存在,判断令牌是否合法,不合法返回未登录信息
try {
JwtUtils.parseJwt(jwt);
} catch (Exception e) {
e.printStackTrace();
log.info("解析令牌失败,返回未登录信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象->JSON 格式 利用阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//放行
log.info("令牌合法,放行,jwt:{}",jwt);
filterChain.doFilter(servletRequest, servletResponse);
}
}
Postman测试:
②拦截器Interceptor:
使用方法:
拦截路径:
与过滤器Filter的区别:
代码:
Interceptor:
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override//目标资源方法执行前执行,返回true 放行,返回false 不放行
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
//1.获取url
String url = req.getRequestURL().toString();
//2.判断url中是否包含login,如果有直接放行,如果没有需要再判断
if(url.contains("login")) {
log.info("登录操作,放行");
return true;
}
//3.获取请求头中的令牌
String jwt = req.getHeader("token");
//4.判断令牌是否存在,若存在继续判断,不存在则返回未登录信息
if(!StringUtils.hasLength(jwt)) {
log.info("请求头token为空,返回未登录信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象->JSON 格式 利用阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
//令牌存在,判断令牌是否合法,不合法返回未登录信息
try {
JwtUtils.parseJwt(jwt);
} catch (Exception e) {
e.printStackTrace();
log.info("解析令牌失败,返回未登录信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象->JSON 格式 利用阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
//放行
log.info("令牌合法,放行,jwt:{}",jwt);
return true;
}
@Override//目标资源方法执行后执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override//视图渲染完毕后执行,最后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
配置类:
@Configuration//配置类
public class WebConfig implements WebMvcConfigurer {
@Autowired
LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
}
}
异常处理
全局异常处理器:
代码:
exception:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result ex(Exception ex) {
ex.printStackTrace();
return Result.error("对不起,操作失败,请联系管理员");
}
}
到这里基础功能部分基本完成,下面是上面代码的一些注意事项。
注意事项:
1.参数及属性值都使用基本类型的包装类,比如int类型用Integer,short类型用Short,这样传递的值为空也不会报错
2.动态SQL中,查询语句后不能加分号
3.根据name查询时模糊匹配使用name like concat('%',#{name},'%') 字符串拼接,不然编译后#{...}变成问号出现在字符串中不起作用,并且<if>的test判断中不仅要添加非空判断,还要加上等于空值的判断and name != '',否则不输入内容点击查询会传递一个空值字符串。
事务管理:
Spring事务管理:
代码演示:
empMapper:
添加代码
@Delete("delete from emp where dept_id = #{deptId}")
void deleteByDeptId(Integer deptId);
DeptService:
修改删除部门代码
/**
* 根据id删除部门
* @param id
*/
@Transactional
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);
//删除该部门下的员工
empMapper.deleteByDeptId(id);
}
事务属性
1.回滚rollbackFor:
将回滚属性改为出现任何异常都回滚
代码演示:
/**
* 根据id删除部门
* @param id
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);
//删除该部门下的员工
empMapper.deleteByDeptId(id);
}
2.传播行为propagation:
案例
代码:
建表SQL语句:
CREATE TABLE `dept_log` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`create_time` datetime NOT NULL COMMENT '创建时间',
`description` varchar(300) NOT NULL COMMENT '部分解散描述',
PRIMARY KEY (`id`)
)
日志实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeptLog {
private int id;
private LocalDateTime createTime;
private String description;
}
Controller层:
删除部门部分:
/**
* 根据id删除部门
* @param id
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void delete(Integer id) {
try {
deptMapper.deleteById(id);
int i = 1/0;
//删除该部门下的员工
empMapper.deleteByDeptId(id);
} finally {
DeptLog deptLog = new DeptLog();
deptLog.setCreateTime(LocalDateTime.now());
deptLog.setDescription("删除部门,id为:" + id);
deptLogService.insert(deptLog);
}
}
Service层:
接口:
public interface DeptLogService {
void insert(DeptLog log);
}
实现类:
@Service
public class DeptLogServiceImpl implements DeptLogService {
@Autowired
DeptLogMapper deptLogMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void insert(DeptLog log) {
deptLogMapper.insert(log);
}
}
Mapper层:
@Mapper
public interface DeptLogMapper {
@Insert("insert into dept_log(create_time,description) values (#{createTime},#{description})")
void insert(DeptLog log);
}
使用场景:
AOP(面向切面编程)
场景:
基于动态代理实现,最后运行的是基于目标对象代理的加强后的方法
代码:
在pom.xim文件中添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
编写AOP程序:
@Slf4j
@Component
@Aspect//AOP类
public class TimeAspect {
@Around("execution(* com.han.service.*.*(..))")
public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
long begin = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
log.info(joinPoint.getSignature() + "方法的执行时间为{}ms", end - begin);
return result;
}
}
优势:
核心概念:
通知类型:
@PointCut:
通知顺序:
切入点表达式:
1.execution:
书写建议:
2.@annotation:
它可以通过自定义注解,然后在写切入点表达式时括号中写这个自定义注解的全类名,就可以把这个自定义注解注解的方法包含。
连接点:
案例:
准备工作:
建表:
-- 操作日志表
create table operate_log(
id int unsigned primary key auto_increment comment 'ID',
operate_user int unsigned comment '操作人ID',
operate_time datetime comment '操作时间',
class_name varchar(100) comment '操作的类名',
method_name varchar(100) comment '操作的方法名',
method_params varchar(1000) comment '方法参数',
return_value varchar(2000) comment '返回值',
cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';
创建实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OperateLog {
private Integer id;
private Integer operateUser;
private LocalDateTime operateTime;
private String className;
private String methodName;
private String methodParams;
private String returnValue;
private Long costTime;
}
编码:
定义Mapper:
@Mapper
public interface OperateLodMapper {
@Insert("insert into operate_log (operate_user,operate_time,class_name,method_name,method_params,return_value,cost_time)" +
"values (#{operateUser},#{operateTime},#{className},#{methodName},#{methodParams},#{returnValue},#{costTime})")
public void insert(OperateLog log);
}
定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
}
编写AOP代码:
@Slf4j
@Component
@Aspect
public class LogAspect {
@Autowired
private HttpServletRequest request;
@Autowired
private OperateLodMapper operateLodMapper;
@Around("@annotation(com.han.anno.Log)")
public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
//获取操作用户id
String jwt = request.getHeader("token");
Map<String, Object> claims = JwtUtils.parseJwt(jwt);
Integer operateUser = (Integer) claims.get("id");
//获取操作时间
LocalDateTime operateTime = LocalDateTime.now();
//获取操作的类名
String operateClass = joinPoint.getTarget().getClass().getName();
//获取操作的方法名
String operateMethod = joinPoint.getSignature().getName();
//获取方法参数
Object[] args = joinPoint.getArgs();
String methodParams = Arrays.toString(args);
//获取返回值(JSON字符串格式)
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
String returnValue = JSONObject.toJSONString(result);
//获取方法执行耗时
Long costTime = endTime - startTime;
OperateLog operateLog = new OperateLog(null,operateUser,operateTime,operateClass,
operateMethod,methodParams,returnValue,costTime);
operateLodMapper.insert(operateLog);
log.info("AOP记录操作日志:{}",operateLog);
return result;
}
}
在Controller中添加注解:
EmpController:
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
/**
* 根据每页记录数和页码获取页面实体类
* @return
*/
@GetMapping
public Result getPage(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
log.info("每页记录数:{},查询页码:{}",pageSize,page);
PageBean pb = empService.getPage(page,pageSize,name,gender,begin,end);
return Result.success(pb);
}
/**
* 批量删除员工
* @param ids
* @return
*/
@Log
@DeleteMapping("/{ids}")
public Result delete(@PathVariable("ids") List<Short> ids) {
log.info("批量删除操作ids:{}",ids);
empService.delete(ids);
return Result.success();
}
/**
* 新增员工
* @param emp
* @return
*/
@Log
@PostMapping
public Result add(@RequestBody Emp emp) {
log.info("新增员工:{}",emp);
empService.add(emp);
return Result.success();
}
/**
* 根据id查询员工
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
log.info("查询id为:{}的员工",id);
Emp emp = empService.getById(id);
return Result.success(emp);
}
/**
* 修改员工
* @param emp
* @return
*/
@Log
@PutMapping
public Result update(@RequestBody Emp emp) {
log.info("修改员工:{}",emp);
empService.update(emp);
return Result.success();
}
}
DeptController:
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 查询部门数据
* @return
*/
@GetMapping
public Result list() {
log.info("查询全部部门信息");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
* @return
*/
@Log
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除id为" + id +"的部门");
deptService.delete(id);
return Result.success();
}
/**
* 新增部门
* @param dept
* @return
*/
@Log
@PostMapping
public Result insert(@RequestBody Dept dept) {
log.info("添加部门:" + dept);
deptService.add(dept);
return Result.success();
}
/**
* 根据id查找部门
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
log.info("查询id为"+ id + "的部门信息");
Dept dept = deptService.get(id);
return Result.success(dept);
}
/**
* 修改部门
* @param dept
* @return
*/
@Log
@PutMapping
public Result update(@RequestBody Dept dept) {
log.info("修改部门:" + dept);
deptService.update(dept);
return Result.success();
}
}
注意点:
在获取操作用户id时要用到以下方法:
SpringBoot
配置优先级:
1.properties>yml>yaml
2.命令行参数>Java系统属性
项目打包之后在cmd运行时设置属性或参数
3.命令行参数>Java系统属性
并且在SpringBoot中直接配置Java系统属性后,再使用配置文件配置,那么会根据Java系统属性的配置信息配置
总结:
优先级:命令行参数>Java系统属性>properties>yml>yaml
bean的管理:
获取bean:
代码演示:
/**
* 获得bean对象
*/
@Autowired
private ApplicationContext applicationContext;
@Test
void testGetBean(){
//通过name获取bean
DeptController bean1 = (DeptController) applicationContext.getBean("deptController");
System.out.println(bean1);
//通过类型获取bean
DeptController bean2 = applicationContext.getBean(DeptController.class);
System.out.println(bean2);
//通过name获取bean(带类型转换)
DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);
System.out.println(bean3);
}
}
运行结果:
bean的作用域:
第三方bean:
(以xml解析类SAXReader举例)
使用场景:
★SpringBoot原理:
起步依赖:
如果要使用web相关的依赖,只需要导入spring-boot-starter-web依赖,通过maven的依赖传递,关于web的所有依赖都会被导入,还不用担心版本兼容问题
自动配置:
自动配置的原理:
问题:
如果我们直接在pom.xml.文件中引入第三方依赖,第三方依赖中通过@Component、@Bean等注解定义了bean对象,这种情况第三方依赖中的bean对象也是不会出现在springboot程序中的,因为springboot程序通过启动类注解@SpringBootApplication扫描其所在包和子包中的bean对象,是扫描不到第三方依赖的。
解决方案一 @ComponentScan组件扫描:
启动类:(com.han为当前启动类所在包,com.example为第三方依赖的包)
@ComponentScan({"com.han","com.example"})
@ServletComponentScan
@SpringBootApplication
public class TliasApplication {
public static void main(String[] args) {
SpringApplication.run(TliasApplication.class, args);
}
}
这种方式使用较繁琐,性能低。
解决方案二 @Import导入:
@EnableXxxx注解使用举例:
@SpringBootApplication源码跟踪:
这里最重要的是@EnableAutoConfiguration注解。
@EnableAutoConfiguration:
它通过封装@Import注解,将上图两个文件中的需要导入到IOC容器的类的全类名放入ImportSelector接口的实现类中的selectImports方法返回的字符数组,以自动配置。
但是这些类并不是全部注册为IOC容器的bean,SpringBoot会根据@Conditional注解条件装配。
条件装配注解@Conditional:
1.@ConditionalOnClass:
2.@ConditionalOnMissingBean:
不指定类型和名称时,默认类型指该方法返回值的类型。
使用场景:默认的bean,引入依赖后,用户如果自定义了这个类型的bean,则会导入用户自定义的,如果用户没有定义,就导入依赖中默认的。
3.@ConditionalOnProperty:
根据上述代码,若在配置文件application.yml中添加配置信息name: itheima,那么就会将该bean放入IOC容器中。
使用场景:引入第三方变量后,可以在配置文件中配置信息后,才将某个类加入IOC容器。
案例(自定义starter):
自定义starter场景:
案例需求:
步骤:
代码:
1.新建模块aliyun-oss-spring-boot-starter(只需要pom.xml文件),aliyun-oss-spring-boot-autoconfigure(只需要pom.xml文件和src文件夹,也不需要启动类),在aliyun-oss-spring-boot-starter中的pom.xml文件中引入aliyun-oss-spring-boot-autoconfigure的依赖。
aliyun-oss-spring-boot-starter:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
2.在aliyun-oss-spring-boot-autoconfigure中的pom.xml文件中引入阿里云OSS的依赖
aliyun-oss-spring-boot-autoconfigure:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--阿里云OSS依赖-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</project>
3.在aliyun-oss-spring-boot-autoconfigure中编写能够使用阿里云OSS的代码
这里要使用MultipartFile还需要引入web开发的起步依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--阿里云OSS依赖-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
工具类:
/**
* 阿里云 OSS 工具类
*/
public class AliOSSUtils {
private AliOSSProperties aliOSSProperties;
//不能依赖注入了但是后续方法要使用aliOSSProperties对象,所以定义get set方法
public AliOSSProperties getAliOSSProperties() {
return aliOSSProperties;
}
public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
this.aliOSSProperties = aliOSSProperties;
}
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws ClientException, IOException {
String endpoint = aliOSSProperties.getEndpoint();
String bucketName = aliOSSProperties.getBucketName();
InputStream inputStream = file.getInputStream();
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Object完整路径,例如exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + objectName.substring(objectName.lastIndexOf("."));
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, inputStream);
// 上传文件。
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 设置请求头。
Map<String, String> headers = new HashMap<String, String>();
/*// 指定Object的存储类型。
headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString());
// 指定ContentType。
headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/
// 设置用户自定义元数据。
Map<String, String> userMetadata = new HashMap<String, String>();
/*userMetadata.put("key1","value1");
userMetadata.put("key2","value2");*/
URL signedUrl = null;
// 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
// 生成签名URL。
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, fileName);
// 设置过期时间。
request.setExpiration(expiration);
// 将请求头加入到request中。
request.setHeaders(headers);
// 添加用户自定义元数据。
request.setUserMetadata(userMetadata);
// 通过HTTP PUT请求生成签名URL。
signedUrl = ossClient.generatePresignedUrl(request);
// 返回签名URL。
ossClient.shutdown();
return signedUrl.toString().split("\\?")[0];
}
}
认证信息存储类:
@ConfigurationProperties(prefix = "aliyun.oss")//用于验证配置文件中以"aliyun.oss"为前缀的属性
public class AliOSSProperties {
private String endpoint;
private String bucketName;
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
}
4.定义自动配置类AliOSSAutoConfiguration
@Configuration//配置类
@EnableConfigurationProperties(AliOSSProperties.class)//将AliOSSProperties类bean对象放入IOC容器
public class AliOSSAutoConfiguration {
@Bean
public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){//需要注入某个对象直接在方法形参中指定
AliOSSUtils aliOSSUtils = new AliOSSUtils();
aliOSSUtils.setAliOSSProperties(aliOSSProperties);
return aliOSSUtils;
}
}
5.定义自动配置文件,在resource目录下创建文件夹META-INF/spring下的文件org.springframework.boot.autoconfigure.AutoConfiguration
并存入配置类的全类名
com.aliyun.oss.AliOSSAutoConfiguration
测试案例:
新建模块,配置阿里云OSS信息
application.yml:
#阿里云OSS配置
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
bucketName: web-talias-test
引入自定义的依赖,只需要引入starter
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.han</groupId>
<artifactId>springboot-autoconfiguration-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-autoconfiguration-test</name>
<description>springboot-autoconfiguration-test</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-oss-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
编写Controller:
@RestController
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
@PostMapping("/upload")
public String upload(MultipartFile image) throws Exception {
String url = aliOSSUtils.upload(image);
return url;
}
}
Postman测试:
浏览器打开网址可正常下载显示。
框架总结:
SpringMVC + Spring framework(Spring) + Mybatis = SSM框架
SpringMVC属于Spring框架,是Spring框架当中提供的web开发模块,是用来简化原始的servelet程序的开发的。
基于传统的SSM框架开发进行整合开发是比较繁琐的,效率也较低,所以目前的企业项目开发当中,基本上都是基于SpringBoot进行项目开发的。
标签:return,JavaWeb,SpringBootWeb,id,案例,emp,Integer,param,public From: https://blog.csdn.net/wsxcjg/article/details/139376509