中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

門戶網(wǎng)站概念網(wǎng)絡(luò)營銷推廣服務(wù)

門戶網(wǎng)站概念,網(wǎng)絡(luò)營銷推廣服務(wù),做視頻網(wǎng)站付費版,佛山高端外貿(mào)網(wǎng)站建設(shè)文章目錄 1. 后端項目搭建 1.1 環(huán)境準(zhǔn)備1.2 數(shù)據(jù)表準(zhǔn)備1.3 SpringBoot3項目創(chuàng)建1.4 MySql環(huán)境整合,使用druid連接池1.5 整合mybatis-plus 1.5.1 引入mybatis-plus1.5.2 配置代碼生成器1.5.3 配置分頁插件 1.6 整合swagger3(knife4j) 1.6.1 整…
文章目錄
  • 1. 后端項目搭建
    • 1.1 環(huán)境準(zhǔn)備
    • 1.2 數(shù)據(jù)表準(zhǔn)備
    • 1.3 SpringBoot3項目創(chuàng)建
    • 1.4 MySql環(huán)境整合,使用druid連接池
    • 1.5 整合mybatis-plus
      • 1.5.1 引入mybatis-plus
      • 1.5.2 配置代碼生成器
      • 1.5.3 配置分頁插件
    • 1.6 整合swagger3(knife4j)
      • 1.6.1 整合
      • 1.6.2 使用
    • 1.7 數(shù)據(jù)交互處理
      • 1.7.1 響應(yīng)數(shù)據(jù)封裝(公共返回數(shù)據(jù)類)
      • 1.7.2 分頁查詢返回數(shù)據(jù)封裝
    • 1.8 全局異常處理
    • 1.9 整合JWT,生成token
    • 1.10 封裝ThreadLocal 工具類
    • 1.11 MD5封裝
    • 1.12登錄驗證攔截
    • 1.13 登錄和獲取當(dāng)前用戶信息接口處理
  • 2. 前端項目搭建
    • 2.1 環(huán)境準(zhǔn)備
    • 2.2 創(chuàng)建Vue3項目
    • 2.3 項目搭建準(zhǔn)備
    • 2.4 Element Plus 安裝使用
    • 2.5 axios 安裝使用
      • 2.5.1 安裝
      • 2.5.2 配置(創(chuàng)建實例,配置請求、響應(yīng)攔截器)
      • 2.5.3 配置跨域
    • 2.6 Vue Router 安裝使用
    • 2.7 Pinia狀態(tài)管理庫
    • 2.7.1 Pinia持久化插件-persist
    • 2.8 搭建管理頁面基礎(chǔ)框架
      • 2.8.1 在src下創(chuàng)建api目錄,次目錄存放請求http方法的封裝,創(chuàng)建user.js, 里邊寫封裝請求方法
      • 2.8.2 登錄頁面
      • 2.8.3 布局頁面
  • 3.項目代碼

項目使用SpringBoot3+Vue3, 后端使用springboot3, mybatisPlus, druid,knife4j(swagger3),Jwt; 前端 vue3 , element-plus, axios, pinia, vue-router; 項目前后端分離, 可持續(xù)擴展, 代碼放到最后

1. 后端項目搭建

1.1 環(huán)境準(zhǔn)備

