畢業設計學習鋒迷商城的的筆記(手寫後臺商品管理,分類管理,用戶,地址管理系統)

来源:https://www.cnblogs.com/smallcutemonkey/archive/2022/11/03/16855589.html
-Advertisement-
Play Games

前言 所謂熱部署,簡單來說,就是代碼修改後不需重啟項目就可自動載入出新的內容。 ==註意:熱部署在 debug 調試模式下才生效!== IDEA 配置 在 IDE(IDEA)中開啟相關項目自動構建選項 開啟編譯器設置中修改後自動編譯的選項(下圖是 IDEA 2021版本,其他版本可能在其他位置) S ...


@

目錄

自己添加的後端管理頁面

視頻演示效果

[video(video-CZIQF8d5-1652505187791)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=641370075)(image-https://img-blog.csdnimg.cn/img_convert/6fc48aff3f62b207e20ca7badb21395a.png)(title-畢業設計SpringBoot+Vue+ElementUI商城系統實現(有後臺))]

論文地址

商城論文地址

後臺代碼視頻實現講解思路

[video(video-zgz2Gybc-1667056389114)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=816242633)(image-https://img-blog.csdnimg.cn/img_convert/69a030b2c0a14349f093065947c707ae.jpeg)(title-畢業設計鋒迷商城手敲後臺管理,實現邏輯講解,代碼講解)]

b站地址

1. 商品管理

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述

2.商品分類管理

在這裡插入圖片描述

3.商品地址管理

在這裡插入圖片描述

4.用戶中心管理

在這裡插入圖片描述

4. 用戶許可權管理

5.訂單管理

5.1

6.商品品牌管理

鋒迷商城項目

使用Maven聚合項目進行創建(一個maven的父項目多個maven的子項目),

可以在父項目pom.xml文件中加上:

<package>pom<package>

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-aKHt478Q-1633568521449)(C:\Users\CourageAndLove\AppData\Roaming\Typora\typora-user-images\image-20210812151308862.png)]

1.通過Maven聚合工程搭建項目:

1. 創建一個Maven的父項目,然後修改它的pom.xml文件,可以刪除src等一些沒有用的目錄

<packaging>pom<packaing>

2.在父項目下麵創建多個module,包括(common,beans,mapper,service,api)把它們全部打包成jar包

pom.xml加上

<packaging>jar</packaging>

3.由於mapper層需要調用beans層(pojo),需要在pom.xml文件中,然後可以在mapper中加入相關的依賴。

   <dependencies>

<!--        mapper需要用到Beans所以需要加上beans的依賴-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>beans</artifactId>
            <version>2.0.1</version>
        </dependency>
    </dependencies>

4.創建service需要調用mapper,和common,需要在pom.xml文件中加上

 <dependency>
            <groupId>org.example</groupId>
            <artifactId>mapper</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>common</artifactId>
            <version>2.0.1</version>
        </dependency>

5.api層需要接收前端的請求所以需要我們創建一個SpringBoot工程,你可以創建一個Maven工程,然後加入相關的依賴

6.api子工程,對外提供介面

總的說父項目的所以依賴可以被子項目引用,子項目也可以單獨的添加所需的依賴

鋒迷商城資料庫設計

2.軟體開發步驟

  • 提出問題

  • 可行性分析(技術(一般可以相關人員實現),成本,法律法規)

  • 概要設計

    • 系統設計(技術選型,架構模式)
    • 資料庫設計
    • UI設計
    • 業務流程設計
  • 詳細設計

    • 實現步驟(業務流程的實現細節)
  • 編碼

    • 根據設計好的實現步驟進行代碼實現
    • 開發過程使用單元測試
  • 測試

    • 集成測試
    • 功能測試(墨盒)
    • 性能測試(白盒)高併發,壓力測試
  • 交付/部署實施

    3.資料庫設計流程

  • 根據功能分析出資料庫實體(javaBean)

    • 商品,訂單,購物車,用戶,地址...
  • 提取實體屬性

    • spu商品(id,商品名稱,商品圖片,商品描述...)

    • 1 min10 ..... ....

    • sku(skuId, 參數 , 價格 商品id

    • 101 記憶體8G\存儲128G 2999 1

    • 102 記憶體12G\存儲256G 3999 1

    • 地址(姓名,地址,電話.....)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-P8zP9MYA-1633446686624)(C:\Users\CourageAndLove\AppData\Roaming\Typora\typora-user-images\image-20210814172548189.png)]

