二刷蒼穹外賣 day02

新增員工

DTO

將前端傳遞的參數列表通過對應的實體類接收
當前端提交的數據和實體類中對應的屬性差別較大時,使用DTO來封裝數據
![[Pasted image 20250611183830.png]]

@Data
public class EmployeeDTO implements Serializable {private Long id;private String username;private String name;private String phone;private String sex;private String idNumber;}

記得要implements Serializable,實現接口后,對象就具備了可序列化的能力

controller

/**  * 新增員工  */  
@PostMapping  
@ApiOperation("新增員工")  
public Result save(@RequestBody EmployeeDTO employeeDTO)  
{  log.info("新增員工:{}",employeeDTO);  employeeService.save(employeeDTO);  return Result.success();  
}

Result定義了后端的返回結果格式

Result

package com.sky.result;  import lombok.Data;  import java.io.Serializable;  /**  * 后端統一返回結果  * @param <T>  */  
@Data  
public class Result<T> implements Serializable {  private Integer code; //編碼:1成功,0和其它數字為失敗  private String msg; //錯誤信息  private T data; //數據  public static <T> Result<T> success() {  Result<T> result = new Result<T>();  result.code = 1;  return result;  }  public static <T> Result<T> success(T object) {  Result<T> result = new Result<T>();  result.data = object;  result.code = 1;  return result;  }  public static <T> Result<T> error(String msg) {  Result result = new Result();  result.msg = msg;  result.code = 0;  return result;  }  }

Result是一個通用的后端統一返回結果封裝類,用于向前端返回統一格式的響應數據

泛型參數表示返回的數據類型,可以是任何對象
屬性:
code 相應狀態碼,1表示成功,0或其他表示失敗
msg:描述錯誤信息,成功則為空
data:封裝返回給前端的具體數據,類型為泛型T

方法:
success()

只返回code=1
success(T object):靜態方法,返回包含具體數據的成功響應(code=1,data=object)
error(String msg):返回錯誤信息和失敗狀態碼

public static <T> Result<T>
是一個Java泛型方法的聲明,前一個表明了泛型方法的類型參數聲明部分
Result表示該方法返回一個Result類型的對象
static表示這是一個類方法,可通過類名調用

@Service

@Override  
public void save(EmployeeDTO employeeDTO) {  Employee employee = new Employee();  BeanUtils.copyProperties(employeeDTO,employee);  employee.setStatus(StatusConstant.ENABLE);  employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes());  employee.setCreateTime(LocalDateTime.now());  employee.setUpdateTime(LocalDateTime.now());  employee.setCreateUser(10L);  employee.setCreateUser(10L);employeeMapper.insert(employee);  
}

注意一下BeanUtils.copyProperties()方法,以后用的很多
用于將一個 JavaBean 對象(源對象)的屬性值復制到另一個 JavaBean 對象(目標對象)中。這里它將 EmployeeDTO 對象 employeeDTO 的屬性值復制到 Employee 對象 employee 中。通常,源對象和目標對象需有相同或兼容的屬性名及類型,這樣才能正確復制屬性值,比如 EmployeeDTO 中的 name 屬性若與 Employee 中的 name 屬性類型匹配,就會將 employeeDTOname 值復制到 employeename 屬性中 。

mapper

@Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user,status) " +  "values " +  "(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")  
void insert(Employee employee);

上面的是的屬性是數據庫屬性,下面的是后端
因為在application.yml中已經開啟了駝峰命名,所以二者可以對應

mybatis:configuration:#開啟駝峰命名map-underscore-to-camel-case: true

問題一 重名

使用全局異常處理器來解決問題

@ExceptionHandler
public 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);  }  
}

@ExceptionHandler 是一個注解,該方法用于處理特定類型的異常。比如在上述代碼中,標記的方法 exceptionHandler 專門處理 SQLIntegrityConstraintViolationException 類型的異常。當程序執行過程中拋出此類型異常時,就會執行被 @ExceptionHandler 標記的方法,根據異常信息進行相應處理,比如提取異常信息中的用戶名,返回特定的錯誤提示給前端,告知用戶用戶名已存在等。