- spring-boot3 最低支持jdk17, 所以需要準(zhǔn)備jdk17環(huán)境
- Idea 版本IntelliJ IDEA 2021.2及以后,版本關(guān)系參考[https://blog.csdn.net/m0_62258564/article/details/134527268](https://blog.csdn.net/m0_62258564/article/details/134527268)
- maven 版本參考以上鏈接
- MySql8

1.2 數(shù)據(jù)表準(zhǔn)備

創(chuàng)建數(shù)據(jù)庫 base_manage, 并創(chuàng)建表

CREATE TABLE user(id INT NOT NULL AUTO_INCREMENT COMMENT '主鍵',login_name VARCHAR(255) NOT NULL COMMENT '登錄名(賬號)',password VARCHAR(255) NOT NULL COMMENT '密碼',name varchar(50) NOT NULL COMMENT '姓名',sex char(1) NOT NULL COMMENT '性別',phone VARCHAR(20) COMMENT '聯(lián)系電話',PRIMARY KEY(id))COMMENT '用戶信息表';

用戶表只是便于后續(xù)過程搭建操作,可根據(jù)需求修改

1.3 SpringBoot3項目創(chuàng)建

在這里插入圖片描述
springboot版本可根據(jù)需求選擇,這里選則默認的3.2.4
在這里插入圖片描述
耐心等待項目構(gòu)建完成, 構(gòu)建完成pom文件如下,請注意,mysql驅(qū)動包<groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId>較之前版本有所改變

<?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.4</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.buzhisuoyun</groupId><artifactId>base_manage</artifactId><version>0.0.1-SNAPSHOT</version><name>base_manage</name><description>base_manage</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

1.4 MySql環(huán)境整合,使用druid連接池

添加 jdbc依賴,防止項目啟動時找不到Bean報錯

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

添加druid依賴

<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-3-starter -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.20</version>
</dependency>

項目使用yml格式配置文件,修改resources下application.properties
為application.yml, 并刪除文件內(nèi)容

配置項目端口號
server:port: 8099

配置數(shù)據(jù)源和druid 連接池

spring:# 數(shù)據(jù)源datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/base_manage?serverTimezone=UTCusername: rootpassword: root

啟動項目, 查看日志,端口和druid 初始化, 整合成功
在這里插入圖片描述

1.5 整合mybatis-plus

1.5.1 引入mybatis-plus

官網(wǎng)地址: https://baomidou.com/
1、添加依賴

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-spring-boot3-starter -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version>
</dependency>

2、配置

# mybatis-plus
mybatis-plus:configuration:# sql日志, 開發(fā)調(diào)試時開啟log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:id-type: auto

啟動項目,出現(xiàn)mybatis-plus日志
在這里插入圖片描述

1.5.2 配置代碼生成器

1.引入相關(guān)依賴

<!-- mybatis-plus 代碼生成器-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.5</version>
</dependency><!-- mybatis-plus代碼生成器模板引擎 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>
  1. 新建utis包,并在下邊創(chuàng)建MybatisPlusGenerator.java代碼生成器配置類
    在這里插入圖片描述

    package com.buzhisuoyun.base_manage.utils;

    import com.baomidou.mybatisplus.generator.FastAutoGenerator;
    import com.baomidou.mybatisplus.generator.config.OutputFile;
    import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
    import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

    import java.io.File;
    import java.sql.Types;
    import java.util.Collections;

    public class MybatisPlusGenerator {
    static final String url = “jdbc:mysql://127.0.0.1:3306/base_manage?serverTimezone=UTC”; // 數(shù)據(jù)庫地址
    static final String username = “root”; // 數(shù)據(jù)庫用戶名
    static final String password = “root”; // 數(shù)據(jù)庫密碼
    static final String authorName = “buzhisuoyun”; // 作者名
    static final String parentPackageNameResource = “com/buzhisuoyun/base_manage”; // mapper.xml路徑
    static final String parentPackageNameJava = “com.buzhisuoyun.base_manage”; // java 文件父包名
    // 要生成代碼對應(yīng)的數(shù)據(jù)表名
    static final String tableName = “user”;

    public static void main(String[] args) {FastAutoGenerator.create(url, username, password)// 1.全局配置.globalConfig(builder -> {builder.author(authorName)                // 設(shè)置作者.enableSpringdoc()               // 開啟 swagger 模式// 獲取當(dāng)前工程路徑并定位到項目java目錄下.outputDir(System.getProperty("user.dir") + "/src/main/java");            // 指定輸出目錄})// 2.數(shù)據(jù)源配置.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {int typeCode = metaInfo.getJdbcType().TYPE_CODE;if (typeCode == Types.SMALLINT) {// 自定義類型轉(zhuǎn)換return DbColumnType.INTEGER;}return typeRegistry.getColumnType(metaInfo);}))// 3.包名策略配置.packageConfig(builder -> {builder.parent(parentPackageNameJava) // 設(shè)置父包名.entity("entity").mapper("mapper").service("service").serviceImpl("service.impl").controller("controller")//.moduleName("system") // 設(shè)置父包模塊名.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/" + parentPackageNameResource + "/mapper")); // 設(shè)置mapperXml生成路徑})// 策略配置.strategyConfig(builder -> {builder.addInclude(tableName) // 設(shè)置需要生成的表名// 覆蓋已生成文件.entityBuilder().enableFileOverride().mapperBuilder().enableFileOverride().serviceBuilder().enableFileOverride().formatServiceFileName("%sService");//.addTablePrefix("t_", "c_"); // 設(shè)置過濾表前綴})// 配置模板.templateConfig(builder -> {//builder.controller("");         // 不生成controller}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默認的是Velocity引擎模板.execute();
    }
    

    }

  • 修改數(shù)據(jù)庫相關(guān)信息
  • 修改authorName
  • 修改parentPackageNameResource, parentPackageNameJava
  • 修改tableName, 要生成代碼的數(shù)據(jù)表名稱,多個表使用,分割
  • .enableSpringdoc() 可以選擇,生成swagger3文檔注釋
    修改完成后運行main函數(shù),生成相應(yīng)代碼,mapper.xml在resource下與java同路徑下
    在這里插入圖片描述
    實體類import io.swagger.v3.oas.annotations.media.Schema;報錯,是因為swagger3依賴還未導(dǎo)入,下邊整合swagger3后就不會報錯了
1.5.3 配置分頁插件

新建config包,并在下邊創(chuàng)建配置類MybatisPlusConfig.java
在這里插入圖片描述

package com.buzhisuoyun.base_manage.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@MapperScan("com/buzhisuoyun/base_manage/mapper")
public class MybatisPlusConfig {/*** 添加分頁插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多個插件,切記分頁最后添加//interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多數(shù)據(jù)源可以不配具體類型 否則都建議配上具體的DbTypereturn interceptor;}
}

@MapperScan(“com/buzhisuoyun/base_manage/mapper”) 掃描mapper路勁,也可在啟動類配置

1.6 整合swagger3(knife4j)

1.6.1 整合

引入依賴

<!-- API 文檔 knife4j -->
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter -->
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.5.0</version>
</dependency>

配置:

# springdoc-openapi 配置
springdoc:swagger-ui:path: /swagger-ui.htmltags-sorter: alphaoperations-sorter: alphaapi-docs:path: /v3/api-docsgroup-configs:- group: 'default'paths-to-match: '/**'packages-to-scan: com.buzhisuoyun.base_manage# knife4j 配置
knife4j:# 是否啟用增強enable: true# 開啟生產(chǎn)環(huán)境屏蔽production: false# 是否認證登錄basic:# basic是否開啟,默認為falseenable: trueusername: knife4jpassword: knife4jsetting:language: zh_cnenable-version: trueenable-swagger-models: true

在config下創(chuàng)建配置類

package com.buzhisuoyun.base_manage.config;import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class Knife4jConfig {@Beanpublic OpenAPI springShopOpenApi() {return new OpenAPI()// 接口文檔標(biāo)題.info(new Info().title("接口文檔").description("api接口文檔").version("1.0版本"));}
}

配置完后,啟動項目,訪問路徑http://localhost:9999/doc.html,用戶名密碼就是配置文件中的,結(jié)果如圖
在這里插入圖片描述

1.6.2 使用

實體類使用@Schema 注解,在mybatis-plus選擇的話會自動生成
在這里插入圖片描述
Conntroller 層使用:

@Tag(name = "用戶接口")
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;
/*** 用戶列表分頁* @param pageSize 每頁顯示的條數(shù)* @param currentPage  要查詢的頁* @param name  用戶姓名* @return  Result<PageResultBean<List<User>>>*/@GetMapping("/pageList")@Operation(summary = "用戶列表分頁查詢")@Parameters({@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token"),@Parameter(name = "pageSize", required = true, description = "每頁顯示的條數(shù)"),@Parameter(name = "currentPage", required = true, description = "要查詢的頁"),@Parameter(name = "name", description = "用戶姓名", required = false)})public Result<PageResultBean<User>> pageList(@RequestParam int pageSize, @RequestParam int currentPage, @Nullable @RequestParam String name) {IPage<User> page = userService.pageList(pageSize, currentPage, name);if (page == null) {return Result.error("查詢失敗");}//PageResultBean<User> pageResultBean = new PageResultBean<User>(page.getTotal(), page.getRecords());return Result.success(PageResultBean.getInstance(page.getTotal(), page.getRecords()));}
}

在這里插入圖片描述

1.7 數(shù)據(jù)交互處理

1.7.1 響應(yīng)數(shù)據(jù)封裝(公共返回數(shù)據(jù)類)

封裝返回數(shù)據(jù)封裝類,放到common包下:
在這里插入圖片描述

package com.buzhisuoyun.base_manage.common;import io.swagger.v3.oas.annotations.media.Schema;public class Result<T> {@Schema(description = "業(yè)務(wù)狀態(tài)碼 0:成功  1: 失敗")private int code;        // 業(yè)務(wù)狀態(tài)碼 0:成功  1: 失敗@Schema(description = "提示信息")private String message;  // 提示信息@Schema(description = "返回數(shù)據(jù)")private T data;          // 響應(yīng)數(shù)據(jù)public Result(int code, String message, T data) {this.code = code;this.message = message;this.data = data;}// 操作成功返回響應(yīng)結(jié)果(帶響應(yīng)數(shù)據(jù))public static <E> Result<E> success(E data) {return new Result<>(0, "操作成功", data);}public static <E> Result<E> success() {return new Result<>(0, "操作成功", null);}public static <E> Result<E> error(String message) {return new Result<>(1, message, null);}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}@Overridepublic String toString() {return "Result{" +"code=" + code +", message='" + message + ''' +", data=" + data +'}';}
}
1.7.2 分頁查詢返回數(shù)據(jù)封裝

封裝分頁查詢數(shù)據(jù),放到common包下:
在這里插入圖片描述

package com.buzhisuoyun.base_manage.common;import io.swagger.v3.oas.annotations.media.Schema;import java.util.List;public class PageResultBean<T> {@Schema(description = "數(shù)據(jù)總條數(shù)")private Long total;@Schema(description = "當(dāng)前頁數(shù)據(jù)集合")private List<T> items;public PageResultBean() {}public PageResultBean(Long total, List<T> items) {this.total = total;this.items = items;}public static <E> PageResultBean<E> getInstance(Long total, List<E> items) {return new PageResultBean<>(total, items);}public Long getTotal() {return total;}public void setTotal(Long total) {this.total = total;}public List<T> getItems() {return items;}public void setItems(List<T> items) {this.items = items;}
}

1.8 全局異常處理

創(chuàng)建xception包,在包下放全局異常處理類GlobalExceptionHandler.java,類名放置 位置可以隨意,為便于分類整理, 同類包放到一個包下
xception包
使用springboot @RestControllerAdvice 注解配置

package com.buzhisuoyun.base_manage.exception;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;// 全局異常處理
@RestControllerAdvice
public class GlobalExceptionHandler {private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);@ExceptionHandler(Exception.class)public Result<String> handlerException(Exception e) {logger.warn(e.getMessage());return Result.error(StringUtils.hasLength(e.getMessage()) ? e.getMessage() : "操作失敗");}
}

1.9 整合JWT,生成token

引入依賴

 <!-- jwt --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency>

封裝工具類, 放到utils包下:

package com.buzhisuoyun.base_manage.utils;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;import java.util.Date;
import java.util.Map;public class JwtUtil {private static final String KEY = "buzhisuoyun";   // 密鑰// 接收數(shù)據(jù),生成token并返回public static String getToken(Map<String, Object> claims) {return JWT.create().withClaim("claims", claims).withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60))       // 失效時間1小時.sign(Algorithm.HMAC256(KEY));}// 接收token,驗證并返回數(shù)據(jù)public static Map<String, Object> parseToken(String token) {return JWT.require(Algorithm.HMAC256(KEY)).build().verify(token).getClaim("claims").asMap();}
}

1.10 封裝ThreadLocal 工具類

因項目使用前后端分離,使用ThreadLocal 線程變量存儲用戶登錄信息,替代session

package com.buzhisuoyun.base_manage.utils;public class ThreadLocalUtil {// 提供ThreadLocal 對象private static final ThreadLocal<Object> THREAD_LOCAL = new ThreadLocal<>();// 獲取存儲值public static <T> T get() {return (T) THREAD_LOCAL.get();}// 存儲值public static void set(Object value) {THREAD_LOCAL.set(value);}// 清除THREAD_LOCAL 防止內(nèi)存泄漏public static void remove() {THREAD_LOCAL.remove();}
}

1.11 MD5封裝

package com.buzhisuoyun.base_manage.utils;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class Md5Util {/*** 默認的密碼字符串組合,用來將字節(jié)轉(zhuǎn)換成 16 進制表示的字符,apache校驗下載的文件的正確性用的就是默認的這個組合*/protected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};protected static MessageDigest messagedigest = null;static {try {messagedigest = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException nsaex) {System.err.println(Md5Util.class.getName() + "初始化失敗,MessageDigest不支持MD5Util。");nsaex.printStackTrace();}}/*** 生成字符串的md5校驗值** @param s* @return*/public static String getMD5String(String s) {return getMD5String(s.getBytes());}/*** 判斷字符串的md5校驗碼是否與一個已知的md5碼相匹配** @param password  要校驗的字符串* @param md5PwdStr 已知的md5校驗碼* @return*/public static boolean checkPassword(String password, String md5PwdStr) {String s = getMD5String(password);return s.equals(md5PwdStr);}public static String getMD5String(byte[] bytes) {messagedigest.update(bytes);return bufferToHex(messagedigest.digest());}private static String bufferToHex(byte bytes[]) {return bufferToHex(bytes, 0, bytes.length);}private static String bufferToHex(byte bytes[], int m, int n) {StringBuffer stringbuffer = new StringBuffer(2 * n);int k = m + n;for (int l = m; l < k; l++) {appendHexPair(bytes[l], stringbuffer);}return stringbuffer.toString();}private static void appendHexPair(byte bt, StringBuffer stringbuffer) {char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字節(jié)中高 4 位的數(shù)字轉(zhuǎn)換, >>>// 為邏輯右移,將符號位一起右移,此處未發(fā)現(xiàn)兩種符號有何不同char c1 = hexDigits[bt & 0xf];// 取字節(jié)中低 4 位的數(shù)字轉(zhuǎn)換stringbuffer.append(c0);stringbuffer.append(c1);}// 測試public static void main(String[] args) {System.out.println(Md5Util.getMD5String("admin"));}}

1.12登錄驗證攔截

1、創(chuàng)建包interceptors,在包下配置登錄攔截器

package com.buzhisuoyun.base_manage.interceptors;import com.buzhisuoyun.base_manage.utils.JwtUtil;
import com.buzhisuoyun.base_manage.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 獲取tokenString token = request.getHeader("Authorization");// 驗證tokentry {Map<String, Object> claims = JwtUtil.parseToken(token);// 存儲業(yè)務(wù)信息到線程變量ThreadLocalUtil.set(claims);// 放行攔截return true;} catch (Exception e) {// 登錄信息異?;蛭吹卿?#xff0c;http響應(yīng)狀態(tài)碼為401response.setStatus(401);// 攔截請求return false;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清除ThreadLocal業(yè)務(wù)數(shù)據(jù)ThreadLocalUtil.remove();}
}

2、在config包下創(chuàng)建WebConfig配置類,注冊登錄攔截器

package com.buzhisuoyun.base_manage.config;import com.buzhisuoyun.base_manage.interceptors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.ArrayList;
import java.util.List;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 配置放行資源// 無需攔截的接口集合List<String> ignorePath = new ArrayList<>();// knife4j(swagger)ignorePath.add("/swagger-resources/**");ignorePath.add("/doc.html");ignorePath.add("/v3/**");ignorePath.add("/webjars/**");ignorePath.add("/static/**");ignorePath.add("/templates/**");ignorePath.add("/error");// 登錄頁面ignorePath.add("/user/login");registry.addInterceptor(loginInterceptor).excludePathPatterns(ignorePath);}
}

1.13 登錄和獲取當(dāng)前用戶信息接口處理

	@PostMapping("/login")@Operation(summary = "用戶登錄")@Parameters({@Parameter(name = "loginName", description = "登錄名", required = true, schema = @Schema(type = "sting")),@Parameter(name = "password", description = "密碼", required = true, schema = @Schema(type = "sting"))})public Result<String> login(@RequestBody User user) {if (user == null || "".equals(user.getLoginName()) || user.getLoginName() == null || "".equals(user.getPassword()) || user.getPassword() == null) {return Result.error("用戶名密碼不能為空");}// 檢驗用戶名是否存在User eruser = userService.findByLoginName(user.getLoginName());if (eruser == null) {return Result.error("用戶名不存在");}// 檢驗用戶密碼是否正確if (Md5Util.getMD5String(user.getPassword()).equals(eruser.getPassword())) {Map<String, Object> claims = new HashMap<>();claims.put("id", eruser.getId());claims.put("name", eruser.getName());claims.put("loginName", eruser.getLoginName());String token = JwtUtil.getToken(claims);return Result.success(token);}return Result.error("密碼錯誤");}/*** 獲取當(dāng)前登錄用戶信息* @return  User*/@GetMapping("/currentUser")@Operation(summary = "獲取當(dāng)前登錄用戶信息")@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true, description = "token")public Result<User> getCurrentUser() {Map<String, Object> userSession = ThreadLocalUtil.get();int id = (int) userSession.get("id");User user = userService.getUserById(id);if (user != null) {return Result.success(user);}return Result.error("用戶狀態(tài)異常");}

因為是做簡單后端項目搭建,所以token存在一定問題,如在修改用戶密碼后必須強制重新登錄或采用redis緩存token,同時驗證瀏覽器token和用戶token,或采用第三方認證中心解決等
項目工程結(jié)構(gòu)如圖
在這里插入圖片描述

2. 前端項目搭建

2.1 環(huán)境準(zhǔn)備

- node安裝
- vscode安裝

2.2 創(chuàng)建Vue3項目

在將要存放vue3項目的路徑打開cmd, 使用以下命令創(chuàng)建項目

npm init vue@latest

在這里插入圖片描述
此時項目創(chuàng)建完成,vscode打開項目目錄,在資源目錄空白右鍵,打開終端
在這里插入圖片描述
執(zhí)行命令 npm install安裝依賴,等待安裝完成后執(zhí)行 npm run dev 運行項目
在這里插入圖片描述
訪問路徑可訪問項目
在這里插入圖片描述
在終端ctrl c 可停止運行項目
項目描述如圖,圖引自黑馬開源教程PPT
在這里插入圖片描述

2.3 項目搭建準(zhǔn)備

說明:項目中使用組合式API
刪掉components下所有文件,刪除App.vue文件不需要的東西,最后如下所示

<script setup></script><template><router-view></router-view>
</template><style scoped></style>

2.4 Element Plus 安裝使用

  • 安裝 npm install element-plus --save

  • 引入:在main.js中引入Element Plus(參照官方文檔)https://element.eleme.cn/#/zh-CN/component/quickstart

    import { createApp } from ‘vue’
    import ElementPlus from ‘element-plus’
    import ‘element-plus/dist/index.css’
    import App from ‘./App.vue’

    const app = createApp(App)
    app.use(ElementPlus)
    app.mount(‘#app’)

  • 使用: 訪問Element官方文檔,復(fù)制組件代碼,修改調(diào)整

2.5 axios 安裝使用

2.5.1 安裝
npm install axios
2.5.2 配置(創(chuàng)建實例,配置請求、響應(yīng)攔截器)

在src目錄下新建 utils, 并在utils 下創(chuàng)建request.js 進行axios配置
在這里插入圖片描述

// 請求配置import axios from "axios";// 定義公共前綴,創(chuàng)建請求實例
// const baseUrl = "http://localhost:8080";
const baseURL = '/api/';
const instance = axios.create({baseURL})import { ElMessage } from "element-plus"
import { useTokenStore } from "@/stores/token.js"
// 配置請求攔截器
instance.interceptors.request.use((config) => {// 請求前回調(diào)// 添加tokenconst tokenStore = useTokenStore()// 判斷有無tokenif (tokenStore.token) {config.headers.Authorization = tokenStore.token}return config},(err) => {// 請求錯誤的回調(diào)Promise.reject(err)}
)import router from "@/router";
// 添加響應(yīng)攔截器
instance.interceptors.response.use(result => {// 判斷業(yè)務(wù)狀態(tài)碼if (result.data.code === 0) {return result.data;}// 操作失敗ElMessage.error(result.data.message ? result.data.message : '服務(wù)異常')// 異步操作的狀態(tài)轉(zhuǎn)換為失敗return Promise.reject(result.data)},err => {// 判斷響應(yīng)狀態(tài)碼, 401為未登錄,提示登錄并跳轉(zhuǎn)到登錄頁面if (err.response.status === 401) {ElMessage.error('請先登錄')router.push('/login')} else {ElMessage.error('服務(wù)異常')}// 異步操作的狀態(tài)轉(zhuǎn)換為失敗return Promise.reject(err)  }
)export default instance
2.5.3 配置跨域

在vite.config.js 中defineConfig配置代理,實現(xiàn)跨域

server: {proxy: {'/api': {   // 獲取路徑中包含了/api的請求target: 'http://localhost:9999',        // 服務(wù)端地址changeOrigin: true, // 修改源rewrite:(path) => path.replace(/^/api/, '')   // api 替換為 ''}}}

在這里插入圖片描述

2.6 Vue Router 安裝使用

  • 安裝 npm install vue-router@4

  • 在src/router/index.js中創(chuàng)建路由器,并導(dǎo)出

    // 導(dǎo)入vue-router
    import {createRouter, createWebHistory} from ‘vue-router’

    // 導(dǎo)入組件
    import LoginVue from ‘@/views/Login.vue’
    import LayoutVue from ‘@/views/Layout.vue’
    import UserList from ‘@/views/user/UserList.vue’
    import EditPassword from ‘@/views/user/EditPassword.vue’
    import DisplayUser from ‘@/views/user/DisplayUser.vue’

    // 定義路由關(guān)系
    const routes = [
    {path: ‘/login’, component: LoginVue},
    {
    path: ‘/’, component: LayoutVue, redirect: ‘’, children: [
    {path: ‘/user/userlist’, name: “/user/userlist”, component: UserList, meta: {
    title: “用戶列表”
    },},
    {path: ‘/user/editpassword’, name: “/user/editpassword”, component: EditPassword, meta: {
    title: “修改密碼”
    }
    },
    {path: ‘/user/displayuser’, name: “/user/displayuser”, component: DisplayUser, meta: {
    title: “個人信息”
    }}
    ]
    }
    ]

    // 創(chuàng)建路由器
    const router = createRouter({
    history: createWebHistory(),
    routes: routes
    })

    export default router

  • 在vue應(yīng)用實例中使用vue-router

    在main.js 中

    import router from ‘@/router’
    app.use(router)

  • 聲明router-view標(biāo)簽,展示組件內(nèi)容

    在app.vue 中

2.7 Pinia狀態(tài)管理庫

  • 安裝 npm install pinia

2.7.1 Pinia持久化插件-persist

  • 安裝persist npm install pinia-persistedstate-plugin

  • 在pinia中使用persist

    main.js

    import {createPersistedState} from’pinia-persistedstate-plugin’ const persist = createPersistedState()
    pinia.use(persist)

  • 定義狀態(tài)Store時指定持久化配置參數(shù)
    在這里插入圖片描述

  • 在src/stores/下定義token.js和userInfo.js 用來存儲token和用戶相關(guān)信息

    token.js

    // 定義 store
    import { defineStore } from “pinia”
    import {ref} from ‘vue’
    /*
    第一個參數(shù):名字,唯一性
    第二個參數(shù):函數(shù),函數(shù)的內(nèi)部可以定義狀態(tài)的所有內(nèi)容

    返回值: 函數(shù)
    

    */
    export const useTokenStore = defineStore(‘token’, () => {
    // 響應(yīng)式變量
    const token = ref(‘’)

    // 修改token值函數(shù)
    const setToken = (newToken) => {token.value = newToken
    }// 移除token值函數(shù)
    const removeToke = () => {token.value = ''
    }return {token, setToken, removeToke
    }
    

    },
    {
    persist: true // 持久化存儲
    }
    )

    userInfo.js

    import { defineStore } from “pinia”
    import {ref} from ‘vue’

    const useUserInfoStore = defineStore(‘userInfo’, () => {
    const info = ref({})

    const setInfo = (newInfo) => {info.value = newInfo
    }const removeInfo = () => {info.value = {}
    }return {info, setInfo, removeInfo}
    

    },
    {
    persist: true
    }
    )

    export default useUserInfoStore;

  • 在組件中使用store 示例

    import {userLoginService} from ‘@/api/user.js’
    import {useTokenStore} from ‘@/stores/token.js’
    import {useRouter} from ‘vue-router’
    const router = useRouter()
    const tokenStore = useTokenStore();
    const login = async ()=>{
    // 校驗表單
    if (!ruleFormRef.value) return
    console.log(“校驗”)
    await ruleFormRef.value.validate(async (valid) => {
    if (valid) {
    console.log(“校驗成功”)
    // 調(diào)用接口,完成登錄
    let result = await userLoginService(registerData.value);
    /* if(result.code===0){
    alert(result.msg? result.msg : ‘登錄成功’)
    }else{
    alert(‘登錄失敗’)
    } */
    //alert(result.msg? result.msg : ‘登錄成功’)
    ElMessage.success(result.msg ? result.msg : ‘登錄成功’)
    //token存儲到pinia中
    tokenStore.setToken(result.data)
    //跳轉(zhuǎn)到首頁 路由完成跳轉(zhuǎn)
    router.push(‘/’)
    } else {
    console.log(“校驗失敗”)
    }
    })
    }

    // 配置請求攔截器
    instance.interceptors.request.use(
    (config) => {
    // 請求前回調(diào)
    // 添加token
    const tokenStore = useTokenStore()
    // 判斷有無token
    if (tokenStore.token) {
    config.headers.Authorization = tokenStore.token
    }
    return config
    },
    (err) => {
    // 請求錯誤的回調(diào)
    Promise.reject(err)
    }
    )

2.8 搭建管理頁面基礎(chǔ)框架

2.8.1 在src下創(chuàng)建api目錄,次目錄存放請求http方法的封裝,創(chuàng)建user.js, 里邊寫封裝請求方法
import request from "@/utils/request.js"// 登錄接口調(diào)用函數(shù)
export const userLoginService = (loginData) => {return request.post('/user/login', loginData)
}// 獲取當(dāng)前登錄用戶信息
export const currentUserService = () => {return request.get('/user/currentUser')
}// 獲取所有用戶信息
export const allUserService = () => {return request.get('/user/userList')
}// 分頁查詢
export const pageListService = (pageParam) => {return request.get('/user/pageList', {params: pageParam})
}// 新增用戶
export const addUserService = (addData) => {return request.post('/user/add', addData)
}// 根據(jù)id獲取用戶信息
export const getUserById = (id) => {return request.get('/user/getuserById', {params: id})
}// 修改用戶信息
export const updateUserService = (data) => {return request.put('/user/update', data)
}// 刪除用戶
export const deleteByIdService = (id) => {console.log("deleteRequestid:", id)return request.delete('/user/delete/' + id)
}
2.8.2 登錄頁面
  • 安裝 npm install sass -D

在src下創(chuàng)建views目錄,用于存放vue頁面組件
在這里插入圖片描述
登錄 Login.vue

<script setup>
import { User, Lock } from '@element-plus/icons-vue'
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
//定義數(shù)據(jù)模型
const registerData = ref({loginName: 'admin',password:'admin',rePassword: ''
})// 定義表單組件的引用
const ruleFormRef = ref(null)//定義表單校驗規(guī)則
const rules = ref({loginName: [{ required: true, message: '請輸入用戶名', trigger: 'blur' },{ min: 5, max: 16, message: '長度為5~16位非空字符', trigger: 'blur' }],password: [{ required: true, message: '請輸入密碼', trigger: 'blur' },{ min: 5, max: 16, 2: '長度為5~16位非空字符', trigger: 'blur' }]
})//綁定數(shù)據(jù),復(fù)用注冊表單的數(shù)據(jù)模型
//表單數(shù)據(jù)校驗
//登錄函數(shù)
import {userLoginService} from '@/api/user.js'
import {useTokenStore} from '@/stores/token.js'
import {useRouter} from 'vue-router'
const router = useRouter()
const tokenStore = useTokenStore();
const login = async ()=>{// 校驗表單if (!ruleFormRef.value) returnconsole.log("校驗")await ruleFormRef.value.validate(async (valid) => {if (valid) {console.log("校驗成功")// 調(diào)用接口,完成登錄let result = await userLoginService(registerData.value);/* if(result.code===0){alert(result.msg? result.msg : '登錄成功')}else{alert('登錄失敗')} *///alert(result.msg? result.msg : '登錄成功')ElMessage.success(result.msg ? result.msg : '登錄成功')//token存儲到pinia中tokenStore.setToken(result.data)//跳轉(zhuǎn)到首頁 路由完成跳轉(zhuǎn)router.push('/')} else {console.log("校驗失敗")}})
}//定義函數(shù),清空數(shù)據(jù)模型的數(shù)據(jù)
const clearRegisterData = ()=>{registerData.value={loginName: '',password:'',rePassword:''}
}
</script><template><el-row class="login-page"><el-col :span="12" class="bg"></el-col><el-col :span="6" :offset="3" class="form"><!-- 登錄表單 --><el-form ref="ruleFormRef" :model=registerData size="large" autocomplete="off" :rules="rules"><el-form-item><h1>登錄</h1></el-form-item><el-form-item prop="loginName"><el-input :prefix-icon="User" placeholder="請輸入用戶名" v-model="registerData.loginName"></el-input></el-form-item><el-form-item prop="password"><el-input name="password" :prefix-icon="Lock" type="password" placeholder="請輸入密碼" v-model="registerData.password"></el-input></el-form-item><el-form-item class="flex"><div class="flex"><el-checkbox>記住我</el-checkbox><!-- <el-link type="primary" :underline="false">忘記密碼?</el-link> --></div></el-form-item><!-- 登錄按鈕 --><el-form-item><el-button class="button" type="primary" auto-insert-space @click="login">登錄</el-button></el-form-item></el-form></el-col></el-row>
</template><style lang="scss" scoped>
/* 樣式 */
.login-page {height: 100vh;background-color: #fff;.bg {background: url('@/assets/login_bg.jpg') no-repeat center / cover;border-radius: 0 20px 20px 0;}.form {display: flex;flex-direction: column;justify-content: center;user-select: none;.title {margin: 0 auto;}.button {width: 100%;}.flex {width: 100%;display: flex;justify-content: space-between;}}
}
</style>
2.8.3 布局頁面
  • Layout .vue

項目結(jié)構(gòu):
在這里插入圖片描述

3.項目代碼

https://download.csdn.net/download/qq_51355375/89085020

此項目不包含動態(tài)路由,菜單權(quán)限部分, 如需要可參考 : https://blog.csdn.net/qq_51355375/article/details/139722876

http://www.risenshineclean.com/news/34613.html

相關(guān)文章:

  • 怎樣做類似淘寶網(wǎng)的網(wǎng)站汕頭網(wǎng)站優(yōu)化
  • 用html編寫淘寶網(wǎng)站怎么做seo友情鏈接
  • 漢子由來 外國人做的網(wǎng)站網(wǎng)站建設(shè)公司服務(wù)
  • 南和網(wǎng)站建設(shè)公司網(wǎng)絡(luò)推廣費用計入什么科目
  • 程序開源網(wǎng)站關(guān)鍵詞列表
  • 新手學(xué)易語言多久可以做網(wǎng)站中國優(yōu)秀網(wǎng)頁設(shè)計案例
  • 本地旅游網(wǎng)站模版網(wǎng)絡(luò)營銷網(wǎng)站推廣方法
  • 做公司網(wǎng)站多少錢站長工具在線查詢
  • 網(wǎng)站背景色最新天氣預(yù)報最新消息
  • 如何做網(wǎng)站刷題西安網(wǎng)站建設(shè)
  • 做企業(yè)網(wǎng)站的架構(gòu)圖廣州王牌seo
  • 公司做網(wǎng)站流程關(guān)鍵詞挖掘工具愛網(wǎng)
  • 菲律賓有做網(wǎng)站的嗎seo優(yōu)化是做什么的
  • 安卓手機 做網(wǎng)站湘潭seo優(yōu)化
  • 有哪些做留學(xué)資訊的網(wǎng)站搜全網(wǎng)的瀏覽器
  • 豬八戒做網(wǎng)站怎么樣打開百度一下的網(wǎng)址
  • 服務(wù)器安全設(shè)置河南網(wǎng)站seo費用
  • 網(wǎng)站域名不合法新聞最新消息
  • 建設(shè)單位企業(yè)鎖登陸網(wǎng)站seo沈陽
  • 做中英文游戲門戶網(wǎng)站關(guān)鍵詞怎么弄百度一下的網(wǎng)址
  • 500人在線網(wǎng)站建設(shè)配置國家市場監(jiān)管總局官網(wǎng)
  • 武漢武昌做網(wǎng)站推廣百度推廣需要什么條件
  • 長沙做網(wǎng)站好的公司有哪些跨境電商平臺哪個最好最可靠
  • 做第三方的qq互聯(lián)接口時_回調(diào)到自己的網(wǎng)站時要延時很久是什么原因品牌推廣平臺
  • 網(wǎng)站域名301是什么意思什么是長尾關(guān)鍵詞舉例
  • 老的網(wǎng)站為什么要改版新網(wǎng)站東莞seo優(yōu)化排名
  • 免費做三級網(wǎng)站正規(guī)網(wǎng)站優(yōu)化哪個公司好
  • 免費cms建站系統(tǒng)有哪些小說關(guān)鍵詞自動生成器
  • 網(wǎng)站更換服務(wù)器影響今日頭條官網(wǎng)登錄入口
  • 深圳交易服務(wù)中心官網(wǎng)學(xué)校seo推廣培訓(xùn)班