JavaWeb_SpringBootWeb案例

環境搭建:

開發規范

接口風格-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 {@Autowiredprivate 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 {@Autowiredprivate DeptMapper deptMapper;@Overridepublic 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 {@Autowiredprivate 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 {@Autowiredprivate DeptMapper deptMapper;/*** 查詢部門信息* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根據id刪除部門* @param id*/@Overridepublic 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 {@Autowiredprivate 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 {@Autowiredprivate DeptMapper deptMapper;/*** 查詢部門信息* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根據id刪除部門* @param id*/@Overridepublic void delete(Integer id) {deptMapper.deleteById(id);}/*** 新增部門* @param dept*/@Overridepublic 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 {@Autowiredprivate DeptService deptService;/*** 查詢部門數據* @return*/@GetMappingpublic 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*/@PostMappingpublic Result insert(@RequestBody Dept dept) {log.info("添加部門:" + dept);deptService.add(dept);return Result.success();}}

根據id查找部門:

代碼:
Controller層:
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {@Autowiredprivate DeptService deptService;/*** 查詢部門數據* @return*/@GetMappingpublic 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*/@PostMappingpublic 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 {@Autowiredprivate DeptMapper deptMapper;/*** 查詢部門信息* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根據id刪除部門* @param id*/@Overridepublic void delete(Integer id) {deptMapper.deleteById(id);}/*** 新增部門* @param dept*/@Overridepublic void add(Dept dept) {dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.insert(dept);}/*** 根據id查找部門* @param id*/@Overridepublic 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 {@Autowiredprivate DeptService deptService;/*** 查詢部門數據* @return*/@GetMappingpublic 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*/@PostMappingpublic 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*/@PutMappingpublic 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 {@Autowiredprivate DeptMapper deptMapper;/*** 查詢部門信息* @return*/@Overridepublic List<Dept> list() {return deptMapper.list();}/*** 根據id刪除部門* @param id*/@Overridepublic void delete(Integer id) {deptMapper.deleteById(id);}/*** 新增部門* @param dept*/@Overridepublic void add(Dept dept) {dept.setCreateTime(LocalDateTime.now());dept.setUpdateTime(LocalDateTime.now());deptMapper.insert(dept);}/*** 根據id查找部門* @param id*/@Overridepublic Dept get(Integer id) {return deptMapper.getById(id);}/*** 修改部門* @param dept*/@Overridepublic 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 {@Autowiredprivate EmpService empService;/*** 根據每頁記錄數和頁碼獲取頁面實體類* @return*/@GetMappingpublic 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 {@Autowiredprivate EmpMapper empMapper;/*** 分頁查詢,獲取列表數據* @param page* @param pageSize* @return*/@Overridepublic 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 {@Autowiredprivate 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分頁插件進行分頁查詢*/@Overridepublic 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 {@Autowiredprivate EmpService empService;/*** 根據每頁記錄數和頁碼獲取頁面實體類* @return*/@GetMappingpublic 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 {@Autowiredprivate 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分頁插件進行分頁查詢*/@Overridepublic 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插件來進行分頁查詢*///動態SQLList<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);}
動態SQL:
xml文件:
<?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.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_timefrom 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 {@Autowiredprivate EmpService empService;/*** 根據每頁記錄數和頁碼獲取頁面實體類* @return*/@GetMappingpublic 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 {@Autowiredprivate 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分頁插件進行分頁查詢*/@Overridepublic 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*/@Overridepublic 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 mapperPUBLIC "-//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_timefrom 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">deletefrom empwhere 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 {@Autowiredprivate 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 {@Autowiredprivate EmpService empService;/*** 根據每頁記錄數和頁碼獲取頁面實體類* @return*/@GetMappingpublic 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*/@PostMappingpublic 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 {@Autowiredprivate 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分頁插件進行分頁查詢*/@Overridepublic 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*/@Overridepublic void delete(List<Short> ids) {empMapper.delete(ids);}/*** 新增員工* @param emp*/@Overridepublic void add(Emp emp) {emp.setUpdateTime(LocalDateTime.now());emp.setCreateTime(LocalDateTime.now());empMapper.add(emp);}/*** 根據id查詢員工* @return*/@Overridepublic 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 {@Autowiredprivate EmpService empService;/*** 根據每頁記錄數和頁碼獲取頁面實體類* @return*/@GetMappingpublic 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*/@PostMappingpublic 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*/@PutMappingpublic 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 {@Autowiredprivate 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分頁插件進行分頁查詢*/@Overridepublic 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*/@Overridepublic void delete(List<Short> ids) {empMapper.delete(ids);}/*** 新增員工* @param emp*/@Overridepublic void add(Emp emp) {emp.setUpdateTime(LocalDateTime.now());emp.setCreateTime(LocalDateTime.now());empMapper.add(emp);}/*** 根據id查詢員工* @return*/@Overridepublic Emp getById(Integer id) {Emp emp = empMapper.get(id);return emp;}@Overridepublic 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 mapperPUBLIC "-//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_timefrom 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">deletefrom empwhere 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.Driverurl: jdbc:mysql://localhost:3306/tliasusername: rootpassword: 123456#文件上傳的配置servlet:multipart:max-file-size: 10MBmax-request-size: 100MB
#mybatis配置
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true#阿里云OSS配置
aliyun:oss:endpoint: https://oss-cn-beijing.aliyuncs.combucketName: 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;@Autowiredprivate 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 {@AutowiredEmpService 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 {@Autowiredprivate 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分頁插件進行分頁查詢*/@Overridepublic 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*/@Overridepublic void delete(List<Short> ids) {empMapper.delete(ids);}/*** 新增員工* @param emp*/@Overridepublic void add(Emp emp) {emp.setUpdateTime(LocalDateTime.now());emp.setCreateTime(LocalDateTime.now());empMapper.add(emp);}/*** 根據id查詢員工* @return*/@Overridepublic Emp getById(Integer id) {Emp emp = empMapper.get(id);return emp;}@Overridepublic void update(Emp emp) {emp.setUpdateTime(LocalDateTime.now());empMapper.update(emp);}@Overridepublic 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令牌*/@Testvoid 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令牌*/@Testvoid 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 {@AutowiredEmpService 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 {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) servletRequest;HttpServletResponse resp = (HttpServletResponse) servletResponse;//1.獲取urlString 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 格式 利用阿里巴巴fastJSONString 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 格式 利用阿里巴巴fastJSONString 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.獲取urlString 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 格式 利用阿里巴巴fastJSONString 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 格式 利用阿里巴巴fastJSONString 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 {@AutowiredLoginCheckInterceptor loginCheckInterceptor;@Overridepublic 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@Overridepublic void delete(Integer id) {deptMapper.deleteById(id);//刪除該部門下的員工empMapper.deleteByDeptId(id);}

事務屬性

1.回滾rollbackFor:

? ? ? ? 將回滾屬性改為出現任何異常都回滾

代碼演示:
    /*** 根據id刪除部門* @param id*/@Transactional(rollbackFor = Exception.class)@Overridepublic 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)@Overridepublic 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 {@AutowiredDeptLogMapper deptLogMapper;@Transactional(propagation = Propagation.REQUIRES_NEW)@Overridepublic 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 {@Autowiredprivate HttpServletRequest request;@Autowiredprivate OperateLodMapper operateLodMapper;@Around("@annotation(com.han.anno.Log)")public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {//獲取操作用戶idString 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 {@Autowiredprivate EmpService empService;/*** 根據每頁記錄數和頁碼獲取頁面實體類* @return*/@GetMappingpublic 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@PostMappingpublic 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@PutMappingpublic Result update(@RequestBody Emp emp) {log.info("修改員工:{}",emp);empService.update(emp);return Result.success();}}
DeptController:
@Slf4j
@RequestMapping("/depts")
@RestController
public class DeptController {@Autowiredprivate DeptService deptService;/*** 查詢部門數據* @return*/@GetMappingpublic 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@PostMappingpublic 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@PutMappingpublic 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對象*/@Autowiredprivate ApplicationContext applicationContext;@Testvoid testGetBean(){//通過name獲取beanDeptController bean1 = (DeptController) applicationContext.getBean("deptController");System.out.println(bean1);//通過類型獲取beanDeptController 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 {@Beanpublic 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.combucketName: 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 {@Autowiredprivate 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進行項目開發的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/23311.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/23311.shtml
英文地址,請注明出處:http://en.pswp.cn/web/23311.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Xmind Pro 2024 專業版激活碼(附下載鏈接)

說到思維導圖&#xff0c;就不能不提 Xmind。這是一款優秀的思維導圖工具&#xff0c;擁有著豐富的導圖模板&#xff0c;漂亮的界面和配色&#xff0c;以及各種各樣的創意工具。 新架構速度更快 采用全新 Snowdancer 引擎&#xff0c;一種堪稱「黑科技」的先進圖形渲染技術。…

翹首以盼的抗鋸齒

Antialiasing 實際的圖形學中是怎么實現反走樣的呢&#xff1f; 我們不希望實際產出的圖形有鋸齒效果&#xff0c;那怎么辦呢&#xff1f; 從采樣的理論開始談起吧 Simpling theory 照片也是一種采樣&#xff0c;把景象打散成像素放到屏幕上的過程&#xff1a; 還可以在不…

14、企業數據資源相關會計處理暫行規定

為規范企業數據資源相關會計處理, 強化相關會計信息披露, 根據《中華人民共和國會計法》 和企業會計準則等相關規定, 現對企業數據資源的相關會計處理規定如下: 一、 關于適用范圍 本規定適用于企業按照企業會計準則相關規定確認為無形資產或存貨等資產類別的數據資源,以…

21 - 即時食物配送 II(高頻 SQL 50 題基礎版)

21 - 即時食物配送 II -- sum(if(order_datecustomer_pref_delivery_date,1,0))/count(*)sum(order_datecustomer_pref_delivery_date)/count(*) -- count(*),表示數據的行數&#xff0c;如果有分組&#xff0c;為分組后數據的行數select round(100*sum(if(order_datecustomer_…

【名詞解釋】Unity的Button組件及其使用示例

Unity的Button組件是Unity引擎中UI系統的一部分&#xff0c;它允許用戶創建可交互的按鈕&#xff0c;用戶可以點擊這些按鈕來觸發事件。Button組件通常用于游戲界面中&#xff0c;比如開始游戲、暫停游戲、選擇選項等。 Button組件的主要屬性包括&#xff1a; interactable: …

原來Stable Diffusion是這樣工作的

stable diffusion是一種潛在擴散模型&#xff0c;可以從文本生成人工智能圖像。為什么叫做潛在擴散模型呢&#xff1f;這是因為與在高維圖像空間中操作不同&#xff0c;它首先將圖像壓縮到潛在空間中&#xff0c;然后再進行操作。 在這篇文章中&#xff0c;我們將深入了解它到…

達摩院重大“遺產”!fluxonium量子比特初始化300納秒且保真度超過99%

通用量子計算機開發的主要挑戰之一是制備量子比特。十多年來&#xff0c;研究人員在構建量子計算機的過程中主要使用了transmon量子比特&#xff0c;這也是迄今為止商業上最成功的超導量子比特。 但與業界多數選擇transmon量子比特不同&#xff0c;&#xff08;前&#xff09;…

npm運行報錯:無法加載文件 C:\Program Files\nodejs\npm.ps1,因為在此系統上禁止運行腳本問題解決

問題其實已經顯而易見了 系統禁止運行腳本 以管理員身份運行 PowerShell&#xff1a; 右鍵點擊“開始”按鈕或按 Win X&#xff0c;然后選擇“Windows PowerShell(管理員)”。 查看當前執行策略&#xff1a; 在 PowerShell 中輸入以下命令來查看當前的執行策略&#xff1a; G…

Python文本處理利器:jieba庫全解析

文章目錄 Python文本處理利器&#xff1a;jieba庫全解析第一部分&#xff1a;背景和功能介紹第二部分&#xff1a;庫的概述第三部分&#xff1a;安裝方法第四部分&#xff1a;常用庫函數介紹1. 精確模式分詞2. 全模式分詞3. 搜索引擎模式分詞4. 添加自定義詞典5. 關鍵詞提取 第…

服務器遭遇UDP攻擊時的應對與解決方案

UDP攻擊作為分布式拒絕服務(DDoS)攻擊的一種常見形式&#xff0c;通過發送大量的UDP數據包淹沒目標服務器&#xff0c;導致網絡擁塞、服務中斷。本文旨在提供一套實用的策略與技術手段&#xff0c;幫助您識別、緩解乃至防御UDP攻擊&#xff0c;確保服務器穩定運行。我們將探討監…

最新PHP眾籌網站源碼 支持報名眾籌+商品眾籌+公益眾籌等多種眾籌模式 含完整代碼包和部署教程

在當今互聯網飛速發展的時代&#xff0c;眾籌模式逐漸成為了創新項目、商品銷售和公益活動融資的重要渠道。分享一款最新版的PHP眾籌網站源碼&#xff0c;支持報名眾籌、商品眾籌和公益眾籌等多種眾籌模式。該源碼包含了完整的代碼包和詳細的部署教程&#xff0c;讓新手也可以輕…

利用醫學Twitter進行病理圖像分析的視覺-語言基礎模型| 文獻速遞-視覺通用模型與疾病診斷

Title 題目 A visual–language foundation model for pathology image analysis using medical Twitter 利用醫學Twitter進行病理圖像分析的視覺-語言基礎模型 01 文獻速遞介紹 缺乏公開可用的醫學圖像標注是計算研究和教育創新的一個重要障礙。同時&#xff0c;許多醫生…

自動化測試-Selenium(一),簡介

自動化測試-Selenium 1. 什么是自動化測試 1.1 自動化測試介紹 自動化測試是一種通過自動化工具執行測試用例來驗證軟件功能和性能的過程。與手動測試不同&#xff0c;自動化測試使用腳本和軟件來自動執行測試步驟&#xff0c;記錄結果&#xff0c;并比較預期輸出和實際輸出…

【Python報錯】已解決ModuleNotFoundError: No module named ‘timm’

成功解決“ModuleNotFoundError: No module named ‘timm’”錯誤的全面指南 一、引言 在Python編程中&#xff0c;經常會遇到各種導入模塊的錯誤&#xff0c;其中“ModuleNotFoundError: No module named ‘timm’”就是一個典型的例子。這個錯誤意味著你的Python環境中沒有安…

Navicate 導入導出數據庫

導出數據庫 找地方存在來&#xff0c;別忘了放在那里。 新建一個數據庫&#xff0c;記得要和導出數據庫的 字符集與排序規則 相同 打開數據庫后&#xff0c;我們選擇它&#xff08;就是單擊它&#xff09;然后右鍵打開菜單-運行sql文件 找到剛才存儲的位置&#xff0c;開始 &a…

大中小面積紫外光老化加速試驗機裝置

高低溫試驗箱,振動試驗臺,紫外老化試驗箱,氙燈老化試驗箱,沙塵試驗箱,箱式淋雨試驗箱,臭氧老化試驗箱,換氣老化試驗箱,電熱鼓風干燥箱,真空干燥箱&#xff0c;超聲波清洗機&#xff0c;鹽霧試驗箱 一、產品用途 紫外光加速老化試驗裝置采用熒光紫外燈為光源,通過模擬自然陽光中…

oracle報錯ORA-01940: cannot drop a user that is currently connected解決方法

目錄 一.原因 二.解決方法 1.查詢活動會話 2.記下SID和SERIAL# 3.斷開會話 4.刪除用戶 一.原因 ORA-01940代表你正在刪除一個有活動會話的用戶 二.解決方法 1.查詢活動會話 SQL> SELECT sid, serial#, username, programFROM v$sessionWHERE username 你要刪除的u…

重寫mybatisPlus自定義ID生成策略

1.項目中需要引入mybatisplus核心組件 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mp.version}</version></dependency> 2.新建一個類實現IdentifierGenera…

直接寫和放在函數中不同的R語言用法

索引數據框中的某一列 df$A可以索引數據框df中列名為A的列的所有值。那么假如列名是一個R對象怎么做&#xff1f; df <- data.frame(A1:5, B(1:5)*2)df$A## [1] 1 2 3 4 5needed_column A# df$needed_column ? Wrong# 注意是雙方括號 df[[needed_column]]## [1] 1 2 3 4…

微信小程序bindgetphonenumber獲取手機號阻止冒泡觸發

問題&#xff1a;點擊手機號彈出微信的手機號驗證組件&#xff0c;這是可以的。但是我點擊車牌號&#xff0c;也彈出來了&#xff0c;這就郁悶了。 以下是解決方法 點擊手機號時&#xff0c;彈出選擇手機號 解決&#xff1a; <view style"display: flex;justify-conte…