可以知道價格的依賴於參數的改變而改變,參數依賴於id改變,不滿足資料庫設計表的要求,可以設計兩張表進行實現。

  • 使用資料庫的第三範式進行檢查數據項是否合理
  • 分析實體關係圖:E-R圖 (一對一,一對多)
  • 資料庫建模(三線圖)建模工具(PdMan)
  • 建庫建表-sql

3.數據建模工具PDMan

  • 可視化創建資料庫表(數據表

  • 視圖顯示表之間的關係(關係圖)

  • 導出sql指令(模型---導出DDL腳本

  • 記錄資料庫模型版本管理

  • 可以連接資料庫直接生成表

    Spu和Sku的區別

  • spu(Standard Product Unit):商品信息聚合的最小 單位。通俗講屬性值,特性相同的商品可以稱為一個SPU.

    產品: 榮耀8 小米10

  • sku(Stock Keeping Unit)最小存貨單元,定義為保存最小庫存的控制最小可用單元

    sku 榮耀8 8G/128G 10

    sku 榮耀8 4G/124G 20

    註意一下 :訂單表的設計功能:因為訂單表只要用戶一下訂單,訂單表的相關信息就不可以進行改變 ,所以需要進行地址的的快照和商品信息的快照,這樣就算你臨時改變了價格的信息或者其他的也沒有關係

    購物車的設計:

4.鋒城業務流程設計

在企業開發中,當完成項目的需求分析,功能分析,資料庫分析與設計後,項目組就會按照項目中的功能模塊進行開發任務的分配。

每個人會被分配不同的功能

4.1用戶管理9業務流程分析

單體架構:頁面和控制之間可以進行跳轉,同步請求控制器,流程式控制制由控制器來完成

前後端分離架構:前端和後端開發開發和部署,前端只能通過非同步發送請求,後端只負責接收請求及參數,處理請求,返回結果

前端可以發送如圖所示的請求:需要url,params

5介面介紹

狹義:的理解:就是控制器中可以接受用戶請求的方法

標准定義:API(Application Programming interface)應用程式編程介面,就是軟體系統不同組成部分銜接的約定。

5.1介面規範

作為後端程式員不僅要完成介面程式的開發,還要編寫介面的說明文檔---介面規範

5.2Swagger(自動生成伺服器介面的規範性文檔)

前後端分離規開發,後端需要編寫介面說明文檔,會耗費比較多的時間

swagger是一個用於生成伺服器介面的的規範性文檔,並且能夠對介面進行測試的工具。

  • swagger作用
  • 生成介面規範性文檔
  • 生成介面測試工具

5.2.1引入相關的依賴:

<!--        swagger2介面文檔生成工具-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
<!--        swagger-ui-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>


5.2.2 創建相關的配置類

可以在api這個module中進行相關的controller層的測試,建立一個config包下麵的SwaggerConfig類進行相關的測試,加上@Configuration,@EnableSwagger2註解,然後進行配置相關的信息

package com.qfedu.fmmall.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.w3c.dom.DocumentType;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    /*
    * swagger生成我們的介面文檔:
    * 1.需要配置生成文檔的信息
    * 2.配置生成規則
    *
    * */
    @Bean
    public Docket docket(){

//創建封面信息對象
        ApiInfoBuilder apiInfoBuilder=new ApiInfoBuilder();//指定生成文檔中的封面信息:文檔標題,作者,版本
        apiInfoBuilder.title("《鋒迷商城》後端介面說明")
                .description("此文檔詳細說明瞭鋒迷商城項目後端介面規範")
                .version("v 2.0.1")
                .contact(new Contact("houge","www.houge.com","[email protected]"));


        ApiInfo apiInfo=apiInfoBuilder.build();


        Docket docket=new Docket(DocumentationType.SWAGGER_2) //指定文檔風格
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.qfedu.fmmall.controller"))
//                定義了path之後只會為user開頭的請求進行掃描 .paths(PathSelectors.regex("/user/"))
//                PathSelectors.any()表示任何的請求
                .paths(PathSelectors.any())
                .build();


        return docket;

    }




}

5.2.3根據你的配置的埠號進行相關的測試

http://localhost:8080/swagger-ui.html

5.2.4 swagger提供了一套註解對每個介面進行詳細的說明

@Api(value=" 用戶管理",tags="提供用戶的登錄和註冊的介面")//這個介面可以直接放在@Controller註解下麵

@ApiOperation 和ApiImplicitParams({ @ApiImplicitParam(dataType="",name="username",value="",required=true), @ApiImplictParm}) 這兩個註解放在@RequestMapping("/login")請求之上,用來修飾方法和方法中的參數。

 @ApiOperation("用戶登錄的介面")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "string",name = "username",value = "用戶登錄的賬號",required = true),
            @ApiImplicitParam(dataType = "string",name = "password",value = "用戶登錄的密碼",defaultValue = "111111",required = false)
    })
    @RequestMapping("/login")