![[Pasted image 20250611202502.png]]

問題二:

新增員工時,我們需要獲得當前登錄員工的id
使用JWT 令牌并相應給前端

當前端指令請求時,它所攜帶的JWT令牌可以解析出對應員工的登錄id;

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;  }  
}

在攔截器中已經解析出了員工的id

Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);  Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());  

第一行調用JwtUtil工具類的parseJWT方法,使用配置文件中的管理員密鑰對token令牌進行解析,將解析后的對象(包括id)存儲在claim對象中
通過JwtClaimsContant.EMP_ID這個常量作為鍵,獲取對應的用戶ID,得到字符串之后再轉換為Long類型

ThreadLocal

ThreadLocal是為每一個線程提供的一個單獨的存儲空間,具有線程隔離的效果,其他線程無法訪問

常用方法

public void set(T value)設置
public T get()獲取
public void remove()

解決流程

**![[Pasted image 20250611203416.png]]**

在初始工程中已經封裝了對應類

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();  
}

在一個多線程的 Web 應用中,不同的請求線程可能需要各自獨立的用戶 ID 標識。可以在某個請求線程開始處理業務時,調用setCurrentId方法設置該線程的用戶 ID,在處理業務過程中通過getCurrentId方法隨時獲取該線程的用戶 ID,處理完成后調用removeCurrentId方法清理資源。

在攔截器中存儲empid

 try {//.................Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("當前員工id:", empId);/將用戶id存儲到ThreadLocalBaseContext.setCurrentId(empId);//3、通過,放行return true;

在service中獲取局部變量的值

    public void save(EmployeeDTO employeeDTO) {//.............................//設置當前記錄創建人id和修改人idemployee.setCreateUser(BaseContext.getCurrentId());employee.setUpdateUser(BaseContext.getCurrentId());employeeMapper.insert(employee);}

員工分頁查詢

注意:
請求參數類型為Query,在路徑后拼接/admin/employee/page?name=zhangsan

返回數據中records數組使用Employee實體類對屬性進行了封裝

Controller

  @GetMapping("/page")@ApiOperation("員工分頁查詢")public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){log.info("員工分頁查詢,參數為:{}", employeePageQueryDTO);PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);//后續定義return Result.success(pageResult);}

方法返回值類型為Result<PageResult>Result是自定義的用于封裝響應結果的類,PageResult則可能是包含分頁數據的類。

PageResult是一個專用的數據載體
long total 總記錄數
List records 當前頁實際查詢到的數據集合

Result
是泛型的具體類型實例,data字段的類型是PageResult

service

@Override  
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {  PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());  Page<Employee>page=employeeMapper.pageQuery(employeePageQueryDTO);  long total=page.getTotal();  List<Employee> records=page.getResult();  return new PageResult(total,records);  
}

mappe層

<select id="pageQuery" resultType="com.sky.entity.Employee">  select * from employee    <where>  <if test="name !=null and name !=''">  and name like concat('%',${name},'%');        </if>  </where>  order by create_time desc  
</select>

查詢名字中間包含name的,不需要limit,分頁由pagehelper插件進行處理

操作時間字段問題

