Day02 員工管理,分類管理

新增員工

需求分析和設計

產品原型:

接口設計:

本項目約定:

? ? ? ? 管理端發出的請求,統一使用 /admin 作為前綴

? ? ? ? 用戶端發出的請求,統一使用 /user 作為前綴

數據庫表設計:

代碼開發

根據新增員工接口設計對應的 DTO:

package com.sky.dto;import lombok.Data;import java.io.Serializable;@Data
public class EmployeeDTO implements Serializable {private Long id;private String username;private String name;private String phone;private String sex;private String idNumber;}
    @PostMapping@ApiOperation("新增員工")public Result save(@RequestBody EmployeeDTO employeeDTO){log.info("新增了員工: {}", employeeDTO);employeeService.save(employeeDTO);return Result.success();}
    @Overridepublic void save(EmployeeDTO employeeDTO) {Employee employee = new Employee();//對象屬性拷貝BeanUtils.copyProperties(employeeDTO,employee);//設置賬號狀態,默認正常狀態,1表示正常,0表示鎖定employee.setStatus(StatusConstant.ENABLE);//設置加密后的密碼employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));//設置當前記錄的創建時間employee.setUpdateTime(LocalDateTime.now());employee.setCreateTime(LocalDateTime.now());//設置當前記錄的創建人id和修改人id//TODO 后期更改為當前登錄用戶的 idemployee.setCreateUser(10L);employee.setUpdateUser(10L);log.info("新增了員工: {}", employee);employeeMapper.save(employee);}
    @Insert("insert into sky_take_out.employee (name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user) " +"values (#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})")void save(Employee employee);
}

功能測試

功能測試方法:
通過接口文檔測試

? ? ? ? 通過前后端聯調測試

注意:由于開發階段前端和后端是并行開發的,后端完成某個功能后,此時前端對應的功能可能還沒有開發完成,導致無法進行前后端聯調測試,所以在開發階段,后端測試主要以接口文檔測試為主。

代碼完善

程序存在的問題:
錄入的用戶名已存在,拋出異常后沒有處理

? ? ? ? 新增員工時,創建人 id 和 修改人 id 設置了固定值

先在全局異常處理類中完成第一個問題

    @ExceptionHandlerpublic Result exceptionHandler(BaseException ex){log.error("異常信息:{}", ex.getMessage());return Result.error(ex.getMessage());}@ExceptionHandlerpublic Result exceptionHandler(SQLIntegrityConstraintViolationException ex){// Duplicate entry 'zhangsan' for key 'employee.idx_username'String message = ex.getMessage();if(message.contains("Duplicate entry")){String[] split = message.split(" ");String username = split[2];String msg = username + MessageConstant.ALREADY_EXISTS;return Result.error(msg);}else{return Result.error(MessageConstant.UNKNOWN_ERROR);}}
}

這里用到了方法重載

針對第二個問題,需要通過某種方式動態獲取當前登錄員工的 id

當登錄成功時,我們的 id 就已經在 claims 里面了,所以如果我們想反向拿出來也是可以辦到的

package com.sky.interceptor;import com.sky.constant.JwtClaimsConstant;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** jwt令牌校驗的攔截器*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校驗jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判斷當前攔截到的是Controller的方法還是其他資源if (!(handler instanceof HandlerMethod)) {//當前攔截到的不是動態方法,直接放行return true;}//1、從請求頭中獲取令牌String token = request.getHeader(jwtProperties.getAdminTokenName());//2、校驗令牌try {log.info("jwt校驗:{}", token);Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("當前員工id:", empId);//3、通過,放行return true;} catch (Exception ex) {//4、不通過,響應401狀態碼response.setStatus(401);return false;}}
}

注意第48行,就是我們需要的 empId,那么現在的問題就是怎么將這個 id 傳給我們的 service

的 save 方法。這里需要用到一個重要的知識 ThreadLocal

ThreadLocal 并不是一個 Thread,而是 Thread 的局部變量。

ThreadLocal 為每一個線程提供單獨一份存儲空間,具有線程隔離效果,只有在線程內才能獲取到對應的值,線程外則不能訪問

? ? ? ??

我們需要一個工具類用來調用 ThreadLocal 方法

package com.sky.context;public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}}

然后在校驗令牌時取出 empId,,并將他放入 threadlocal

最后要用的時候拿出來

員工分頁查詢

需求分析和設計

產品原型

接口設計

代碼開發