//    @RequestParam可以有預設的參數
    public ResultVO login(@RequestParam("username") String name,@RequestParam(value = "password",defaultValue = "111111") String pwd){

        return userService.checkLogin(name,pwd);


    }
    @RequestMapping(value = "regist",metho

@ApiModel 和@ApiModelProperty介面參數返回一個對象類型時,需要在實體類中添加註解說明(也就是Beans這個Module進行相關的配置)

package com.qfedu.fmmall.entity;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor

@ApiModel(value = "用戶的買家信息",description = "買家的相關的參數")
public class User {

    @ApiModelProperty(name = "用戶id",required = false,dataType = "int")
    private Integer userId;

    @ApiModelProperty(dataType = "string",name = "買家姓名",required = true)
    private String  userName;
    @ApiModelProperty(dataType = "string",name = "買家密碼",required = true)
    private String userPwd;
    @ApiModelProperty(dataType = "string",name = "買家真實姓名",required = true)
    private String userRealname;
    @ApiModelProperty(dataType = "string",name = "用戶圖片",required = true)
    private String userImg;


}
@ApiIgnore     介面方法註解,添加此註解的方法將不會生成到介面文檔中

5.2.5swagger-ui插件使用

1.api的module加入依賴
<!--        swagger-ui插件-->
        <!-- https://mvnrepository.com/artifact/com.github.xiaoymin/swagger-bootstrap-ui -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>


2.進行訪問,然後可以使用它進行相關的測試

http://ip:port/doc.html

一、鋒迷商城設計及實現用戶管理

1.UserDao介面的創建:

package com.qfedu.fmmall.dao;

import com.qfedu.fmmall.entity.User;
import org.springframework.stereotype.Repository;

@Repository
public interface UserDao {

//    用戶註冊
    public int insert(User user);

//   根據用戶名進行登錄的驗證
    public User queryByName(String name);


}


2.UserMapper.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.qfedu.fmmall.dao.UserDao">

 <resultMap id="userResultMap" type="User">
  <id column="user_id" property="userId"></id>

 <result column="username" property="userName"/>
 <result column="password" property="password"/>
 <result column="nickname" property="nickname"/>
 <result column="realname" property="realname"/>
 <result column="user_img" property="userImg"/>
 <result column="user_mobile " property="userMobile"/>
 <result column=" user_email" property="userEmail"/>
 <result column="user_sex " property="userSex"></result>
     <result column=" user_birth" property="userBirth"></result>
     <result column="user_regtime " property="userRegtime"></result>
     <result column="user_modtime " property="userModtime"></result>

 </resultMap>

    
    <select id="queryByName" resultType="User">

     select *from users where username=#{username}

 </select>
    <insert id="insert" parameterType="User">

        insert into users(username,password,user_regtime,user_modtime) values (#{username},
        #{password},#{userRegtime},#{userModtime})
    </insert>
    </mapper>

3.UserService

package com.qfedu.fmmall.service;

import com.qfedu.fmmall.entity.User;
import com.qfedu.fmmall.vo.ResultVO;

public interface UserService {
//    ResultVO是一個響應給前端的自定義的一個類。
    public ResultVO checkLogin(String username, String pwd);

//    用戶註冊
    public ResultVO insert(String username, String pwd);
}

4.UserServiceimpl:

package com.qfedu.fmmall.service.impl;

import com.qfedu.fmmall.service.UserService;
import com.qfedu.fmmall.dao.UserDao;
import com.qfedu.fmmall.entity.User;
import com.qfedu.fmmall.utils.MD5Utils;
import com.qfedu.fmmall.vo.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

@Service
@Transactional
//使所有的線程都用這個對象,單例模式預設是開啟的
@Scope("singleton")
public class UserServiceimpl implements UserService {
    @Autowired
    private UserDao userDao;//可以在UserDao上面加上userDao,這個不會報紅,但是沒有什麼意義
    @Override
    public ResultVO checkLogin(String username, String pwd) {
//        查詢用戶名
        User user = userDao.queryByName(username);
        if(user==null){
//            用戶名不正確

            return new ResultVO(10001,"用戶名不正確",null);



        }else {
            //密碼使用MD5進行加密
            String md5Pwd = MD5Utils.md5(pwd);

            if(md5Pwd.equals(user.getPassword())){
//          驗證成功
                return  new ResultVO(200,"登錄成功",user);
            }else {
                //密碼不正確
                return  new ResultVO(10001,"密碼錯誤",null);

            }


        }



    }
    @Transactional
    @Override
    public ResultVO insert(String username, String pwd) {
//        判斷這個用戶是否被註冊

//        加上這個鎖可以使用所有的註冊都用這個userServiceimpl
        synchronized (this){
//            把密碼進行MD5的加密
            String password = MD5Utils.md5(pwd);

            User user1 = userDao.queryByName(username);
//表示用戶名沒有被註冊過,可以進行註冊
            if (user1==null){
//一個是註冊時間,regtime,一個是修改時間modtime
                User user=new User(username,password,new Date(),new Date());
                int i = userDao.insert(user);
                if(i>0){
                    return new ResultVO(1000,"註冊成功",null);
                }else {

                    return new ResultVO(1001,"註冊失敗",null);

                }


            }
//            判斷一下用戶名是否已經被註冊,然後把數據返回前端,goodjob,Noone can influence you
            else {

                return new ResultVO(1001,"用戶名已經被註冊",null);
            }



        }


    }
}

5.api模塊的UserController:

package com.qfedu.fmmall.vo;


import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor

@ApiModel(value = "ResultVO對象",description = "響應封裝的數據給前端")
public class ResultVO {
//    響應給前端的狀態碼
    @ApiModelProperty(dataType = "int",value = "響應的狀態碼")
    private  int code;

//    響應給前端的提示消息
    @ApiModelProperty(dataType = "string",value = "響應的消息")
    private  String msg;
//響應給前端的數據
    @ApiModelProperty(dataType = "object",value = "響應數據的內容")
    private  Object data;
}

6.ResultVO一個和前端進行數據交互的類

package com.qfedu.fmmall.vo;


import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor

@ApiModel(value = "ResultVO對象",description = "響應封裝的數據給前端")
public class ResultVO {
//    響應給前端的狀態碼
    @ApiModelProperty(dataType = "int",value = "響應的狀態碼")
    private  int code;

//    響應給前端的提示消息
    @ApiModelProperty(dataType = "string",value = "響應的消息")
    private  String msg;
//響應給前端的數據
    @ApiModelProperty(dataType = "object",value = "響應數據的內容")
    private  Object data;
}

7.在common模塊的MD5Utils類:

package com.qfedu.fmmall.utils;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

//MD5 生成器
public class MD5Utils {
	public static String md5(String password){
		//生成一個md5加密器
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			//計算MD5 的值
			md.update(password.getBytes());
			//BigInteger 將8位的字元串 轉成16位的字元串 得到的字元串形式是哈希碼值
			//BigInteger(參數1,參數2) 參數1 是 1為正數 0為0 -1為負數
			return new BigInteger(1, md.digest()).toString(16);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}
}

二、逆向工程

根據創建好的表,生成實體類,和DAO層、映射文件

在Dependencies下麵加入依賴,這個依賴是一個Mybatis的maven插件

<build>
    <plugins>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.5</version>
            <configuration>
                <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
            </configuration>
            

            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.46</version>
                </dependency>
                <dependency>
                    <groupId>tk.mybatis</groupId>
                    <artifactId>mapper</artifactId>
                    <version>4.1.5</version>
                </dependency>


            </dependencies>

  </plugin>

    </plugins>


</build>

7.1逆向工程配置

在resources的generator目錄下麵創建generatorConfig.xml

  1. 需要修改資料庫的配置

  2. 需要修改pojo,mapper,Mapper.xml文件生成位置的配置

  3. <!--%表示當前這個資料庫裡面的所有的表都會被生成-->
            <table tableName="%"></table>
    
  4. <!-- 指定生成 Mapper 的繼承模板 -->
           <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
               <property name="mappers" value="com.hou.general.GeneralDao"/>
           </plugin>
      
    
  5. 指定你的用Configuration generatorConfig.xml文件的路徑

  6. 註意一下你的文件一定想要有空格什麼東西的

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!-- 引入 application.properties -->

<!--    <properties resource="application.properties" />-->

    <!-- MyBatis3Simple:不生成 Example相關類及方法 defaultModelType="flat" -->
    <context id="MysqlContext" targetRuntime="MyBatis3Simple" >

        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <!-- 指定生成 Mapper 的繼承模板 -->
        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <property name="mappers" value="com.qfedu.fmmall.general.GeneralDao"/>
        </plugin>

        <!--註意context內的文件要按序放-->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自動生成的註釋 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>


        <!-- jdbc 連接配置 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/fmmall?characterEncoding=utf8"
                        userId="root"
                        password="roothouzhicong">
        </jdbcConnection>

        <javaTypeResolver>
            <!-- 是否使用bigDecimal, false可自動轉化以下類型(Long, Integer, Short, etc.) -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 生成實體類的包名和位置 ,targetPackage指的是包名,targetProject值得是路徑位置-->
        <!-- 對於生成的pojo所在包,pojo其實就是domain Entity-->
        <javaModelGenerator targetPackage="com.qfedu.fmmall.entity" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- 對於生成的mapper.xml所在目錄 -->
        <sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>

        <!-- 配置mapper對應的java映射  也可以叫dao層 -->
        <javaClientGenerator targetPackage="com.qfedu.fmmall.dao" targetProject="src/main/java"
                             type="XMLMAPPER"/>

        <!--%表示當前這個資料庫裡面的所有的表都會被繼承-->
        <table tableName="%"></table>

    </context>
</generatorConfiguration>

7.2在pom.xml文件中指定generatorConfig.xml文件的路徑

加上了這個:

 <configuration>
                <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
            </configuration>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.5</version>
            <configuration>
                <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
            </configuration>

            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.46</version>
                </dependency>
                <dependency>
                    <groupId>tk.mybatis</groupId>
                    <artifactId>mapper</artifactId>
                    <version>4.1.5</version>
                </dependency>


            </dependencies>


        </plugin>

三、跨域問題

解決方案:
後端解決辦法:在UserController加上@CrossOrigin註解

前端通過Ajax請求跨域登錄:

		<form>
							<div class="user-name"  style="margin-top: 20px;">
								<label for="user"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></label>
								<input type="text" name="username" id="userName" placeholder="郵箱/手機/用戶名">
							</div>
							<div class="user-pass"  style="margin-top: 20px;">
								<label for="password"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></label>
								<input type="password" name="" id="userPwd" placeholder="請輸入密碼">
							</div>
						</form>




<input type="button" name="" id="submitBtn"  value="登 錄" class="am-btn am-btn-primary am-btn-sm">




<script src="static/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript">

$("#submitBtn").click(function(){
	var name=$("#userName").val();
	var pwd=$('#userPwd').val();
  $.get("http://localhost:8080/user/login",{
	  username:name,
	  password:pwd,
  },function(res){
	  console.log(res);



  },"json"
 
  
  
  
  )



})

</script>





前端使用JSONP設置,後端使用@CrossOrigin註解解決---設置響應頭header允許跨域。
debugger;前端 可以加上代碼debugger進行相關的調試。可以直接進行前端的校驗

四、前端頁面的傳值

cookie和localstorage可以進行前端的頁面之間的傳值

Cookie瀏覽器端的緩存文件:大小受瀏覽器的限制。

LocalStorage:為了存儲更大容量的數據

區別:cookie可以和後臺進行傳值,localStorage只可以在前端存儲值,但是存儲的時間長。

4.1Cookie使用(自定義封裝一個js,cookie_utils.js)

var opertor="=";

function getCookieValue(keyStr){
	
	
	var s=window.document.cookie;
	var arr=s.split("; ");
for(var i=0;i<arr.length;i++){
	var str=arr[i];

	var k=str.split(opertor)[0];
	var v=str.split(opertor)[1];
	if(k==keyStr){

		value=v;
		break;
	}

	
}
return value;



}


function setCookieValue(key,value){

	document.cookie=key+opertor+value;



}

A頁面設置值:

function(res){
	  console.log(res);
	  if(res.code==1000){
// 獲取前端傳過來的數據 data
		var userInfo=res.data;
		// cookie和localstorage可以進行前端的頁面之間的傳值
	setCookieValue("username",userInfo.username);
	setCookieValue("userImg",userInfo.userImg);

		window.location.href="index.html";
	  }else{

		$("#tips").html("<label style='color:red'>"+ res.msg +"</label>");




	  }

B頁面取值:

var name=getCookieValue("username");
 var userImg=getCookieValue("userImg");
 console.log(name+userImg);

4.2localStorage

A頁面:

	localStorage.setItem("user",JSON.stringify(userInfo));

B頁面:

var jsonStr=localStorage.getItem("user");

// 把json串轉換為對象
var userInfo=eval("("+jsonStr+")");


// 把取到的值消失
localStorage.removeItem("user");
console.log(userInfo);

4.3Vue實現登錄

data:{
		username:"",
		password:"",	
		tips:" ",
		colorStyle:"",
		isRight:false,
	


	},
	methods:{
		doSubmit:function() {
			// 校驗成功

			if(vm.isRight){
				var url=baseUrl+"/user/login";
				axios.get(url,{	
					params:{
						username:vm.username,password:vm.password

					} }
				
					).then((res)=>{

				console.log(res);

					var vo=res.data;
					if(vo.code==1){
						window.location.href="index.html";
					}else{
						vm.tips="賬號或者密碼錯誤";
					}



				});

			}else{
				vm.tips="請輸入正確的用戶名和密碼";
				vm.colorStyle="color:red"
			}

            //  1.進行數據的校驗

            if(vm.username==" "){
                vm.tips="請輸入用戶名";
                vm.colorStyle="color:red";


            }
             
         },
         checkInfo:function(){
            if(vm.username==""){
                vm.tips="請輸入用戶名";
                this.colorStyle="color:red";
				vm.isRight=false;


            }else if(vm.username.length<6 ||vm.username.length>20){
                vm.tips="賬號長度必須為6-20";
                vm.colorStyle="color:red";
				vm.isRight=false;





            }else{
// 校驗密碼
				if(vm.password==" "){
                vm.tips="請輸入密碼";
                this.colorStyle="color:red";
				vm.isRight=false;


            }else if(vm.password.length<6 ||vm.password.length>16){
				vm.tips="密碼長度為6-16";
                this.colorStyle="color:red";

			}else{
				vm.tips=" ";
				vm.isRight=true;
			}



			}





         }







	}


from表單(用@keyup進行表單的輸入的綁定):

	<form>
							<div class="user-name"  style="margin-top: 20px;">
								<label for="user"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></label>
								<!-- @keyup進行綁定 -->
								<input type="text" name="username" v-model="username" id="userName" @keyup="checkInfo" placeholder="郵箱/手機/用戶名">
							</div>
							<div class="user-pass"  style="margin-top: 20px;">
								<label for="password"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></label>
								<input type="password" name="" v-model="password" id="userPwd" placeholder="請輸入密碼"@keyup="checkInfo">
							</div>
						</form>

五、前後端分離開發用戶認證的問題

5.1單體項目中:

可以知道每台伺服器中存在多個Session,只是id不相同,Cookie中可以存放sessionId,然後判斷是是不是同一個session

在單體項目中用戶怎麼認證的?

在單體項目中視圖資源和控制器都在同一臺伺服器,用戶的多次請求老師基於同一個會話,可以基於session進行會話的驗證:

  1. 用戶登錄將信息存放在session中
  2. 根據session中是否有用戶信息來判斷用戶是否可以進行登錄。

5.2前後端分離項目中

可以知道使用token實現用戶驗證,token存在於cookie中(同一臺伺服器可以訪問cookie),然後驗證token是否正確

基於token認證的用戶代碼實現

在commons模塊中引入

package com.qfedu.fmmall.utils;

import java.util.Base64;

//base64 加密 解密 激活郵件的時候 為 郵箱地址 code驗證碼 進行加密
//當 回傳回來後 進行郵箱地址 和 code 的解密
public class Base64Utils {
	//加密
	public static String encode(String msg){
		return Base64.getEncoder().encodeToString(msg.getBytes());
	}
	//解密
	public static String decode(String msg){
		return new String(Base64.getDecoder().decode(msg));
	}
}

登錄成功生成token:UserController

package com.qfedu.fmmall.controller;


import com.qfedu.fmmall.entity.Users;
import com.qfedu.fmmall.service.UserService;
import com.qfedu.fmmall.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/*@Controller
@ResponseBody*/

@RestController
@RequestMapping("/user")
@CrossOrigin
@Api(value = "提供用戶的登錄和註冊的介面",tags = "用戶管理")
public class UserController {

    @Autowired
    private UserService userService;

//    @ApiIgnore加上這個註解會swagger忽略這個方法
    @ApiOperation("用戶登錄的介面")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "string",name = "username",value = "用戶登錄的賬號",required = true),
            @ApiImplicitParam(dataType = "string",name = "password",value = "用戶登錄的密碼",required = true)
    })
    @RequestMapping("/login")
//    @RequestParam可以有預設的參數
    public ResultVO login(@RequestParam("username") String name,@RequestParam(value = "password") String pwd){

        return userService.checkLogin(name,pwd);


    }

    @ApiOperation(value = "用戶註冊")
    @PostMapping("/regist")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "string",name = "username",value = "用戶註冊的賬號",required = true),
            @ApiImplicitParam(dataType = "string",name = "password",value = "用戶註冊的密碼",required = true)
    })
