跟做springboot尚品甄選項目(二)

登錄功能的書寫

后端接口的書寫

(1)創建配置文件

粘貼這兩個文件(E:\project\AllProJect\Shangpin Selection\項目材料素材\資料\資料\03-配置文件)

在spzx-manager服務的src/resources目錄下創建application.yml、application-dev.yml文件,文件的內容如下所示:

# application.yml文件內容==================================================================================
spring:application:name: service-managerprofiles:active: dev		# 激活的環境文件#  application-dev.yml文件內容=============================================================================
# 配置服務端口號
server:port: 8501# 配置數據庫連接信息
spring:datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_spzx?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: root# Redis的相關配置data:redis:host: localhostport: 6379
#  password: 1234# mybatis的配置
mybatis:config-location: classpath:/mybatis-config.xmlmapper-locations: classpath:/mapper/*/*.xml

導入課程資料中提供的:mybatis-config.xml和logback-spring.xml配置文件

(2)創建啟動類

ManagerApplication

package com.atguigu.spzx;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ManagerApplication {public static void main(String[] args) {SpringApplication.run(ManagerApplication.class , args) ;}}

(3)創建實體類

SysUser

創建與數據庫表對應的實體類:

BaseEntity: 定義一個BaseEntity實體類,在該實體類中定義公共的屬性

  • 類名: BaseEntity
  • 包路徑: com.xuan.spzx.model.entity.base
  • 用途: 為其他實體類提供通用字段
  • 使用@Data注解(Lombok)自動生成getter/setter方法
  • 使用@Schema注解為Swagger API文檔提供字段說明
  • 使用@JsonFormat注解格式化日期時間顯示格式
  • 實現Serializable接口支持序列化
// com.xuan.spzx.model.entity.base
package com.xuan.spzx.model.entity.base;import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;import java.io.Serializable;
import java.util.Date;@Data
public class BaseEntity implements Serializable {@Schema(description = "唯一標識")private Long id;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@Schema(description = "創建時間")private Date createTime;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@Schema(description = "修改時間")private Date updateTime;@Schema(description = "是否刪除")private Integer isDeleted;}

SysUser用戶實體類定義:

// com.xuan.spzx.model.entity.system
@Data
public class SysUser extends BaseEntity {private static final long serialVersionUID = 1L;private String userName;  // 該字段的屬性名稱和數據表字段不一致private String password;private String name;private String phone;private String avatar;private String description;private Integer status;}
LoginDto

創建一個LoginDto實體類,封裝登錄請求參數。

// com.xuan.spzx.model.dto.system
package com.xuan.spzx.model.dto.system;import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;@Data
@Schema(description = "用戶登錄請求參數")
public class LoginDto {@Schema(description = "用戶名")private String userName ;@Schema(description = "密碼")private String password ;@Schema(description = "提交驗證碼")private String captcha ;@Schema(description = "驗證碼key")private String codeKey ;}
LoginVo

創建一個LoginVo實體類,封裝登錄成以后響應結果數據。

package com.xuan.spzx.model.vo.system;import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;@Data
@Schema(description = "登錄成功響應結果實體類")
public class LoginVo {@Schema(description = "令牌")private String token ;@Schema(description = "刷新令牌,可以為空")private String refresh_token ;}

(4)三層書寫

IndexController

表現層代碼實現(初始化->引入Service業務代碼->用戶登錄)

package com.atguigu.spzx.controller;import com.atguigu.spzx.model.dto.system.LoginDto;
import com.atguigu.spzx.model.vo.common.Result;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.system.LoginVo;
import com.atguigu.spzx.service.SysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@Tag(name = "用戶接口")
@RestController
@RequestMapping(value = "/admin/system/index")
public class IndexController {@Autowiredprivate SysUserService sysUserService ;@Operation(summary = "登錄接口")@PostMapping(value = "/login")public Result<LoginVo> login(@RequestBody LoginDto loginDto) {LoginVo loginVo = sysUserService.login(loginDto) ;return Result.build(loginVo , ResultCodeEnum.SUCCESS) ;}}
SysUserService

業務層代碼實現(初始化->引入Mapper的代碼->業務代碼)

實現類

impl/SysUserServiceImpl它實現了SysUserService接口。該類被@Service注解標記,表明它是一個Spring框架管理的業務服務層組件,負責處理系統用戶相關的業務邏輯

package com.xuan.spzx.manager.service.impl;
import com.alibaba.fastjson.JSON;
import com.xuan.spzx.manager.mapper.SysUserMapper;
import com.xuan.spzx.manager.service.SysUserService;
import com.xuan.spzx.model.dto.system.LoginDto;
import com.xuan.spzx.model.entity.system.SysUser;
import com.xuan.spzx.model.vo.system.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;import java.util.UUID;
import java.util.concurrent.TimeUnit;@Service
public class SysUserServiceImpl implements SysUserService {@Autowiredprivate SysUserMapper sysUserMapper;@Autowiredprivate RedisTemplate<String,String> redisTemplate;//用戶登錄@Overridepublic LoginVo login(LoginDto loginDto) {//1.獲取提交用戶名,LoginDto獲取到String userName = loginDto.getUserName();//2.根據用戶名查詢數據庫用戶表sys_userSysUser sysUser =sysUserMapper.selectUserInfoByUserName(userName);//3.如果用戶名查不到對應信息,用戶不存在,返回錯誤信息if (sysUser == null){throw new RuntimeException("用戶不存在");}//4.如果用戶名存在,則判斷輸入密碼與數據庫密碼是否一致//把輸入密碼進行md5加密String database_password = sysUser.getPassword();//數據庫密碼String input_password =DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes());//比較if(!input_password.equals(database_password)){throw new RuntimeException("密碼錯誤");}//5.如果一致,則返回登錄成功信息,如果不一致登錄失敗//登錄成功生成用戶唯一標識tokenString token = UUID.randomUUID().toString().replaceAll("-","");//6.把用戶信息保存到redis中//key: token value:用戶信息redisTemplate.opsForValue().set("user:login"+token,JSON.toJSONString(sysUser),7,TimeUnit.DAYS);//7.返回登錄成功信息,loginVo對象返回LoginVo loginVo = new LoginVo();loginVo.setToken(token);return loginVo;}
}
SysUserMapper

@Mapper注解

  • 作用: 標識這是一個MyBatis的Mapper接口
  • 功能: MyBatis會自動為該接口生成實現類,用于執行數據庫操作
  • 持久層代碼實現

這個Mapper接口主要用于用戶登錄驗證:

  • 當用戶輸入用戶名和密碼進行登錄時
  • 系統通過該接口查詢對應用戶名的用戶信息
  • 獲取到用戶數據后,驗證密碼是否正確
  • 完成用戶身份認證

@Mapper
public interface SysUserMapper {/*** 根據用戶名查詢用戶數據* @param userName* @return*/public abstract SysUser selectByUserName(String userName) ;}
SysUserMapper.xml