和前面新增員工一樣,我們需要一個與接口設計相對應的 DTO:

package com.sky.dto;import lombok.Data;import java.io.Serializable;@Data
public class EmployeePageQueryDTO implements Serializable {//員工姓名private String name;//頁碼private int page;//每頁顯示記錄數private int pageSize;}

    @GetMapping("/page")@ApiOperation("分頁查詢")public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){log.info("分頁查詢:{}", employeePageQueryDTO);PageResult pageResult = employeeService.page(employeePageQueryDTO);return Result.success(pageResult);}

    @Overridepublic PageResult page(EmployeePageQueryDTO employeePageQueryDTO) {PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());Page<Employee> page = employeeMapper.pagequery(employeePageQueryDTO);return new PageResult(page.getTotal(), page.getResult());}

拓展:PageHelper 的底層時 ThreadLocal 實現的

    <select id="pagequery" resultType="com.sky.entity.Employee">select * from sky_take_out.employee<where><if test="name != null and name != ' '">and name like concat('%', #{name}, '%')</if></where></select>

功能測試

這里會發現日期這邊看起來不舒服,接下來完善代碼解決這個問題

代碼完善

package com.sky.json;import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;/*** 對象映射器:基于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);}
}

解決方式:

? ? ? ? 方式一:在屬性上加入注解,對日期進行格式化??

? ? ? ? 方式二:在 WebMvcConfiguration 中拓展 Spring MVC 的消息轉換器,統一對日期類型進行? ? ? ? ? ? ? ? ? ? ? ? ?格式化處理

建議使用第二種,這個方法是固定的,是我們這個配置類繼承的父類里面就有的

啟用禁用員工賬號

需求分析和設計

產品原型

接口設計

代碼開發

    @PostMapping("/status/{status}")@ApiOperation("啟用或禁用員工")public Result start_or_stop(@PathVariable Integer status, Long id){log.info("啟用或禁用員工:{},{}", status, id);employeeService.start_or_stop(status, id);return Result.success();}
    @Overridepublic void start_or_stop(Integer status, Long id) {Employee employee = Employee.builder().status(status).id(id).build();employeeMapper.update(employee);}
    <update id="update">UPDATE sky_take_out.employee<set><if test="name != null and name != ''">name = #{name},</if><if test="username != null and username != ''">username = #{username},</if><if test="password != null and password != ''">password = #{password},</if><if test="phone != null and phone != ''">phone = #{phone},</if><if test="sex != null and sex != ''">sex = #{sex},</if><if test="idNumber != null and idNumber != ''">id_number = #{idNumber},</if><if test="status != null">status = #{status},</if><if test="updateTime != null">update_time = #{updateTime},</if><if test="updateUser!= null">update_user = #{updateUser}</if></set>WHERE id = #{id}</update>

功能測試

編輯員工

需求分析和設計

產品原型

接口設計

注意這里需要兩個接口

1:根據 id 查詢員工信息,也就是查詢回顯

2:編輯員工信息

代碼開發

首先是查詢回顯

    @GetMapping("/{id}")@ApiOperation("根據 id 查詢員工")public Result<Employee> queryById(@PathVariable Long id){log.info("查詢的員工的 id 為:{}", id);Employee employee = employeeService.queryById(id);return Result.success(employee);}
    @Overridepublic Employee queryById(Long id) {Employee employee = employeeMapper.queryById(id);return employee;}
    <select id="queryById" resultType="com.sky.entity.Employee">select * from sky_take_out.employee where id = #{id}</select>

然后是更新員工

    @PutMapping@ApiOperation("修改員工數據")public Result update(@RequestBody EmployeeDTO employeeDTO){log.info("修改員工:{}", employeeDTO);employeeService.update(employeeDTO);return Result.success();}
    @Overridepublic void update(EmployeeDTO employeeDTO) {Employee employee = new Employee();BeanUtils.copyProperties(employeeDTO,employee);employee.setUpdateUser(BaseContext.getCurrentId());employee.setUpdateTime(LocalDateTime.now());employeeMapper.update(employee);}
    <update id="update">UPDATE sky_take_out.employee<set><if test="name != null and name != ''">name = #{name},</if><if test="username != null and username != ''">username = #{username},</if><if test="password != null and password != ''">password = #{password},</if><if test="phone != null and phone != ''">phone = #{phone},</if><if test="sex != null and sex != ''">sex = #{sex},</if><if test="idNumber != null and idNumber != ''">id_number = #{idNumber},</if><if test="status != null">status = #{status},</if><if test="updateTime != null">update_time = #{updateTime},</if><if test="updateUser!= null">update_user = #{updateUser}</if></set>WHERE id = #{id}</update>


功能測試

導入分類模塊功能代碼

需求分析和設計

產品原型:

接口設計

代碼導入

因為這里和之前員工管理的部分基本一樣,所以直接導入即可,注意最好從后往前導入,也就是從Mapper 層開始導入,這樣會減少報錯,導入完之后記得手動編譯

功能測試

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

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

相關文章

[SC]SystemC 常見的編譯/語法錯誤與解法(三)

SystemC 常見的編譯/語法錯誤與解法(三) 摘要:下面按“現象/編譯信息 → 成因 → 解決方案”的結構,歸納 SystemC 建模在 SoC 驗證中常見的“編譯期/語法層面”問題,并補充如何根據編譯信息快速定位與如何在流程上避免這些問題。 一、SystemC 常見的編譯/語法錯誤與…

06-docker容器常用命令

文章目錄一.docker容器相關指令概述二.生產環境中常用的 docker容器相關指令1.創建容器(create)2.查看已創建的容器(ps&#xff0c;ls&#xff0c;list)3.運行一個已創建的容器(start)4.停止一個正在運行的容器(stop)5.重啟容器(restart)6.創建并啟動一個容器(run&#xff0c;等…

Xiphos Q8 攝像頭板 高性能圖像處理板

我們的高性能圖像處理板設計用于與具有兩個 Camera Link 接口&#xff08;2x Base 或 1x Medium&#xff09;的 Q8 混合處理器卡配合使用。接口&#xff1a; 2個Camera Link接口 4個SpaceWire接口 4個USB 2.0主端口 串行接口和 GPIO 多個 Vcc 輸出&#xff08;5.0、3.3 和 1.8V…

Rocky Linux 10 搭建 NFS 服務詳細步驟

1.NFS描述 NFS&#xff0c;全稱為Network File System&#xff0c;即網絡文件系統&#xff0c;是一種分布式文件系統協議&#xff0c;允許一個系統在網絡上與他人共享目錄和文件。通過NFS&#xff0c;用戶和程序可以像訪問本地文件一樣訪問遠端系統上的文件。以下是NFS的一些主…

Android MediaMetadataRetriever取視頻封面,Kotlin(1)

Android MediaMetadataRetriever取視頻封面&#xff0c;Kotlin&#xff08;1&#xff09; <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE&qu…

qt的元對象系統詳解

Qt 的元對象系統&#xff08;Meta-Object System&#xff09;&#xff0c;這是 Qt 框架最核心、最強大的特性之一。 1.什么是 Qt 的元對象系統&#xff1f; Qt 的元對象系統&#xff08;Meta-Object System&#xff09;是 Qt 在標準 C 基礎上擴展的一套機制&#xff0c;它為 C …

Nginx 性能優化與動態內容處理

一、壓縮功能 實驗目的&#xff1a;通過啟用 Nginx 的 Gzip 壓縮功能&#xff0c;對傳輸的文件&#xff08;如 HTML、日志等&#xff09;進行壓縮&#xff0c;減少網絡傳輸數據量&#xff0c;提升用戶訪問速度&#xff08;尤其適用于帶寬有限的場景&#xff09;&#xff0c;同…

ComfyUI——舒服地讓大模型為我所用

主頁&#xff1a;ComfyUI | 用AI生成視頻、圖像、音頻 https://github.com/comfyanonymous/ComfyUI 安裝環境 我的環境是mac&#xff0c;芯片為M4pro。首先從github中下載工程&#xff0c;clone失敗就直接下載zip壓縮包。在model文件夾中&#xff0c;可以看到很多大名鼎鼎的…

【Visual Studio】使用VS調試(Debug)

確保在Debug模式下而不是Release 打斷點(break point) 直接在有代碼的行前單擊&#xff0c;會出現紅色的點(再次單擊會取消)&#xff1b;或者光標停留在某行&#xff0c;按F9 這意味著程序當執行到這一行時會終止 在打完斷點后點擊”本地Windows調試器“或者按F5 往下翻會有代碼…

B2.0:對硬件學習的一些個人心得感悟

對于硬件學習&#xff0c;所有人都會迷茫的找不到學習的路徑和方向&#xff0c;都是自我摸索或者老師帶領或者其他情況&#xff0c;而我倒是沒有機會接觸到現實的老師帶我領進這個門&#xff0c;自然走的彎路比較多&#xff0c;所以引申出這篇文章&#xff0c;來聊聊硬件學習的…

Cursor設置

一&#xff1a;設置 Port: 7890TUN Mode&#xff1a;開啟二&#xff1a;Editor Settings值為http://127.0.0.1:7890三&#xff1a;Cursor 測試一下

Windows下使用PyInstaller打包PyQt項目

在 Windows 環境下&#xff0c;使用 PyQt 開發的項目可以通過多種工具打包成 可執行文件&#xff08;.exe&#xff09;&#xff0c;以下是幾種常見的方法及詳細步驟&#xff1a;1. 使用 PyInstallerPyInstaller 是最常用的 Python 打包工具&#xff0c;支持 PyQt5/PyQt6/PySide…

AI大語言模型在生活場景中的應用日益廣泛,主要包括四大類需求:文本處理、信息獲取、決策支持和創意生成。

一、AI大語言模型生活應用全景圖&#xff08;Mermaid流程圖&#xff09;graph TDA[生活小事需求] --> B{需求分類}B --> C[文本處理類]B --> D[信息獲取類]B --> E[決策支持類]B --> F[創意生成類]C --> C1[郵件寫作]C --> C2[內容潤色]C --> C3[文檔總…

物奇路由器Wi-Fi芯片榮膺2025中國創新IC-強芯領航獎,并亮相第五屆RISC-V中國峰會

近日&#xff0c;第五屆中國集成電路設計創新大會在蘇州舉辦&#xff0c;物奇攜多款高性能網絡通信與終端人工智能芯片亮相展會&#xff0c;其中首顆路由器Wi-Fi6芯片WQ9301憑借獨特的架構創新和領先的性能優勢&#xff0c;在國產IC強芯評選中脫穎而出&#xff0c;榮膺2025中國…

【已解決】npm install報錯

~/autodl-tmp/App/magic_conch_frontend# npm install報錯內容&#xff1a;WARN EBADENGINE Unsupported engine { npm WARN EBADENGINE package: vitejs/plugin-vue5.1.4, npm WARN EBADENGINE required: { node: ^18.0.0 || >20.0.0 }, npm WARN EBADENGINE current: { no…

IPC總結

IPC 是 Inter-Process Communication&#xff08;進程間通信&#xff09;的縮寫&#xff0c;指的是操作系統中不同進程之間傳遞數據、交換信息或同步行為的機制。由于進程在內存中擁有獨立的地址空間&#xff0c;無法直接訪問彼此的內存&#xff0c;因此需要通過操作系統提供的…

java之父-新特性

目錄 一.函數式接口Functional Interface 1. Supplier接口 --供給型接口 2. Consumer接口 --消費型接口 3.Function接口 --轉換型接口 4. Predicate接口--斷言型接口 5. Comparator接口--比較器接口 一.函數式接口Functional Interface 只有一個抽象方法的接口&#xff…

GPT-5的多模態能力如何?

GPT-5的多模態能力如何&#xff1f;概述問題1-非整點鬧鐘問題2-數數問題一問題3-數數問題二小結概述 2025年&#xff0c;8月8日凌晨&#xff0c;OpenAI 發布了 GPT-5&#xff0c;讓我們看看其多模態能力如何&#xff0c;用之前大模型無法解決的題目測試&#xff0c;數數問題時…

多模態RAG賽題實戰--Datawhale AI夏令營

參考自科大訊飛AI大賽&#xff08;多模態RAG方向&#xff09; - Datawhale 賽題意義&#xff1a; 我們正處在一個信息爆炸的時代&#xff0c;但這些信息并非以整潔的純文本形式存在。它們被封裝在各種各樣的載體中&#xff1a;公司的年度財報、市場研究報告、產品手冊、學術論…

SQL Server 創建 PostgreSQL 數據庫 鏈接服務器指南

SQL Server 創建 PostgreSQL 數據庫 鏈接服務器指南SQL Server 創建 PostgreSQL 數據庫 鏈接服務器指南一、準備工作二、創建鏈接服務器三、測試連接四、常見問題解決五、注意事項SQL Server 創建 PostgreSQL 數據庫 鏈接服務器指南 一、準備工作 安裝 PostgreSQL ODBC 驅動&a…