//    前端用user傳值,後端可以用users 接收
     public ResultVO register(@RequestBody Users users){

        return userService.insert(users.getUsername(),users.getPassword());

    }


}

然後在UserServiceimpl中進行token的加密:

// 如果登錄成功,則需要生成令牌token(token就是按照規則生成的字元串)
String token= Base64Util.encode(username+"roothouzhicong");

package com.qfedu.fmmall.service.impl;

import com.qfedu.fmmall.dao.UsersMapper;
import com.qfedu.fmmall.entity.Users;
import com.qfedu.fmmall.service.UserService;
import com.qfedu.fmmall.utils.MD5Utils;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVO;
import org.apache.logging.log4j.util.Base64Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

@Service
@Transactional
//使所有的線程都用這個對象,單例模式預設是開啟的
@Scope("singleton")
public class UserServiceimpl implements UserService {
    @Autowired
    private UsersMapper userDao;//可以在UserDao上面加上userDao,這個不會報紅,但是沒有什麼意義
    @Override
    public ResultVO checkLogin(String username, String pwd) {
//        查詢用戶名

        Example example = new Example(Users.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username",username);
        List<Users> users = userDao.selectByExample(example);

//
        if(users.size()==0){
//            用戶名不正確

            return new ResultVO(10001,"用戶名不正確",null);



        }else {
            //密碼使用MD5進行加密
            String md5Pwd = MD5Utils.md5(pwd);
            System.out.println(users.get(0).getPassword());

            if(md5Pwd.equals(users.get(0).getPassword())){

//                如果登錄成功,則需要生成令牌token(token就是按照規則生成的字元串)
                String token= Base64Util.encode(username+"roothouzhicong");

                //          驗證成功
                return  new ResultVO(ResultStatus.OK,token,users.get(0));
            }else {
                //密碼不正確
                return  new ResultVO(ResultStatus.NO,"密碼錯誤",null);

            }


        }



    }
    @Transactional
    @Override
    public ResultVO insert(String username, String pwd) {
//        判斷這個用戶是否被註冊

//        加上這個鎖可以使用所有的註冊都用這個userServiceimpl
        synchronized (this){
//            把密碼進行MD5的加密
            String password = MD5Utils.md5(pwd);

            //        查詢用戶名

            Example example = new Example(Users.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("username",username);
            List<Users> users = userDao.selectByExample(example);
//表示用戶名沒有被註冊過,可以進行註冊
            if (users.size()==0){
//一個是註冊時間,regtime,一個是修改時間modtime
                Users user=new Users(username,password,new Date(),new Date());
                int i = userDao.insert(user);
                if(i>0){
                    return new ResultVO(ResultStatus.OK,"註冊成功",null);
                }else {

                    return new ResultVO(ResultStatus.NO,"註冊失敗",null);

                }


            }
//            判斷一下用戶名是否已經被註冊,然後把數據返回前端,goodjob,Noone can influence you
            else {

                return new ResultVO(ResultStatus.NO,"用戶名已經被註冊",null);
            }



        }


    }
}

前端設置token:

	doSubmit:function() {
			// 校驗成功

			if(vm.isRight){
				var url=baseUrl+"/user/login";
				axios.get(url,{	
					params:{
						username:vm.username,password:vm.password

					} }
				
					).then((res)=>{

				console.log(res);

					var vo=res.data;

					console.log(vo);
					if(vo.code==1){
					
 // 如果登錄成功就把token存儲到時cookie中
						setCookieValue("token",vo.msg);

						 window.location.href="index.html";
					}else{
						vm.tips="賬號或者密碼錯誤";
					}



				});

前端的購物車獲取token:

	<script type="text/javascript">
		// 進入購物車時要訪問購物車列表的介面shopController介面
		var baseUrl="http://localhost:8080/";    
		var vm=new Vue({
			el:"#app",
			data:{
				token:"",
			},
			created() {
				this.token=getCookieValue("token");
				console.log("token="+this.token);
				axios({
					method:"get",
					url:baseUrl+"shopcart/list",
					params:{
						token:this.token,
					}

				}).then(function (res) {
					console.log(res);
				});
			},
			




		})
		
		
		
		
		
		
		
		
		
		</script>

登錄進行來可以把購物車獲取token,前端的token用CookieUtils.js封裝的包進行相關的獲取,

package com.qfedu.fmmall.controller;


import com.qfedu.fmmall.utils.Base64Utils;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin
@Api(value = "提供購物車業務相關的介面",tags = "購物車管理介面")
@RequestMapping("/shopcart")
public class ShopCartController {

    @RequestMapping("/list")
    @ApiImplicitParam(dataType = "string",name = "token",value = "登錄的一個標誌",required = true)
    public ResultVO shopcartList(String token){
//        校驗輸入的token看看是否是用戶自己登錄的token
       //解密 
        String decode = Base64Utils.decode(token);
        if(token==null){
            return new ResultVO(ResultStatus.NO, "請先登錄", null);


        }else if(decode.endsWith("roothouzhicong")) {


            System.out.println("購物車列表相關的介面------------");
            return new ResultVO(ResultStatus.OK, "success", null);


        }else {

            return new ResultVO(ResultStatus.NO, "登錄已經過期,請重新登錄!!", null);

        }


    }
}

六、JWT(json Web Token)一個別人封裝好的工具類生成相關的token

  1. 用自定義的token生成的時效性不可以進行定義
  2. 安全性較差

JWT結構:

6.1生成JWT

  • 添加依賴:

    <!--        jwt生成 -->
            <dependency>
                <groupId>com.auth0</groupId>
                <artifactId>java-jwt</artifactId>
                <version>3.10.3</version>
            </dependency>
    <!--        jjwt生成-->
            <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
    
    
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 面向對象 一、三大特征之繼承 python三大特征: 封裝、繼承、多態 三者中繼承最為核心,實際應用多,感受較為直觀 封裝和多態略微抽象 1、繼承的概念 繼承的含義: ​ 在現實生活中,繼承表示人與人之間資源的從屬關係 ​ 例如:兒子繼承父親 ​ 在編程的世界中,繼承表示類與類之間的資源從屬關係 ​ ...
  • 熱度已經過了,但還是覺得有必要從架構設計的角度來討論一下此事。並用以往我的經驗來設計一套負載能力更好一些的系統。 先說一下基本的架構思路: 最大限度的避免計算,靜態化 不用資料庫,更新類操作使用APPEND模式的文本文件 流程最短,最好是客戶端訪問的第一臺伺服器就能完成全部工作 善用CDN 客戶端負 ...
  • 您好,我是湘王,這是我的博客園,歡迎您來,歡迎您再來~ 從之前的Lambda表達式的演變過程可以知道,Lambda表達式其實是一個對匿名內部類的簡化過程:去掉了多餘的語法修飾,只保留最最核心的部分。在Java中類似這種使用匿名內部類寫代碼的場景非常多,比如Runnable介面,就是典型的最好使用La ...
  • 本節內容會用到之前給大家講過的這兩篇: 2流高手速成記(之六):從SpringBoot到SpringCloudAlibaba 2流高手速成記(之三):SpringBoot整合mybatis/mybatis-plus實現數據持久化 鏈接掛出來,方便咱們中途對比著看 老規矩,先放出本節的項目結構: 我們 ...
  • XML 官方文檔:https://www.w3school.com.cn/xml/index.asp 1.為什麼需要xml? 需求1:兩個程式間進行數據通信? 需求2:給一臺伺服器,做一個配置文件,當伺服器程式啟動時,去讀取它應當監聽的埠號、還有連接資料庫的用戶名和密碼 spring中的IOC配置 ...
  • 大家好,我是metahuber,數字宇宙探索者。 本系列教程是Python的入門教程,本篇文章是此教程的第一篇,希望大家多多關註。 在學習Python之前,我們首先瞭解下什麼是編程語言。 說到編程語言,還需要從程式說起。 其實,程式就是一系列指令,電腦之所以能夠工作,根本的原因是它能夠識別人類發出 ...
  • 登錄介面分析 登錄分為多方式登錄和驗證碼登錄方式 多方式登錄 1)前臺提供賬號密碼,賬號可能是 用戶名、手機號、郵箱等 介面: 後臺只需要提供一個多方式登錄介面即可 - 多方式登錄介面 多方式登錄介面 前端輸入完賬號和密碼,點擊登錄,向後端發送請求進行校驗用戶登錄數據 urls.py from dj ...
  • 簡介: 適配器模式屬於結構型設計模式。 將一個類的介面轉換成可應用的相容介面。適配器使原本由於介面不相容而不能一起工作的那些類可以一起工作。 適配器模式有兩種實現方案,一種是繼承的方式,一種是組合的方式。 適用場景: 相容不方便更改的“祖傳”代碼。 歸納具有相似點的模塊,比如Laravel File ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...