目錄和配置文件中的sql映射,位置有關系

創建映射文件并且編寫sql語句: 文件位置classpath: /mapper/system/SysUserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuan.spzx.manager.mapper.SysUserMapper"><sql id="columns">id,username userName ,password,name,phone,avatar,description,status,create_time,update_time,is_deleted</sql><select id="selectUserInfoByUserName" resultType="com.xuan.spzx.model.entity.system.SysUser">SELECT <include refid="columns"/> FROM sys_user where userName = #{userName}</select>
</mapper>

(5)測試啟動

啟動:我啟動時遇到兩處報錯

1.lombok的版本報錯問題

java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCIm

Lombok在早期版本中使用反射訪問com.sun.tools.javac.tree.JCTree$JCImport類的qualid字段,該字段在Java 21中的類型發生了變化,在Java 21及更高版本中,qualid字段的類型從JCTree變更為JCFieldAccess。這導致了Lombok無法正確訪問該字段,從而拋出NoSuchFieldError異常。

在項目的依賴項中添加Lombok的最新版本

在修改項目父文件的pom.xml

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<version>1.18.32</version>

</dependency>

2.yml文件縮進錯誤

#spring:
#  application:
#    name: service-manager
#  profiles:
#    active:dev
# application.yml
spring:profiles:active: dev  # 這里指定默認環境

啟動成功!

http://localhost:8501/doc.html#/home

添加中文提示,重啟

點擊測試

docker restart redis

重啟

(6)異常處理

新建包

新建GlobalExceptionHandler類->全局異常

