1. 相關視頻
Day2的全部視頻集數
2. 學習記錄
2.1 對象屬性拷貝
當DTO與實體類或者VO對象之間的一個裝換的時候,如果通過new創建對象,然后調用set方法進行屬性賦值,不夠方便,代碼不夠簡潔。當屬性過多時候,代碼就會顯得臃腫。所以采用對象屬性拷貝。推薦使用MapStruct
public void save(EmployeeDTO employee){BeanUtils.copyProperties(employeeDTO,employee);
}
MapStruct 快速指南 | Baeldung中文網
2.2 分頁查詢
分頁查詢,項目經常遇到的功能,本人也學過相關的知識,編寫過相關的代碼,這里也記錄一下
對于分頁,可以采取MySQL的limit關鍵字,但是在實際項目的開發,這樣寫不夠代碼的簡潔以及提高代碼量,工作效率低下,因此還是使用框架來進行分頁查詢的開發
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pagehelper}</version>
</dependency>
( 對于版本的多少,可以去maven的repository復制,這里主要是作于技術的記錄 )
這個插件底層是基于mybatis的攔截器,會將我們的sql語句查詢進行一個拼接,動態拼接limit的參數,并且基于參數的計算輸出結果
這里使用分頁查詢插件,最終也還是使用到MySQL的語句進行查詢,似乎好像還有其他的框架可以不需要寫MySQL語句,直接就是調用就可以返回相關的結果,這個大家可以在評論區討論
前提準備
@Data
public class EmployeePageQueryDTO implements Serializable {//員工姓名private String name;//頁碼private int page;//每頁顯示記錄數private int pageSize;}/*----------------------------------------------------------------*//*** 封裝分頁查詢結果*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {private long total; //總記錄數private List records; //當前頁數據集合}
@Service
public class EmployeeServiceImpl implements EmployeeService { /*** 分頁查詢** @param pageQueryDTO 分頁查詢參數* @return 分頁結果*/@Overridepublic PageResult page(EmployeePageQueryDTO pageQueryDTO) {// 使用pageHelper分頁查詢PageHelper.startPage(pageQueryDTO.getPage(), pageQueryDTO.getPageSize());// 這里需要進行MySQL語句的查詢Page<Employee> page = employeeMapper.page(pageQueryDTO);long total = page.getTotal();List<Employee> records = page.getResult();return new PageResult(total, records);}
}/*--------------------------------------------------------------------*/@Mapper
public interface EmployeeMapper {/*** 分頁查詢* @param pageQueryDTO 分頁查詢參數* @return 分頁結果*/Page<Employee> page(EmployeePageQueryDTO pageQueryDTO);
}
<?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.sky.mapper.EmployeeMapper"><select id="page" resultType="com.sky.entity.Employee">select * from employee<where><if test="name != null and name != ''">and name like concat('%', #{name}, '%')</if>order by crate_time desc</where></select>
</mapper>
使用like關鍵字進行一個模糊查詢
友情提醒:mapper文件中的SQL語句不要加分號,否則會報錯,因為你加分號之后,limit拼接在之后,就不是正確的mysql語句
3. JWT流程 && ThreadLocal
4. 時間格式處理
推薦使用第二種方式,因為第二種方式是一個統一的配置。如果沒有進行一個配置的話,那么返回的是一個集合。另外這里的converters是我們Spring MVC中所有的轉換器,并且有順序排列使用,增加的消息轉換器是排在最后,那么為了讓我們自定義的轉換器優先使用,就需要設置權重
注意:是MappingJackson2HttpMessageConverter,不是MappingJackson2CborHttpMessageConverter,沒有Cbor
/*** 對象映射器:基于jackson將Java對象轉為json,或者將json轉為Java對象* 將JSON解析為Java對象的過程稱為 [從JSON反序列化Java對象]* 從Java對象生成JSON的過程稱為 [序列化Java對象到JSON]*/
public class JacksonObjectMapper extends ObjectMapper {public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";//public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";public JacksonObjectMapper() {super();//收到未知屬性時不報異常this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);//反序列化時,屬性不存在的兼容處理this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);SimpleModule simpleModule = new SimpleModule().addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));//注冊功能模塊 例如,可以添加自定義序列化器和反序列化器this.registerModule(simpleModule);}
}
5. 完善蒼穹外賣 —— 密碼修改業務
自己完成蒼穹外賣的員工密碼修改功能
定義傳輸數據的DTO對象
一開始,看著接口文檔還有一個Integer類型的empId,但是經過我后面調試,以及在前端使用f12開啟開發者工具,發現前端的請求只有下方兩個屬性,因此進行修改
@Data
public class EmployeePasswordDTO {private String newPassword;private String oldPassword;
}
因為這個業務涉及到如果員工的舊密碼輸入不對,那么無法進行一個密碼的修改,因此需要定義一個常量OLD_PASSWORD_ERROR和將修改方法的類型設計為boolean類型,不是void類型
/*** 信息提示常量類*/
public class MessageConstant {public static final String OLD_PASSWORD_ERROR = "舊密碼輸入錯誤";
}
// Controller層/*** 修改密碼* @param passwordDTO 密碼DTO* @return 修改結果*/@PutMapping("/editPassword")@ApiOperation(value = "修改員工密碼")public Result<String> updatePassword(@RequestBody EmployeePasswordDTO passwordDTO){log.info("修改密碼:{}", passwordDTO);if (!employeeService.updatePassword(passwordDTO))return Result.error(MessageConstant.OLD_PASSWORD_ERROR);return Result.success();}
// ServiceImpl層/*** 修改員工密碼** @param passwordDTO 員工密碼信息*/@Overridepublic boolean updatePassword(EmployeePasswordDTO passwordDTO) {Long empId = BaseContext.getCurrentId();Employee employee = employeeMapper.getById(empId);String oldPassword = DigestUtils.md5DigestAsHex(passwordDTO.getOldPassword().getBytes());if (!employee.getPassword().equals(oldPassword)) {return false;}employee.setPassword(DigestUtils.md5DigestAsHex(passwordDTO.getNewPassword().getBytes()));employee.setUpdateTime(LocalDateTime.now());employee.setUpdateUser(empId);employeeMapper.update(employee);return true;}
這里ServiceImpl沒有做很多解釋,有涉及MD5密碼的一個不可逆,更新時間以及更新用戶的修改,MySQL的修改的語句等這些內容,大家自己看看代碼吧,如果是在看不懂,那么評論提出疑問,看到就會即時回復給大家
至于這個繼承的接口層就不詳細放出,如果這個不會,那么這個博客沒有看的必要,先打好基礎