在WebMvcConfiguration中擴展SpringMVC消息轉換器
Spring Boot 默認使用 MappingJackson2HttpMessageConverter 處理 JSON 序列化 / 反序列化,但 Jackson 對日期類型的默認序列化規則會導致格式異常

  • 若實體類中是 DateLocalDateTime 等日期類型,Jackson 默認可能將其序列化為 時間戳拆分的數組(如 [年, 月, 日, 時, 分, 秒],與前端期望的格式(如 2022524112024)不匹配。
  • 將自定義的 MappingJackson2HttpMessageConverter 放到轉換器列表的第一位,確保優先使用(覆蓋默認的 Jackson 轉換器)。
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {  log.info("擴展消息轉換器...");  //創建一個消息轉換器對象  MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();  //需要為消息轉換器設置一個對象轉換器,對象轉換器可以將Java對象序列化為json數據  converter.setObjectMapper(new JacksonObjectMapper());  //將自己的消息轉化器加入容器內  converters.add(0, converter);  
}

啟用禁用員工賬號

Controller

@PostMapping("/status/{status}")  
@ApiOperation("啟用禁用員工賬號")  
public Result startOrStop(@PathVariable Integer status,@RequestParam("id") Long id  // 顯式聲明id來自請求參數
)  
{  log.info("啟用禁用員工賬號");  employeeService.startOrStop(status,id);  return Result.success();  
}

注意講義中當前方法中 Long id 參數未顯式聲明參數來源。在 Spring MVC 中,未標注@PathVariable/@RequestBody等注解的參數默認會嘗試從請求參數(@RequestParam)獲取,但如果請求中未傳遞id參數,會直接拋出MissingServletRequestParameterException(400 錯誤)。建議修改

編輯員工

回顯員工信息

controller

/**  * 根據id查詢員工信息  */  
@GetMapping("/{id}")  
@ApiOperation("根據id查詢員工信息")  
public Result<Employee> getById(@PathVariable Long id) {  Employee employee = employeeService.getById(id);  return Result.success(employee);  
}

service層

@Override  
public Employee getById(Long id) {  Employee employee = employeeMapper.getById(id);  employee.setPassword("****");  return employee;  
}

密碼主動修改很細節

修改信息

service

注意這里不能用builder(),因為builder只能是創建對象的時候使用

public void update(EmployeeDTO employeeDTO) {  Employee employee = new Employee();  BeanUtils.copyProperties(employeeDTO, employee);  employee.setUpdateTime(LocalDateTime.now());  employee.setUpdateUser(BaseContext.getCurrentId());  employeeMapper.update(employee);  }

在上一個功能中已經實現了可泛用的mapper,這里不需要再寫了

導入代碼

CategoryMapper.xml文件中注意到一個點
select 語句中使用where if test時需要"and",表示&
在update語句中set里不需要寫表示| ,有就滿足

<select id="pageQuery" resultType="com.sky.entity.Category">  select * from category    <where>  <if test="name != null and name != ''">  and name like concat('%',#{name},'%')        </if>  <if test="type != null">  and type = #{type}        </if>  </where>  order by sort asc , create_time desc</select>  <update id="update" parameterType="Category">  update category    <set>  <if test="type != null">  type = #{type},        </if>  <if test="name != null">  name = #{name},        </if>  <if test="sort != null">  sort = #{sort},        </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.DTO:

用來接受前端提交的數據以及不同層之間傳遞
當與實體類差別較大時使用

2.Result

通用后端統一返回結果封裝類,向前端返回統一格式的響應數據

3.public static Result

是一個Java泛型方法的聲明,前一個表明了泛型方法的類型參數聲明部分
Result表示該方法返回一個Result類型的對象
static表示這是一個類方法,可通過類名調用

4.BeanUtils.copyProperties()

一般將DTO賦值給對應的對象

5.重名

ExceptionHandler注解,當程序拋出對應異常時,會執行被@ExceptionHandler標記的方法

6.JWT令牌

通過JwTUtil.parseJWT可以解析令牌

7.ThreadLocal

僅本線程可用存儲空間
set get remove

8.分頁查詢

PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());
第一個參數employeePageQueryDTO.getPage()獲取到的是要查詢的頁碼,第二個參數employeePageQueryDTO.getPageSize()獲取到的是每頁顯示的記錄數

方法返回值類型為Result
PageResult是專門的數據載體,包括List records,即當前頁查詢到的數據集合
records

9.操作時間字段

更換自定義的轉換器覆蓋原有

10.啟用禁用員工賬號

未表明數據來源會默認從請求參數(@RequestParam)獲取,即帶有查詢參數(Query Parameters)的 URL 鏈接?xx=xx

11.xml文件 if條件

在select時要保證全滿足,即&,所以if 后要加"and"
在update時滿足一個修改一個,即 |,所以If 后不用加

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

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

相關文章

通過Heron Handoff 插件我們在figma設計中可以像sketch導出離線標注

一、設計交付的歷史困境與破局契機 在數字產品開發的全流程中&#xff0c;設計標注的高效傳遞始終是連接創意與實現的關鍵紐帶。傳統設計工具如 Sketch 憑借 Bluebeam、Sketch Measure 等插件構建了成熟的離線標注體系&#xff0c;設計師可將標注文件打包交付&#xff0c;開發…

SSE 數據的傳輸無法流式獲取

問題 調試過程中發現SSE數據返回的時間都是一樣的&#xff0c;懷疑是接口問題。 參考 EventSource數據一次性出來&#xff0c;并未流式輸出的原因_sourceevent為什么結果一下全部返回了-CSDN博客 處理 EventStream 不能流式返回的問題&#xff1a;Nginx 配置優化 解決方案 …

markdown文本轉換時序圖

好久沒更新了~這篇是markdown文本轉換時序圖的常用方法 文章目錄 前言一、Mermaid語法示例二、PlantUML語法示例三、在線工具快速轉換總結 前言 使用專業工具如Mermaid或PlantUML可以直接在Markdown中繪制時序圖。這些工具支持簡潔的語法&#xff0c;生成可嵌入文檔的圖表&…

谷粒商城-分布式微服務 -集群部署篇[一]

十九、k8s 集群部署 19.1 k8s 快速入門 19.1.1 簡介 Kubernetes 簡稱 k8s。是用于自動部署&#xff0c;擴展和管理容器化應用程序的開源系統。 中文官網 中文社區 官方文檔 社區文檔 概述 | Kubernetes 傳統部署時代&#xff1a; 早期&#xff0c;各個組織是在物理服務器上…

微信小程序- 用canvas生成排行榜

設計功能不是很復雜&#xff0c;也不想用插件&#xff0c;最終出現現在版本&#xff0c;主要用到微信小程序 wx.canvasToTempFilePath方法 // 直接調用改方法 createQRCode() {const qrCodeCanvasId "qrcodeCanvas";drawQrcode({width: 200,height: 200,canvasId: …

深度剖析:UI 設計怎樣為小程序構建極致輕量體驗

內容摘要 在小程序的世界里&#xff0c;用戶都追求快速、便捷的輕量體驗。但你是否好奇&#xff0c;為啥有些小程序能讓人輕松上手&#xff0c;快速達成目標&#xff0c;而有些卻讓人感覺繁瑣、卡頓&#xff1f;這里的關鍵差異&#xff0c;往往就藏在 UI 設計中。UI 設計到底施…

【網絡安全】Qt免殺樣本分析

初步研判 SHA256&#xff1a;9090807bfc569bc8dd42941841e296745e8eb18b208942b3c826b42b97ea67ff 我們可以看到引擎0檢出&#xff0c;是個免殺樣本&#xff0c;不過通過微步云沙箱的行為分析&#xff0c;已經被判為惡意 行為分析 進程行為 可以看到demo顯示調用了winver獲…

window 顯示驅動開發-如何查詢視頻處理功能(六)

D3DDDICAPS_FILTERPROPERTYRANGE請求類型 UMD 返回指向 DXVADDI_VALUERANGE 結構的指針&#xff0c;該結構包含傳遞D3DDDICAPS_FILTERPROPERTYRANGE請求類型時特定視頻流上特定篩選器設置允許的值范圍。 Direct3D 運行時在D3DDDIARG_GETCAPS的 pInfo 成員指向的變量中為特定視…

Oracle線上故障問題解決

----重啟電腦找不到sid Listener refused the connection with the following error: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor Could not open connection sqlplus "/as sysdba" SQL> shutdown immediate 數據庫…

語音信號處理三十——高效多相抽取器(Polyphase+Noble)

文章目錄 前言一、Polyphase 多項分解1.定義2.拆分公式3.推導過程1&#xff09;按模 M M M拆分求和項2&#xff09;提取因子 4.總結 二、Noble恒等式1. 定義2.Noble恒等式表達方式1&#xff09;抽取系統的 Noble 恒等式2&#xff09;插值系統的 Noble 恒等式 2.Nodble恒等式推導…

廣告推薦系統中模型訓練中模型的結構信息、Dense數據、Sparse數據

下面結合廣告推薦系統常見的深度學習模型(比如 Wide & Deep、DeepFM、Two-Tower 等),介紹一下“模型的結構信息”、Dense 數據和 Sparse 數據在訓練過程中的角色及處理方式。 模型結構信息 輸入層(Input Layer) ? Sparse 輸入:各類離散高維特征(用戶 ID、廣告 ID、…

安全生產管理是什么?安全生產管理主要管什么?

安全生產管理是什么&#xff1f;安全生產管理主要管什么&#xff1f; 不管是制造業、建筑業&#xff0c;還是倉儲、物流、化工等等&#xff0c;一聊到“安全事故”&#xff0c;大家腦子里最先冒出來的兩個詞&#xff0c;肯定就是&#xff1a; 人的不安全行為物的不安全狀態 …

SecureRandom.getInstanceStrong() 與虛擬機的愛恨情仇

問題描述 使用Ruoyi-cloud 二開&#xff0c;將服務部署到虛擬機上后&#xff0c;準備登錄&#xff0c;發現驗證碼一致加載不出來&#xff0c;接口請求超時! 解決步驟 telnet 虛擬機ipport 發現可以通.curl 接口&#xff0c;發現一致不返回&#xff0c;超時了./code 接口超時&am…

DEM 地形分析與水文建模:基于 ArcGIS 的流域特征提取

技術點目錄 一、 GIS理論及ArcGIS認識二、ArcGIS數據管理與轉換三、ArcGIS地圖制作與發布四、ArcGIS數據制備與編輯五、ArcGIS矢量空間分析及應用六、ArcGIS柵格空間分析及應用七、ArcGIS空間插值及應用八、DEM數據與GIS三維分析九、ArcGIS高級建模及應用十、綜合講解了解更多 …

芯伯樂XBLW GT712選型及應用設計指南

前言 在電子工程領域&#xff0c;精準的電流測量對于眾多電路設計與系統監控至關重要。芯伯樂推出的XBLW GT712電流傳感器以其獨特的優勢&#xff0c;成為工程師在諸多應用中的首選工具。本文將深入剖析XBLW GT712的工作原理、性能特點以及應用要點&#xff0c;為工程師提供詳…

MySQL查看連接情況

說明&#xff1a;本文介紹如何查看MySQL會話連接情況&#xff0c;方便排查MySQL占用CPU過高或其他問題。 連接數據庫 首先&#xff0c;使用命令行連接到MySQL數據庫 mysql -u[用戶名] -p[密碼] -h[主機IP] -P[端口號]如果MySQL就在本機上&#xff0c;那么如下即可 mysql -u…

圖文教程——Deepseek最強平替工具免費申請教程——國內edu郵箱可用

親測有效&#xff01;只需 4 步即可免費體驗最新最強的 AI 助手&#xff01; 最強AI助手 This account isn’t eligible for Google AI Pro plan Google AI Pro plan isn’t available in some countries or for people under a certain age. 問題終極解決方案&#xff1a; ht…

java轉PHP開發需要幾步?

PHP基礎入門指南&#xff08;面向Java開發者&#xff09; 作為Java開發者&#xff0c;你已經掌握了面向對象編程、變量類型和控制結構等核心概念&#xff0c;這將大大加速你學習PHP的過程。下面我將從語法差異和PHP特性兩個方面&#xff0c;幫助你快速上手PHP開發。 語法差異…

一種使用 PowerToys 的鍵盤管理器工具重新映射按鍵實現在 Windows 上快捷輸入字符的方式

文章目錄 一、問題背景二、安裝 PowerToys三、配置快捷鍵 一、問題背景 在之前的一篇文章中介紹了使用 Java 程序實現快捷鍵輸入字符的方式&#xff08;https://blog.csdn.net/TeleostNaCl/article/details/148158298&#xff09;&#xff0c;其原理是利用 后臺常駐的 Java 應…

Python環境搭建競賽技術

Python環境搭建競賽技術文章大綱 競賽背景與意義 Python環境搭建競賽旨在考察參賽者對Python開發環境的熟悉程度&#xff0c;包括工具選擇、配置優化和問題解決能力。此類競賽常見于編程教學、企業內訓或技術社區活動&#xff0c;強調實踐性和效率。 競賽核心考察點 環境隔…