package com.xuan.spzx.common.exception;import com.xuan.spzx.model.vo.common.Result;
import com.xuan.spzx.model.vo.common.ResultCodeEnum;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice
public class GlobalExceptionHandler {//全局異常處理@ExceptionHandler(Exception.class)//攔截所有異常,所有異常都用這個方法處理@ResponseBodypublic Result error(){return Result.build(null, ResultCodeEnum.SYSTEM_ERROR);}
}

新建GuiguException類->自定義

package com.xuan.spzx.common.exception;import com.xuan.spzx.model.vo.common.ResultCodeEnum;
import lombok.Data;@Datapublic class GuiguException extends RuntimeException {private Integer code;private String message;private ResultCodeEnum resultCodeEnum;public GuiguException(ResultCodeEnum resultCodeEnum) {this.code = resultCodeEnum.getCode();this.message = resultCodeEnum.getMessage();this.resultCodeEnum = resultCodeEnum;}}

在第一個里面引入自定義異常

    //自定義異常處理@ExceptionHandler(GuiguException.class)@ResponseBodypublic Result error(GuiguException e){return Result.build(null, e.getResultCodeEnum());}
package com.xuan.spzx.common.exception;import com.xuan.spzx.model.vo.common.Result;
import com.xuan.spzx.model.vo.common.ResultCodeEnum;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice
public class GlobalExceptionHandler {//全局異常處理@ExceptionHandler(Exception.class)//攔截所有異常,所有異常都用這個方法處理@ResponseBodypublic Result error(){return Result.build(null, ResultCodeEnum.SYSTEM_ERROR);}//自定義異常處理@ExceptionHandler(GuiguException.class)@ResponseBodypublic Result error(GuiguException e){return Result.build(null, e.getResultCodeEnum());}
}

修改登錄使用異常

  if (sysUser == null){
//            throw new RuntimeException("用戶不存在");throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);}if(!input_password.equals(database_password)){
//            throw new RuntimeException("密碼錯誤");throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);}

重啟成功

前端接入登錄

當后端接口開發好了以后就可以讓前端去請求該登錄接口完成登錄操作。

修改前端代碼

修改src/utils/request.js更改基礎請求路徑

const service = axios.create({baseURL: 'http://localhost:8501',    // 后端服務的ip地址和端口號timeout: 10000,withCredentials: true,
})

修改src/api/login.js更改登錄接口地址

// 登錄接口
export const Login = data => {return request({url: '/admin/system/index/login',method: 'post',data,})
}

發送登錄請求,那么此時會報一個錯誤:

報錯的原因是因為此時的請求是一個跨域的請求。

跨域請求

跨域請求簡介

跨域請求:通過一個域的JavaScript腳本和另外一個域的內容進行交互

域的信息:協議、域名、端口號

同域:當兩個域的協議、域名、端口號均相同

如下所示:

同源【域】策略:在瀏覽器中存在一種安全策略就是同源策略,同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。同源策略會阻止一個域的javascript腳本和另外一個域的內容進行交互。

CORS概述

官網地址:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

  • CORS的全稱為Cross-origin Resource Sharing,中文含義是跨域資源共享
  • CORS 是跨域的一種解決方案,CORS 給了web服務器一種權限:服務器可以選擇是否允許跨域請求訪問到它們的資源。

CORS解決跨域

后端服務器開啟跨域支持:

方案一:在IndexController上添加**@CrossOrigin**注解

@RestController
@RequestMapping(value = "/admin/system/index")
@CrossOrigin(allowCredentials = "true" , originPatterns = "*" , allowedHeaders = "*") 
public class IndexController {}

弊端:每一個controller類上都來添加這樣的一個接口影響開發效率、維護性較差

方案二:添加一個配置類配置跨域請求(用這個,全局)

// com.atguigu.spzx.manager.config
@Component
public class WebMvcConfiguration implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")      // 添加路徑規則.allowCredentials(true)               // 是否允許在跨域的情況下傳遞Cookie.allowedOriginPatterns("*")           // 允許請求來源的域規則.allowedMethods("*").allowedHeaders("*") ;                // 允許所有的請求頭}}

重啟后端->成功

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

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

相關文章

前后端接口調試提效:Postman + Mock Server 的工作流

前后端接口調試提效&#xff1a;Postman Mock Server 的工作流 &#x1f31f; Hello&#xff0c;我是摘星&#xff01; &#x1f308; 在彩虹般絢爛的技術棧中&#xff0c;我是那個永不停歇的色彩收集者。 &#x1f98b; 每一個優化都是我培育的花朵&#xff0c;每一個特性都是…

大帶寬香港云服務器在數據傳輸速度上有何優勢?

為方便站長快速部署網站、優化用戶訪問體驗&#xff0c;當下眾多實力強勁的香港數據中心&#xff0c;均推出了大帶寬云服務器產品。不過&#xff0c;市面上不少數據中心雖宣稱提供 “專屬大帶寬”&#xff0c;但其線路配置中&#xff0c;國際線路占比高、繞行鏈路多&#xff0c…

HT862 智能音頻功率放大器:為便攜音頻設備打造高效穩定的音質解決方案

在藍牙音箱、智能手機、便攜式游戲機等設備的設計中&#xff0c;音頻功率放大器是決定音質表現、續航能力與使用穩定性的關鍵部件。一款優質的音頻功放&#xff0c;不僅需要輸出足夠的功率以滿足清晰響亮的聽覺需求&#xff0c;還需在能效、溫控、適配性上達到平衡&#xff0c;…

HarmonyOS-ArkUI Web控件基礎鋪墊7-HTTP SSL認證圖解 及 Charles抓包原理 及您為什么配置對了也抓不到數據

HarmonyOS-ArkUI Web控件基礎鋪墊6--TCP協議- 流量控制算法與擁塞控制算法 HarmonyOS-ArkUI Web控件基礎鋪墊5--TCP協議- 動畫展示超時重傳&#xff0c;滑動窗口&#xff0c;快速重傳 HarmonyOS-ArkUI Web控件基礎鋪墊4--TCP協議- 斷聯-四次揮手解析 HarmonyOS-ArkUI Web控件…

【qt】通過TCP傳輸json,json里包含圖像

主要是使用協議頭 發送方connect(m_pDetectWorker, &DetectionWorker::sig_detectImg, this, [](const QJsonObject &json){// 轉換為JSON數據QJsonDocument doc(json);QByteArray jsonData doc.toJson(QJsonDocument::Compact);// 構建增強協議頭struct EnhancedHead…

四,基礎開發工具(下)

4.5自動構建make/Makefile4.5.1基本使用1示例2進一步解釋3實踐4最佳實踐4.6練習&#xff1a;進度條4.6.1倒計時4.6.2進度條version14.6.2進度條version24.7版本控制器Git4.7.1git操作1操作一次&#xff0c;以后不愁2經典"三件套"3常用4版本回退4.7.2小結4.5自動構建m…

C++基本數據類型的范圍

文章目錄不同位數的系統下各個類型所占字節數如何存儲的我發現我能搜到的相關文章都只講了這些數據類型的范圍是這樣的&#xff0c;不說實際的存儲情況&#xff0c;當你了解了類型實際是如何存儲的&#xff0c;再去記憶這些范圍就簡單了&#xff0c;所以就有了這篇文章不同位數…

基于社交媒體數據的公眾情緒指數構建與重大事件影響分析

一、引言在信息爆炸的時代&#xff0c;社交媒體&#xff08;如微博、Twitter&#xff09;已成為公眾表達情緒、討論熱點事件的主要平臺。通過分析社交媒體數據&#xff0c;可以構建公眾情緒指數&#xff0c;并進一步研究其與股市波動、政策發布等重大事件的關聯性。本文將介紹如…

OpenLayers數據源集成 -- 章節七:高德地圖集成詳解

前言在前面的文章中&#xff0c;我們學習了OpenLayers的瓦片調試&#xff08;VectorTileDebug&#xff09;技術。本文將深入探討OpenLayers中高德地圖的集成方法&#xff0c;這是WebGIS開發中接入商業地圖服務的重要技術。高德地圖作為國內領先的地圖服務提供商&#xff0c;提供…

海外代理IP平臺Top3評測:LoongProxy、神龍動態IP、IPIPGO哪家更適合你?

在當今互聯網環境中&#xff0c;代理IP服務已成為許多企業和個人用戶的剛需。無論是數據采集、市場調研還是賬號管理&#xff0c;優質的代理IP都能大幅提升工作效率。本文將針對LoongProxy、神龍海外動態IP和IPIPGO這三家主流代理IP服務商進行橫向評測&#xff0c;幫助你根據自…

對瀏覽器事件機制的理解

瀏覽器事件是什么&#xff1a; 事件是用戶操作網頁時發生的交互動作&#xff0c;比如 click/move&#xff0c; 事件除了用戶觸發的動作外&#xff0c;還可以是文檔加載&#xff0c;窗口滾動和大小調整。事件被封裝成一個 event 對象&#xff0c;包含了該事件發生時的所有相關信…

XCVP1902-2MSEVSVA6865 AMD 賽靈思 XilinxVersal Premium FPGA

XCVP1902-2MSEVSVA6865 是 AMD 賽靈思&#xff08;Xilinx&#xff09;Versal Premium FPGA 系列中的高端自適應系統級芯片&#xff08;Adaptive SoC&#xff09;變體&#xff0c;面向需要極高邏輯密度、海量 I/O 與超高速收發能力的數據中心互聯、原型驗證與高性能網絡加速等應…

kotlin - 2個Fragment實現左右顯示,左邊列表,右邊詳情,平板橫、豎屏切換(一)

kotlin - 2個Fragment實現左右顯示&#xff0c;左邊列表&#xff0c;右邊詳情&#xff0c;平板橫、豎屏切換(要使用平板測試)平板橫屏&#xff1a;左右fragment實現分屏效果&#xff0c;平板豎屏&#xff1a;只顯示左邊的fragment&#xff0c;點擊才顯示右邊fragment屏幕旋轉&a…

推薦系統中的AB測試:從設計到分析全流程

推薦系統中的AB測試:從設計到分析全流程 關鍵詞:推薦系統、AB測試、實驗設計、數據分析、效果評估、統計顯著性、用戶體驗 摘要:本文將深入探討推薦系統中AB測試的全流程,從實驗設計到結果分析。我們將用通俗易懂的方式解釋AB測試的核心概念,展示如何科學地評估推薦算法改…

【go語言 | 第1篇】Go環境安裝+go語言特性

文章目錄go開發環境1. 下載安裝包2. 配置環境變量3. GOPROXYgo語言特性1. go的優勢2. go適合做什么3. go缺點編寫一個go程序注&#xff1a;在VSCode中補全go代碼go開發環境 我這里是windows操作系統的環境安裝&#xff0c;其他系統可以查看菜鳥教程&#xff1a;Go 語言環境安裝…

【Pywinauto庫】0. Pywinauto Windows GUI 自動化指南

概述 Pywinauto 是一個用于自動化 Windows GUI 應用程序的 Python 庫&#xff0c;適用于自動化測試、數據錄入和其他重復性桌面操作。 快速參考表方面方法/屬性示例說明安裝pip install pywinauto安裝庫后端選擇Application(backend"uia") 或 Application(backend&qu…

CStringArray 和 CStringList

CStringArray 和 CStringList 都是 MFC 中用于管理字符串集合的類&#xff0c;但它們的內部數據結構和適用場景有顯著差異&#xff0c;選擇時需根據具體操作需求決定。以下從核心區別、功能對比和適用場景三個方面詳細說明&#xff1a;一、核心區別&#xff1a;數據結構決定特性…

2025版基于springboot的企業考勤管理系統

博主介紹&#xff1a;java高級開發&#xff0c;從事互聯網行業六年&#xff0c;熟悉各種主流語言&#xff0c;精通java、python、php、爬蟲、web開發&#xff0c;已經做了多年的設計程序開發&#xff0c;開發過上千套設計程序&#xff0c;沒有什么華麗的語言&#xff0c;只有實…

設計模式(C++)詳解—單例模式(1)

<摘要> 單例模式是創建型設計模式中最經典且應用最廣泛的設計模式之一&#xff0c;它確保一個類只有一個實例并提供全局訪問點。本文從歷史背景和核心概念出發&#xff0c;詳細闡述了單例模式的產生背景和演進歷程&#xff0c;深入剖析了其在資源管理、狀態一致性和訪問控…

將GitHub遠程倉庫修改為ssh

8 將GitHub遠程倉庫修改為ssh 文章目錄8 將GitHub遠程倉庫修改為ssh1 創建本地的ssh密鑰2 設置GitHub密鑰3 將本地庫鏈接到遠程倉庫很多時候在使用GitHub的遠程鏈接使用的是http的格式&#xff0c;但是這個格式并不好&#xff0c;尤其是在代碼上傳的時候&#xff0c;因此需要采…