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

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

2022-11-04 06:26:14 後端開發

@

目錄
  • 自己添加的后端管理頁面
    • 視頻演示效果
    • 論文地址
    • 后臺代碼視頻實作講解思路
    • 1. 商品管理
    • 2.商品分類管理
    • 3.商品地址管理
    • 4.用戶中心管理
    • 4. 用戶權限管理
    • 5.訂單管理
      • 5.1
    • 6.商品品牌管理
  • 鋒迷商城專案
      • 1.通過Maven聚合工程搭建專案:
        • 1. 創建一個Maven的父專案,然后修改它的pom.xml檔案,可以洗掉src等一些沒有用的目錄
        • 2.在父專案下面創建多個module,包括(common,beans,mapper,service,api)把它們全部打包成jar包
      • 3.由于mapper層需要呼叫beans層(pojo),需要在pom.xml檔案中,然后可以在mapper中加入相關的依賴,
      • 4.創建service需要呼叫mapper,和common,需要在pom.xml檔案中加上
      • 5.api層需要接收前端的請求所以需要我們創建一個SpringBoot工程,你可以創建一個Maven工程,然后加入相關的依賴
      • 6.api子工程,對外提供介面
    • 鋒迷商城資料庫設計
      • 2.軟體開發步驟
      • 3.資料庫設計流程
      • 3.資料建模工具PDMan
        • Spu和Sku的區別
      • 4.鋒城業務流程設計
        • 4.1用戶管理9業務流程分析
      • 5介面介紹
        • 5.1介面規范
      • 5.2Swagger(自動生成服務器介面的規范性檔案)
        • 5.2.1引入相關的依賴:
        • 5.2.2 創建相關的配置類
        • 5.2.3根據你的配置的埠號進行相關的測驗
        • 5.2.4 swagger提供了一套注解對每個介面進行詳細的說明
        • 5.2.5swagger-ui插件使用
          • 1.api的module加入依賴
          • 2.進行訪問,然后可以使用它進行相關的測驗
      • 一、鋒迷商城設計及實作用戶管理
        • 1.UserDao介面的創建:
        • 2.UserMapper.xml
        • 3.UserService
        • 4.UserServiceimpl:
        • 5.api模塊的UserController:
        • 6.ResultVO一個和前端進行資料互動的類
        • 7.在common模塊的MD5Utils類:
      • 二、逆向工程
        • 7.1逆向工程配置
        • 7.2在pom.xml檔案中指定generatorConfig.xml檔案的路徑
      • 三、跨域問題
      • 四、前端頁面的傳值
        • 4.1Cookie使用(自定義封裝一個js,cookie_utils.js)
        • 4.2localStorage
        • 4.3Vue實作登錄
      • 五、前后端分離開發用戶認證的問題
        • 5.1單體專案中:
        • 5.2前后端分離專案中
        • 基于token認證的用戶代碼實作
      • 六、JWT(json Web Token)一個別人封裝好的工具類生成相關的token
      • 6.1生成JWT
        • 6.2使用攔截器進行攔截
      • 6.3使用請求頭進行傳遞token
        • axios通過請求頭傳值 里面的引數用Headers 不用Params
        • 6.3.1 CheckTokenInterceptor類 前端會發送預險性請求(只有它通過以后才可以進行第二次請求),需要攔截器進行放行
      • 七首頁的分類串列的的實作
        • 7.1介面實作
        • 7.2業務層實作
        • 控制層實作
      • 八、商品的推薦功能實作
        • 8.1 流程分析
        • 8.2介面開發
          • 8.2.1資料庫的實作
        • ProductMapper檔案:
        • ProductImgMapper檔案:
        • ProductMapper.xml檔案實作
      • 8.2.2業務層實作
        • 8.2.3控制層實作
      • 九、商品詳情顯示(在Introduction.html進行相關的顯示)
        • 9.1介面實作
        • 9.1.1 商品詳情介面
      • 十、顯示商品評價的資訊(通過用戶和商品評論表進行相關的連表查詢)
        • 10.1 新建的VO,ProductCommentsVO (一對一的連表查詢可以不用在物體類中宣告另一個物體類)
    • 十一、添加購物車的功能實作
        • 10.1流程分析:
        • 10.2資料庫的相關的操作
        • 10.2.1 購買的數量的前端實作在vue的methods中添加+和-的點擊事件
        • 10.2.2給加入購物車這個按鈕添加點擊事件
    • 十二、添加購物車時候用戶未登錄
        • 12.1 添加購物車用戶未登錄,業務處理方式:
        • 12.2我們使用第三種難度最大的來
        • 12.3使用Layui進行添加購物車成功/失敗的提示
          • 12.3.1宣告layui的彈窗組件
        • 12.3.2成功失敗進行提示
    • 十三購物車的串列
        • 13.1資料庫dao介面的實作
        • 13.2pojo介面實作
        • 13.3修改購物車
          • 13.31通過這個進行購物車數量的修改:
          • 13.32changNum函式進行實作:
    • 十四購物車提交訂單結算功能實作
      • 14.1實作流程分析
    • 十五、訂單提交及支付流程
      • 15.1流程分析
      • 15.2訂單添加介面實作
      • 15.3資料庫操作
      • 15.4serviceimpl層實作 注意:這個方法需要加上@Transactional,也就是訂單生成的時候,快照也必須生成
    • swagger報錯解決
    • 十六 商品個人中心訂單資訊的查詢
      • 16.1 流程分析
        • sql陳述句
        • OrderMapper.xml檔案:
      • 16.2 介面開發
        • 16.2.1 Service層介面開發
      • 16.2.2 Controller層實作
      • 16.2.3前端使用Vue+ElementUI實作分頁功能
        • 1. 引入cdn
        • 2. data中定義相關資料
        • 3.分頁的相關的方法
        • 4. 分頁的表格
        • Linux的常用 的命令的復習
      • Linux系統安裝jdk
      • Linux安裝Tomcat
          • 如果你的專案是部署在Tomcat上面的,你可以把你的專案打成war包,放在tomcat的weapp目錄下面,運行tomcat即可進行該專案
      • Linux安裝mysql(在線安裝)
    • 20.鋒迷專案的后端云部署
      • 20.1企業專案當中需要進行修改的東西:
        • 20.11在你的Linux中建立一個目錄用來存放你的jar包:
    • 21.前端的專案的部署在云服務器上面
    • Tomcat作為前端專案的弊端
      • 1.前端會有大量的請求,Tomcat的弊端(難以滿足高并發的,大約是2000-3000,使用Niginx可以提高高并發的承受,大約2萬)
    • 22.Nginx
    • 23.前端專案部署在Nginx上面
    • 24.Linux安裝Nginx(在線安裝)
      • 24.1 安裝編譯工具(nginx安裝之前需要編譯)
      • 24.2安裝PCRE
      • 24.3安裝SSL庫
      • 24.4安裝zlib庫
      • 24.5下載Nginx

自己添加的后端管理頁面

視頻演示效果

[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="https://www.cnblogs.com/smallcutemonkey/p/用戶管理",tags="提供用戶的登錄和注冊的介面")//這個介面可以直接放在@Controller注解下面

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

 @ApiOperation("用戶登錄的介面")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "string",name = "username",value = "https://www.cnblogs.com/smallcutemonkey/p/用戶登錄的賬號",required = true),
            @ApiImplicitParam(dataType = "string",name = "password",value = "https://www.cnblogs.com/smallcutemonkey/p/用戶登錄的密碼",defaultValue = "https://www.cnblogs.com/smallcutemonkey/p/111111",required = false)
    })
    @RequestMapping("/login")
//    @RequestParam可以有默認的引數
    public ResultVO login(@RequestParam("username") String name,@RequestParam(value = "https://www.cnblogs.com/smallcutemonkey/p/password",defaultValue = "https://www.cnblogs.com/smallcutemonkey/p/111111") String pwd){

        return userService.checkLogin(name,pwd);


    }
    @RequestMapping(value = "https://www.cnblogs.com/smallcutemonkey/p/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 = "https://www.cnblogs.com/smallcutemonkey/p/用戶的買家資訊",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 = "https://www.cnblogs.com/smallcutemonkey/p/ResultVO物件",description = "回應封裝的資料給前端")
public class ResultVO {
//    回應給前端的狀態碼
    @ApiModelProperty(dataType = "int",value = "https://www.cnblogs.com/smallcutemonkey/p/回應的狀態碼")
    private  int code;

//    回應給前端的提示訊息
    @ApiModelProperty(dataType = "string",value = "https://www.cnblogs.com/smallcutemonkey/p/回應的訊息")
    private  String msg;
//回應給前端的資料
    @ApiModelProperty(dataType = "object",value = "https://www.cnblogs.com/smallcutemonkey/p/回應資料的內容")
    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 = "https://www.cnblogs.com/smallcutemonkey/p/ResultVO物件",description = "回應封裝的資料給前端")
public class ResultVO {
//    回應給前端的狀態碼
    @ApiModelProperty(dataType = "int",value = "https://www.cnblogs.com/smallcutemonkey/p/回應的狀態碼")
    private  int code;

//    回應給前端的提示訊息
    @ApiModelProperty(dataType = "string",value = "https://www.cnblogs.com/smallcutemonkey/p/回應的訊息")
    private  String msg;
//回應給前端的資料
    @ApiModelProperty(dataType = "object",value = "https://www.cnblogs.com/smallcutemonkey/p/回應資料的內容")
    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="https://www.cnblogs.com/smallcutemonkey/p/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="https://www.cnblogs.com/smallcutemonkey/p/`"/>
        <property name="endingDelimiter" value="https://www.cnblogs.com/smallcutemonkey/p/`"/>

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

        <!--注意context內的檔案要按序放-->
        <commentGenerator>
            <property name="suppressDate" value="https://www.cnblogs.com/smallcutemonkey/p/true"/>
            <!-- 是否去除自動生成的注釋 true:是 : false:否 -->
            <property name="suppressAllComments" value="https://www.cnblogs.com/smallcutemonkey/p/true"/>
        </commentGenerator>


        <!-- jdbc 連接配置 -->
        <jdbcConnection 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="https://www.cnblogs.com/smallcutemonkey/p/false"/>
        </javaTypeResolver>

        <!-- 生成物體類的包名和位置 ,targetPackage指的是包名,targetProject值得是路徑位置-->
        <!-- 對于生成的pojo所在包,pojo其實就是domain Entity-->
        <javaModelGenerator targetPackage="com.qfedu.fmmall.entity" targetProject="src/main/java">
            <property name="enableSubPackages" value="https://www.cnblogs.com/smallcutemonkey/p/true"/>
            <property name="trimStrings" value="https://www.cnblogs.com/smallcutemonkey/p/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   style="margin-top: 20px;">
								<label for="user"><span  aria-hidden="true"></span></label>
								<input type="text" name="username" id="userName" placeholder="郵箱/手機/用戶名">
							</div>
							<div   style="margin-top: 20px;">
								<label for="password"><span  aria-hidden="true"></span></label>
								<input type="password" name="" id="userPwd" placeholder="請輸入密碼">
							</div>
						</form>




<input type="button" name="" id="submitBtn"  value="https://www.cnblogs.com/smallcutemonkey/p/登 錄" >




<script src="https://www.cnblogs.com/smallcutemonkey/p/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=https://www.cnblogs.com/smallcutemonkey/p/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="https://www.cnblogs.com/smallcutemonkey/p/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="https://www.cnblogs.com/smallcutemonkey/p/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   style="margin-top: 20px;">
								<label for="user"><span  aria-hidden="true"></span></label>
								<!-- @keyup進行系結 -->
								<input type="text" name="username" v-model="username" id="userName" @keyup="checkInfo" placeholder="郵箱/手機/用戶名">
							</div>
							<div   style="margin-top: 20px;">
								<label for="password"><span  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 = "https://www.cnblogs.com/smallcutemonkey/p/提供用戶的登錄和注冊的介面",tags = "用戶管理")
public class UserController {

    @Autowired
    private UserService userService;

//    @ApiIgnore加上這個注解會swagger忽略這個方法
    @ApiOperation("用戶登錄的介面")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "string",name = "username",value = "https://www.cnblogs.com/smallcutemonkey/p/用戶登錄的賬號",required = true),
            @ApiImplicitParam(dataType = "string",name = "password",value = "https://www.cnblogs.com/smallcutemonkey/p/用戶登錄的密碼",required = true)
    })
    @RequestMapping("/login")
//    @RequestParam可以有默認的引數
    public ResultVO login(@RequestParam("username") String name,@RequestParam(value = "https://www.cnblogs.com/smallcutemonkey/p/password") String pwd){

        return userService.checkLogin(name,pwd);


    }

    @ApiOperation(value = "https://www.cnblogs.com/smallcutemonkey/p/用戶注冊")
    @PostMapping("/regist")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "string",name = "username",value = "https://www.cnblogs.com/smallcutemonkey/p/用戶注冊的賬號",required = true),
            @ApiImplicitParam(dataType = "string",name = "password",value = "https://www.cnblogs.com/smallcutemonkey/p/用戶注冊的密碼",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="https://www.cnblogs.com/smallcutemonkey/p/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 = "https://www.cnblogs.com/smallcutemonkey/p/提供購物車業務相關的介面",tags = "購物車管理介面")
@RequestMapping("/shopcart")
public class ShopCartController {

    @RequestMapping("/list")
    @ApiImplicitParam(dataType = "string",name = "token",value = "https://www.cnblogs.com/smallcutemonkey/p/登錄的一個標志",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>
            <version>0.9.1</version>
        </dependency>
    
    

UserServiceimpl(登錄成功)生成token:

 HashMap<String,Object> map=new HashMap<>();

                JwtBuilder builder= Jwts.builder();
                String token = builder.setSubject(username)   //主題就是token中攜帶的資料
                        .setIssuedAt(new Date()) //設定token的生成時間
                        .setId(users.get(0).getUserId() + "") //設定用戶的id為tokenid
                        .setClaims(map)                         //map中可以存放用戶的角色權限資訊
                        .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000)) //設定token的過期時間
                        .signWith(SignatureAlgorithm.HS256, "houzhicong") //設定加密的方式
                        .compact();

                //          驗證成功

前端ShopCart.html通過Cookie獲取生成的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",
					Headers:{
						token:this.token,
					}

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




		})
		
		
		
		
		
		
		
		
		
		</script>

后端ShopController進行決議Token:

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.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
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 = "https://www.cnblogs.com/smallcutemonkey/p/提供購物車業務相關的介面",tags = "購物車管理介面")
@RequestMapping("/shopcart")
public class ShopCartController {

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


        }else {
            JwtParser parser= Jwts.parser();
            parser.setSigningKey("houzhicong");//決議token 必須和生成token時候生成的密碼一致

//            如果token正確(密碼正確,有效期內) 則正常執行,否則拋出例外
            try{


                Jws<Claims> claimsJws=parser.parseClaimsJws(token);

                Claims body=claimsJws.getBody();//獲取token中的用戶資料
                String subject=body.getSubject();//獲取生成token設定subject
               String v1=body.get("key1",String.class);//獲取生成token時存盤的Claims的map中的值
                return new ResultVO(ResultStatus.OK, "success", null);

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


            }



        }


    }
}

6.2使用攔截器進行攔截

  1. 創建一個CheckTokenInterceptor
  2. 創建一個攔截器的類 InterceptorConfig
6.3.1有

package com.qfedu.fmmall.config;

import com.qfedu.fmmall.interceptor.CheckTokenInterceptor;
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;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private CheckTokenInterceptor checkTokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CheckTokenInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/user/**"
                ,"/doc.html"
                ,"/swagger-ui/**");
    }
}

6.3使用請求頭進行傳遞token

前端但凡訪問受限資源,都必須攜帶token請求,token可以通過請求行(params),請求頭(header),以及請求體(data)傳遞,但習慣使用header傳遞

axios通過請求頭傳值 里面的引數用Headers 不用Params

axios({
					method:"get",
					url:baseUrl+"shopcart/list",
					Headers:{
						token:this.token,
					}

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

6.3.1 CheckTokenInterceptor類 前端會發送預險性請求(只有它通過以后才可以進行第二次請求),需要攔截器進行放行

package com.qfedu.fmmall.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVO;
import io.jsonwebtoken.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
public class CheckTokenInterceptor implements HandlerInterceptor {
//   打ov 可以看到它的方法


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getParameter("token");

//        System.out.println("token----------");

//        前端會發送預險性請求
        String method = request.getMethod();

        if("options".equalsIgnoreCase(method)){

            return true;
        }

        if(token==null){
//            提示用戶進行登錄

            PrintWriter out = response.getWriter();
            ResultVO resultVO= new ResultVO(ResultStatus.NO, "請先登錄", null);
//         抽出一個方法進行
            doResponse(response,resultVO);


//            攔截
            return  false;

        }else {
//            驗證token

            try{

                JwtParser parser= Jwts.parser();
                parser.setSigningKey("houzhicong");
                Jws<Claims> claimsJws=parser.parseClaimsJws(token);
                return true;
            }catch (ExpiredJwtException e){
                ResultVO resultVO= new ResultVO(ResultStatus.NO, "登錄過期,請重新登錄", null);
                doResponse(response,resultVO);


                return false;
            }
            catch (UnsupportedJwtException e){
                ResultVO resultVO= new ResultVO(ResultStatus.NO, "Token不合法,請自重", null);
                doResponse(response,resultVO);


                return false;
            }

            catch (Exception e){
                ResultVO resultVO= new ResultVO(ResultStatus.NO, "請先登錄", null);
                doResponse(response,resultVO);


                return false;
            }





        }

    }

    private void doResponse(HttpServletResponse response,  ResultVO resultVO) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
//        寫上Json格式的resultVO
        String s = new ObjectMapper().writeValueAsString(resultVO);
        out.println(s);
        out.flush();
        out.close();


    }
}

七首頁的分類串列的的實作

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

得出結論:資料量較少的情況,使用一次性查詢,資料量較多使用多次查詢

方案一:一次性查詢三級分類

  • 優點只需一查詢
  • 缺點:資料庫查詢效率較低,頁面首次加載的速度較慢

方案二:

  • 先只查詢一級分類,用戶點擊/滑鼠移動到一級分類,動態加載二級分類
  • 缺點:需要多次連接資料庫

7.1介面實作

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

一次性查詢出來的sql陳述句:inner join 和left join 的區別 left join 左邊沒有關聯的資料也會全部顯示

select 

c1.category_id 'category_id1',
c1.category_name 'category_name',
c1.category_level 'category_level',
c1.parent_id 'parent_id',
c1.category_icon 'category_icon',
c1.category_slogan 'category_slogan',
c1.category_pic 'category_pic',
c1.category_bg_color 'category_bg_color',

c2.category_id 'category_id2',
c2.category_name 'category_name2',
c2.category_level 'category_leve2',
c2.parent_id 'parent_id2',




c3.category_id 'category_id3',
c3.category_name 'category_name3',
c3.category_level 'category_leve3',
c3.parent_id 'parent_id3'

from category c1
left join category c2 on c2.parent_id=c1.category_id
left join category c3 on c3.parent_id=c2.category_id
where c1.category_level=1

select *from category c1
  inner join category c2 on c2.parent_id=c1.category_id
  left join category c3 on c3.parent_id=c2.category_id
   where c1.category_level=1
 
--根據父級分類的parent_id進行查詢 1 級 parent_id=0
select *from category where parent_id=0,
  • 創建用于封裝查詢的類別資訊CategoryVO

    在Beans模塊中entity包下面創建一個CategoryVO物體類用于封裝Category和前端 進行資料的回應,相對于Category多了這個屬性

    //物體類中實作當前分類的子分類
    private List<CategoryVO> categories;
    
            public List<CategoryVO> getCategories() {
                return categories;
            }
    
            public void setCategories(List<CategoryVO> categories) {
                this.categories = categories;
            } 
    
  • 在CategoryMapper中定義一個函式

    package com.qfedu.fmmall.dao;
    
    import com.qfedu.fmmall.entity.Category;
    import com.qfedu.fmmall.entity.CategoryVO;
    import com.qfedu.fmmall.general.GeneralDao;
    
    import java.util.List;
    
    public interface CategoryMapper extends GeneralDao<Category> {
    //使用連接查詢實作分類串列查詢
        public List<CategoryVO> selectAllCategories();
        
        
        //    子查詢
        public List<CategoryVO> selectAllCategories2(int parentId);
    }
    
  • 映射檔案配置

    <?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.CategoryMapper">
      <resultMap id="BaseResultMap" type="com.qfedu.fmmall.entity.Category">
        <!--
          WARNING - @mbg.generated
        -->
        <id column="category_id" jdbcType="VARCHAR" property="categoryId" />
        <result column="category_name" jdbcType="VARCHAR" property="categoryName" />
        <result column="category_level" jdbcType="INTEGER" property="categoryLevel" />
        <result column="parent_id" jdbcType="INTEGER" property="parentId" />
        <result column="category_icon" jdbcType="VARCHAR" property="categoryIcon" />
        <result column="category_slogan" jdbcType="VARCHAR" property="categorySlogan" />
        <result column="category_bg_color" jdbcType="VARCHAR" property="categoryBgColor" />
      </resultMap>
    
    
    
      <resultMap id="CategoryVoMap" type="com.qfedu.fmmall.entity.CategoryVO">
        <!--
          WARNING - @mbg.generated
        -->
        <id column="category_id1" jdbcType="VARCHAR" property="categoryId" />
        <result column="category_name1" jdbcType="VARCHAR" property="categoryName" />
        <result column="category_level1" jdbcType="INTEGER" property="categoryLevel" />
        <result column="parent_id1" jdbcType="INTEGER" property="parentId" />
        <result column="category_icon1" jdbcType="VARCHAR" property="categoryIcon" />
        <result column="category_slogan1" jdbcType="VARCHAR" property="categorySlogan" />
        <result column="category_bg_color1" jdbcType="VARCHAR" property="categoryBgColor" />
        <collection property="categories" ofType="com.qfedu.fmmall.entity.CategoryVO">
          <id column="category_id2" jdbcType="VARCHAR" property="categoryId" />
          <result column="category_name2" jdbcType="VARCHAR" property="categoryName" />
          <result column="category_level2" jdbcType="INTEGER" property="categoryLevel" />
          <result column="parent_id2" jdbcType="INTEGER" property="parentId" />
    
         <collection property="categories" ofType="com.qfedu.fmmall.entity.CategoryVO">
    
           <id column="category_id3" jdbcType="VARCHAR" property="categoryId" />
           <result column="category_name3" jdbcType="VARCHAR" property="categoryName" />
           <result column="category_level3" jdbcType="INTEGER" property="categoryLevel" />
           <result column="parent_id3" jdbcType="INTEGER" property="parentId" />
    
    
         </collection>
        </collection>
    
      </resultMap>
    
    
    
    
    
    
    
    
    
      <select id="selectAllCategories" resultMap="CategoryVoMap">
    
    select
    
    c1.category_id 'category_id1',
    c1.category_name 'category_name',
    c1.category_level 'category_level',
    c1.parent_id 'parent_id',
    c1.category_icon 'category_icon',
    c1.category_slogan 'category_slogan',
    c1.category_pic 'category_pic',
    c1.category_bg_color 'category_bg_color',
    
    c2.category_id 'category_id2',
    c2.category_name 'category_name2',
    c2.category_level 'category_leve2',
    c2.parent_id 'parent_id2',
    
    
    
    
    c3.category_id 'category_id3',
    c3.category_name 'category_name3',
    c3.category_level 'category_leve3',
    c3.parent_id 'parent_id3'
    
    from category c1
    left join category c2 on c2.parent_id=c1.category_id
    left join category c3 on c3.parent_id=c2.category_id
    where c1.category_level=1
    
    
      </select>
        
        
       
    
    

使用子查詢實作分類串列的查詢:

```xml
    
<!--  使用子查詢實作的分類串列查詢-->
  <resultMap id="CategoryMap2" type="com.qfedu.fmmall.entity.CategoryVO">
    <!--
      WARNING - @mbg.generated
    -->
    <id column="category_id" jdbcType="VARCHAR" property="categoryId" />
    <result column="category_name" jdbcType="VARCHAR" property="categoryName" />
    <result column="category_level" jdbcType="INTEGER" property="categoryLevel" />
    <result column="parent_id" jdbcType="INTEGER" property="parentId" />
    <result column="category_icon" jdbcType="VARCHAR" property="categoryIcon" />
    <result column="category_slogan" jdbcType="VARCHAR" property="categorySlogan" />
    <result column="category_bg_color" jdbcType="VARCHAR" property="categoryBgColor" />
    <collection property="categories" column="category_id" select="com.qfedu.fmmall.dao.CategoryMapper.selectAllCategories2"/>

<!--  這里的column="category_id"將等于
//    子查詢
    public List<CategoryVO> selectAllCategories2(int parentId);里面的parentId;
-->

  </resultMap>






  <!--  使用子查詢實作的分類串列查詢-->
  <select id="selectAllCategories2" resultMap="CategoryMap2">
    select

     category_id,
category_name,
category_level,
parent_id,
category_icon,
category_slogan,
category_pic,
category_bg_color


from category where parent_id=#{parentId};
  </select>


7.2業務層實作

CategoryService

package com.qfedu.fmmall.service;

import com.qfedu.fmmall.vo.ResultVO;

public interface CategoryService {

    public ResultVO queryAllCategory();
}

CategoryServiceimpl:

package com.qfedu.fmmall.service.impl;

import com.qfedu.fmmall.dao.CategoryMapper;
import com.qfedu.fmmall.entity.CategoryVO;
import com.qfedu.fmmall.service.CategoryService;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;


@Service
public class CategoryServiceimpl implements CategoryService {
    @Resource
    private CategoryMapper categoryMapper;

    @Override
    public ResultVO queryAllCategory() {
        List<CategoryVO> categoryVOS = categoryMapper.selectAllCategories2(0);

        return new ResultVO(ResultStatus.OK,"success",categoryVOS);


    }
}

控制層實作

indexController實作:

@Autowired
    private CategoryService categoryService;


    @RequestMapping("category-list")
    @ApiOperation("商品分類查詢介面")
    public ResultVO queryAllCategory(){

        return categoryService.queryAllCategory();
    }


八、商品的推薦功能實作

8.1 流程分析

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

推薦最新上架的商品

8.2介面開發

8.2.1資料庫的實作
  • sql陳述句實作

    -- 商品推薦查詢最新上架資訊
    select *from product order by create_time desc limit 0,3;
    -- 商品圖片查詢 根據商品id查詢商品圖片
    select *from product_img where item_id=2;
    
    

    在子工程beans工程下面創建ProductVO (加上了這個屬性 private List imgs;因為一個商品包含多張表)

    package com.qfedu.fmmall.entity;
    
    import javax.persistence.Column;
    import javax.persistence.Id;
    import java.util.Date;
    import java.util.List;
    
    public class ProductVO {
        /**
         * 商品id
         */
        @Id
        @Column(name = "product_id")
        private Integer productId;
    
        /**
         * 商品名稱
         */
        @Column(name = "product_name")
        private String productName;
    
        /**
         * 商品分類id
         */
        @Column(name = "category_id")
        private Integer categoryId;
    
        /**
         * 一級分類外鍵id
         */
        @Column(name = "root_category_id")
        private Integer rootCategoryId;
    
        /**
         * 銷量
         */
        @Column(name = "sold_num")
        private Integer soldNum;
    
        /**
         * 商品狀態
         */
        @Column(name = "product_status")
        private Integer productStatus;
    
        /**
         * 商品內容
         */
        private String content;
    
        /**
         * 創建時間
         */
        @Column(name = "create_time")
        private Date createTime;
    
        /**
         * 更新時間
         */
        @Column(name = "update_time")
        private Date updateTime;
    
    
        private List<ProductImg> imgs;
    
        public List<ProductImg> getImgs() {
            return imgs;
        }
    
        public void setImgs(List<ProductImg> imgs) {
            this.imgs = imgs;
        }
    
        @Override
        public String toString() {
            return "ProductVO{" +
                    "imgs=" + imgs +
                    '}';
        }
    
        /**
         * 獲取商品id
         *
         * @return product_id - 商品id
         */
        public Integer getProductId() {
            return productId;
        }
    
        /**
         * 設定商品id
         *
         * @param productId 商品id
         */
        public void setProductId(Integer productId) {
            this.productId = productId;
        }
    
        /**
         * 獲取商品名稱
         *
         * @return product_name - 商品名稱
         */
        public String getProductName() {
            return productName;
        }
    
        /**
         * 設定商品名稱
         *
         * @param productName 商品名稱
         */
        public void setProductName(String productName) {
            this.productName = productName == null ? null : productName.trim();
        }
    
        /**
         * 獲取商品分類id
         *
         * @return category_id - 商品分類id
         */
        public Integer getCategoryId() {
            return categoryId;
        }
    
        /**
         * 設定商品分類id
         *
         * @param categoryId 商品分類id
         */
        public void setCategoryId(Integer categoryId) {
            this.categoryId = categoryId;
        }
    
        /**
         * 獲取一級分類外鍵id
         *
         * @return root_category_id - 一級分類外鍵id
         */
        public Integer getRootCategoryId() {
            return rootCategoryId;
        }
    
        /**
         * 設定一級分類外鍵id
         *
         * @param rootCategoryId 一級分類外鍵id
         */
        public void setRootCategoryId(Integer rootCategoryId) {
            this.rootCategoryId = rootCategoryId;
        }
    
        /**
         * 獲取銷量
         *
         * @return sold_num - 銷量
         */
        public Integer getSoldNum() {
            return soldNum;
        }
    
        /**
         * 設定銷量
         *
         * @param soldNum 銷量
         */
        public void setSoldNum(Integer soldNum) {
            this.soldNum = soldNum;
        }
    
        /**
         * 獲取商品狀態
         *
         * @return product_status - 商品狀態
         */
        public Integer getProductStatus() {
            return productStatus;
        }
    
        /**
         * 設定商品狀態
         *
         * @param productStatus 商品狀態
         */
        public void setProductStatus(Integer productStatus) {
            this.productStatus = productStatus;
        }
    
        /**
         * 獲取商品內容
         *
         * @return content - 商品內容
         */
        public String getContent() {
            return content;
        }
    
        /**
         * 設定商品內容
         *
         * @param content 商品內容
         */
        public void setContent(String content) {
            this.content = content == null ? null : content.trim();
        }
    
        /**
         * 獲取創建時間
         *
         * @return create_time - 創建時間
         */
        public Date getCreateTime() {
            return createTime;
        }
    
        /**
         * 設定創建時間
         *
         * @param createTime 創建時間
         */
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    
        /**
         * 獲取更新時間
         *
         * @return update_time - 更新時間
         */
        public Date getUpdateTime() {
            return updateTime;
        }
    
        /**
         * 設定更新時間
         *
         * @param updateTime 更新時間
         */
        public void setUpdateTime(Date updateTime) {
            this.updateTime = updateTime;
        }
    }
    

    ProductMapper檔案:

    package com.qfedu.fmmall.dao;
    
    import com.qfedu.fmmall.entity.Product;
    import com.qfedu.fmmall.entity.ProductVO;
    import com.qfedu.fmmall.general.GeneralDao;
    
    import java.util.List;
    
    public interface ProductMapper extends GeneralDao<Product> {
    //    查詢推薦商品資訊
        public List<ProductVO> selectRecommendProducts();
    }
    

    ProductImgMapper檔案:

    package com.qfedu.fmmall.dao;
    
    import com.qfedu.fmmall.entity.ProductImg;
    import com.qfedu.fmmall.general.GeneralDao;
    
    import java.util.List;
    
    public interface ProductImgMapper extends GeneralDao<ProductImg> {
        public List<ProductImg> selectProductImgByProductId(int productId);
    }
    

    ProductMapper.xml檔案實作

    注意一下子查詢 的陳述句:

     <collection property="imgs" column="product_id"
                    select="com.qfedu.fmmall.dao.ProductImgMapper.selectProductImgByProductId"></collection>
    
    <?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.ProductMapper">
      <resultMap id="BaseResultMap" type="com.qfedu.fmmall.entity.Product">
        <!--
          WARNING - @mbg.generated
        -->
        <id column="product_id" jdbcType="INTEGER" property="productId" />
        <result column="product_name" jdbcType="VARCHAR" property="productName" />
        <result column="category_id" jdbcType="INTEGER" property="categoryId" />
        <result column="root_category_id" jdbcType="INTEGER" property="rootCategoryId" />
        <result column="sold_num" jdbcType="INTEGER" property="soldNum" />
        <result column="product_status" jdbcType="INTEGER" property="productStatus" />
        <result column="content" jdbcType="VARCHAR" property="content" />
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
      </resultMap>
    
      <resultMap id="ProductVoMap" type="com.qfedu.fmmall.entity.ProductVO">
        <!--
          WARNING - @mbg.generated
        -->
        <id column="product_id" jdbcType="INTEGER" property="productId" />
        <result column="product_name" jdbcType="VARCHAR" property="productName" />
        <result column="category_id" jdbcType="INTEGER" property="categoryId" />
        <result column="root_category_id" jdbcType="INTEGER" property="rootCategoryId" />
        <result column="sold_num" jdbcType="INTEGER" property="soldNum" />
        <result column="product_status" jdbcType="INTEGER" property="productStatus" />
        <result column="content" jdbcType="VARCHAR" property="content" />
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
        <collection property="imgs" column="product_id"
                    select="com.qfedu.fmmall.dao.ProductImgMapper.selectProductImgByProductId"></collection>
      </resultMap>
    
    
      <select id="selectRecommendProducts" resultMap="ProductVoMap">
    
    
    select
    product_id,
    product_name,
    category_id,
    root_category_id,
    sold_num,
    product_status,
    content,
    create_time,
    update_time
    
    
    from product order by create_time desc limit 0,3;
    
    
      </select>
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    </mapper>
    

    8.2.2業務層實作

    package com.qfedu.fmmall.service;
    
    import com.qfedu.fmmall.entity.ProductVO;
    import com.qfedu.fmmall.vo.ResultVO;
    
    import java.util.List;
    
    public interface ProductService {
        public ResultVO selectRecommendProducts();
    
    }
    
    

    8.2.3控制層實作

     @ApiOperation("商品推薦查詢資訊介面")
        @RequestMapping(value = "https://www.cnblogs.com/list-recommends",method = RequestMethod.GET)
        public ResultVO selectProductRecommend(){
            ResultVO resultVO = productService.selectRecommendProducts();
            return resultVO;
    
    
        }
    
    

九、商品詳情顯示(在Introduction.html進行相關的顯示)

點擊商品推薦,商品輪播圖,商品的串列頁面點擊商品,就會進入到商品的詳情頁面,

  1. 獲取商品id
  2. 可以查詢商品的詳情資訊(商品的基本資訊,商品套餐,商品圖片資訊,)
  3. 將商品引數回傳給前端

9.1介面實作

9.1.1 商品詳情介面

商品基本資訊(product),商品套餐(sku),商品圖片(product_img)

  • SQL

    -- 根據商品id查詢商品詳情
    select *from product where product_id=3;
    -- 根據商品id查詢商品圖片詳情
    select *from product_img where item_id=3;
    -- 根據商品id查詢當前商品的套餐
    select *from product_sku where product_id=3;
    
  • 可以用子查詢實作這個相關的操作

  • dao介面實作(通過product,product_img,product_sku三張表獲取商品的詳情資訊)

    @Repository
    public interface ProductMapper extends GeneralDao<Product> {
    //    查詢推薦商品資訊
        public List<ProductVO> selectRecommendProducts();
    }
    
    
    package com.qfedu.fmmall.dao;
    
    import com.qfedu.fmmall.entity.ProductImg;
    import com.qfedu.fmmall.general.GeneralDao;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    @Repository
    public interface ProductImgMapper extends GeneralDao<ProductImg> {
        public List<ProductImg> selectProductImgByProductId(int productId);
    }
    
    package com.qfedu.fmmall.dao;
    
    import com.qfedu.fmmall.entity.ProductSku;
    import com.qfedu.fmmall.general.GeneralDao;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface ProductSkuMapper extends GeneralDao<ProductSku> {
    }
    
    
  • 業務層實作

//這里為不需要事務,但是如果某些事務如果呼叫了我也加入到事務中來
//    事務默認的隔離級別是可重復讀 repeateable read
    @Transactional(propagation = Propagation.SUPPORTS)
    public ResultVO selectProductBasicInfo(String productId) {
//      1.查詢商品的基本資訊



        Example example = new Example(Product.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("productId",productId);
        criteria.andEqualTo("productStatus",1);

        List<Product> products = productMapper.selectByExample(example);
//        System.out.println(products);


        if(products.size()>0){
            //      2.查詢商品的圖片資訊
           Example example1 = new Example(ProductImg.class);
            Example.Criteria criteria1 = example1.createCriteria();
            criteria1.andEqualTo("itmeId",productId);
            List<ProductImg> productImgs = productImgMapperMapper.selectByExample(example1);
//            System.out.println(productImgs);


            //        3.查詢商品的套餐資訊

            Example example2 = new Example(ProductSku.class);
            Example.Criteria criteria2 = example2.createCriteria();
            criteria2.andEqualTo("productId",productId);
            criteria2.andEqualTo("status",1);
            List<ProductSku> productSkus = productSkuMapper.selectByExample(example2);
//            System.out.println(productSkus);


//            把所有的商品的詳情資訊放入HashMap當中進行使用
            HashMap<String,Object> basicInfo=new HashMap<>();
            basicInfo.put("product",products.get(0));
            basicInfo.put("productImgs",productImgs);
            basicInfo.put("productSkus",productSkus);

            return new ResultVO(ResultStatus.OK,"success",basicInfo);





        }else {

            new ResultVO(ResultStatus.NO,"查詢商品基本資訊失敗",null);
        }
        return null;
    }
  • 控制層實作(這邊把商品的詳情的資訊放到了ResultVO的Object中)
//    商品詳情查詢

    @RequestMapping(value = "https://www.cnblogs.com/detail/{pid}",method = RequestMethod.GET)
    public ResultVO getProductBasicInfo(@PathVariable("pid") String productId){

        ResultVO resultVO = productService.selectProductBasicInfo(productId);
//        System.out.println(resultVO);

        return resultVO;

    }



十、顯示商品評價的資訊(通過用戶和商品評論表進行相關的連表查詢)

-- 根據評論的id查詢評論資訊,關聯用戶表查詢用戶資訊
select u.username,u.user_img,c.* from product_comments c
inner join users u 
on c.user_id=u.user_id
where c.product_id=3

10.1 新建的VO,ProductCommentsVO (一對一的連表查詢可以不用在物體類中宣告另一個物體類)

package com.qfedu.fmmall.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Table;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductCommentsVO {


    private Integer productId;
    private String productName;
    private Integer orderItemId;

    private String isannonymouns;
    private Integer commType;
    private Integer commLevel;
    private String commImgs;
    private String sepcName;
    private Integer replyStatus;
    private String replyContent;
    private Date replyTime;
    private Integer isShow;


//用于封裝評論對應的用戶資料
    private Integer userId;
    private String username;
    private String nickname;
    private String userImg;


}

在Mapper定義相應的介面:

package com.qfedu.fmmall.dao;

import com.qfedu.fmmall.entity.ProductComments;
import com.qfedu.fmmall.entity.ProductCommentsVO;
import com.qfedu.fmmall.general.GeneralDao;
import org.springframework.stereotype.Repository;

import java.util.List;


@Repository
public interface ProductCommentsMapper extends GeneralDao<ProductComments> {

    public List<ProductCommentsVO> selectCommentsByProductId(int productId);
}

十一、添加購物車的功能實作

10.1流程分析:

點擊添加購物車---------商品、選擇套餐id,套餐屬性,數量,token-------------進行token的校驗

10.2資料庫的相關的操作

  1. 增加欄位sku_props

    表生成之后 用逆向工程重新生成shopping_cart表的相關的結構,修改generalConfig.xml把%修改成shopping_cart

    注意一下%表示生成所有的表

    <table tableName="shopping_cart"></table>
    

10.2.1 購買的數量的前端實作在vue的methods中添加+和-的點擊事件

	changeNum:function(m){
						if(m==-1 && this.num>1){
						this.num=this.num-1;

						}else if(m==1 && this.num<this.productSkus[this.currentSkuIndex].stock){
							this.num=parseInt(this.num)   +1;


						}


					},

進行商品數量的系結可以用 v-model="num"進行雙向系結

<dd>
															<input id="min"   type="button" value="https://www.cnblogs.com/smallcutemonkey/p/-" @click="changeNum(-1)"/>
															<input id="text_box"  type="text" v-model="num" style="width:30px;" />
															<input id="add"   type="button" value="https://www.cnblogs.com/smallcutemonkey/p/+" @click="changeNum(1)" />
															<span id="stock1" >庫存<span >{{productSkus[currentSkuIndex].stock}}</span>件</span>
														</dd>

10.2.2給加入購物車這個按鈕添加點擊事件

<li>
								<div >
									<a id="LikBasket" title="加入購物車" href="" @click="addShopCart()"><i></i>加入購物車</a>
								</div>
							</li>

把相關的添加的購物車的資訊放入cart這個類中:

					addShopCart(){
					var uid=getCookieValue("userId");


						var propStr="";
						// 套餐屬性轉換成字串
						for(var key in this.chooseskuProps){
							propStr+=key+":"+this.chooseskuProps[key]+";";
}


						var cart={
									
									"cartNum": this.num,
									"cartTime": "",
									"productId": this.productId,
									"productPrice": this.productSkus[this.currentSkuIndex].sellPrice,
									"skuId": this.productSkus.skuId,
									"skuProps":propStr,
									"userId": uid
								};

						//從cookie中獲取token

						var token=getCookieValue("token");
						console.log("---token-------");
						console.log(token);

						// 把購物車的資訊放入資料庫中
						var url5=baesUrl+"shopcart/add";
						axios.post(
							{
								url:url5,
								methods:"post",
								headers:{
									token:token
								},
								data:cart
}


						).then( res=>{

							console.log("------res-----"+res);



						}

						);
					 


					}

十二、添加購物車時候用戶未登錄

12.1 添加購物車用戶未登錄,業務處理方式:

  1. 查詢商品詳情頁面的時候,就提示先登錄,跳轉到登錄頁面
  2. 當點擊添加購物車,彈窗顯示先登錄,完成登錄,點擊添加購物車
  3. 點擊添加購物車,會跳轉到登錄頁面,登錄完成之后會跳轉到商品詳情頁面,

12.2我們使用第三種難度最大的來

12.3使用Layui進行添加購物車成功/失敗的提示

  • 引入lay-ui cdn

    <!-- 引入 layui.css -->
    <link rel="stylesheet" href="https://www.cnblogs.com//unpkg.com/[email protected]/dist/css/layui.css">
     
    <!-- 引入 layui.js -->
    <script src="https://www.cnblogs.com//unpkg.com/[email protected]/dist/layui.js">
          
    
    12.3.1宣告layui的彈窗組件

    12.3.2成功失敗進行提示

十三購物車的串列

流程圖:

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

步驟

  1. 獲取用戶user_id
  2. 通過user_id獲取購物車的資訊(包括商品的名字,商品圖片的資訊)
  3. 將購物車資訊資料回傳給前端 ,
  4. 也就是有三張表,購物車表(shopping_cart),商品表(product),商品圖片表(product_img 根據商品id查詢商品主圖)

13.1資料庫dao介面的實作

  1. sql陳述句

    select  c.*,p.product_name,i.url from shopping_cart c
    inner join product p
    inner join product_img i
    on c.product_id=p.product_id 
    and i.item_id=p.product_id
    where user_id=2 and i.is_main=1;
    
   
2. dao介面

  ```java
    List<ShoppingCartVO>  selectShoppingCartByUserId(int userid);

13.2pojo介面實作

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

注意一下資料庫的shopping_cart表不需要加上這兩個欄位,是通過product_img表和product表的column屬性來進行關聯的

13.3修改購物車

13.31通過這個進行購物車數量的修改:
13.32changNum函式進行實作:
	
           methods:{
			   changeNum(event){
				   var oper=event.srcElement.dataset.oper;

				   var index=event.srcElement.dataset.id;
				   console.log(oper);
				   if(oper=="+"){
					  
						this.shoppingCartsSC[index].cartNum=parseInt(this.shoppingCartsSC[index].cartNum) +1;
					   

				   }else{

					if(this.shoppingCartsSC[index].cartNum>1){
					this.shoppingCartsSC[index].cartNum=parseInt(this.shoppingCartsSC[index].cartNum)-1;
  					}
					

				   }
				   //   修改的cartId和cartNum
					var cartId=this.shoppingCartsSC[index].cartId;
					var cartNum=this.shoppingCartsSC[index].cartNum;
					var url1=baseUrl+"shopcart/update/"+cartId+"/"+cartNum;
					axios({
						url:url1,
						method:"put",
						params:{
							token:this.token
						}

					}).then((res)=>{

						console.log(res);

})



			   },

// 			addNum:function(event){
// 				// 這個可以列印系結的id的值
// 				console.log("--add"+event.srcElement.dataset.id);
// 			    var index=event.srcElement.dataset.id;
// 				this.shoppingCartsSC[index].cartNum=parseInt(this.shoppingCartsSC[index].cartNum) +1;

				
				
// 			},
			
// 			mulNum:function(event){
			
// 			    var index=event.srcElement.dataset.id;
// 				if(this.shoppingCartsSC[index].cartNum>1){
// 					this.shoppingCartsSC[index].cartNum=parseInt(this.shoppingCartsSC[index].cartNum)-1;
//   }
				
				
				
// 			}



		   }

十四購物車提交訂單結算功能實作

14.1實作流程分析

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

十五、訂單提交及支付流程

15.1流程分析

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

15.2訂單添加介面實作

15.3資料庫操作

  • 根據識訓id獲取識訓的地址資訊(tkmapper)
  • 根據購物車ID,查詢購物車詳情(需要關聯查詢商品名稱,sku名稱,庫存,商品圖片,商品價格)----》 獲取生成商品快照的資料 只需在ShoppingCartVO中多加上一個stock欄位就好,然后在ShoppCartMapper.xml加上需要查詢的這個欄位
  • 保存訂單資訊(tkMapper)
  • 修改庫存(tkMapper)
  • 保存商品快照(tkMapper)

15.4serviceimpl層實作 注意:這個方法需要加上@Transactional,也就是訂單生成的時候,快照也必須生成

  1. 生成OrderId的方法 UUID.random().toString()
  2. 通過時間戳生成System.currentTimeMillis()+(new Random().nextInt(9999)+100)+""
package com.qfedu.fmmall.service.impl;

import com.qfedu.fmmall.dao.OrdersItemMapper;
import com.qfedu.fmmall.dao.OrdersMapper;
import com.qfedu.fmmall.dao.ProductSkuMapper;
import com.qfedu.fmmall.dao.ShoppingCartMapper;
import com.qfedu.fmmall.entity.Orders;
import com.qfedu.fmmall.entity.OrdersItem;
import com.qfedu.fmmall.entity.ProductSku;
import com.qfedu.fmmall.entity.ShoppingCartVO;
import com.qfedu.fmmall.service.OrderService;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLException;
import java.util.*;

import static java.math.BigDecimal.*;

@Service

public class OrderServiceimpl implements OrderService{

    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrdersItemMapper ordersItemMapper;
    @Autowired
    private ProductSkuMapper productSkuMapper;
    /* userId 1(zhangsan) 3(houzhicong)
    *cids  "39,40,41"
    * @return
    *
    * */

//    int userId, String receiverName,
//    String receiverMobile,String address,
//    double price,int payType,String orderRemark   把這些用Orders物件來接收


//    保存訂單的步驟
//    1.查詢選中購買的購物車詳情
//    2. 校驗庫存
//    3.保存訂單
//    4.保存訂單快照
//    5.購買成功需要洗掉購物車記錄
//    可以知道這四個步驟需要同時成功或者同時失敗,符合一個事務的操作(ACID)
    @Transactional
    public Map<String,String> addOrder(List<Integer> cids, Orders orders) throws  SQLException{
         Map<String,String> map=new HashMap<>();
//        根據cids查詢購物車的詳情記錄(包括庫存)
        List<ShoppingCartVO> shoppingCartVOList = shoppingCartMapper.selectShoppingcartByids(cids);


//        校驗庫存
        boolean f=true;

        String untitled="";
        for (ShoppingCartVO sc :shoppingCartVOList
                ) {
            if(Integer.valueOf(sc.getCartNum())>sc.getStock()){
                f=false;

            }

//            獲取所有的商品名稱,以,分割拼接成字串
            untitled=untitled+sc.getProductName()+",";

        }
        if(f){
//            表示庫存充足進行保存
//            1.userId  2 untitled名稱 3 收件人地址,姓名,電話,地址
//            4. 總價格 5.支付方式
//            6.創建 訂單的時間
//            7.訂單初始狀態 1 待支付
        orders.setStatus(1);
        orders.setUntitled(untitled);
        orders.setCreateTime(new Date());
        orders.setCancelTime(new Date());
        orders.setDeliveryTime(new Date());

//        生成訂單編號
            String orderId = UUID.randomUUID().toString().replace("-", "");
            orders.setOrderId(orderId);


//            保存訂單
            int i=ordersMapper.insert(orders);
            if(i>0){


//               ordersItem 生成商品快照
//                List<OrdersItem> ordersItemList=new ArrayList<>();
                for (ShoppingCartVO sc :shoppingCartVOList) {
//                    生成訂單的編號

                    int cnum=Integer.valueOf(sc.getCartNum());
                  String itemid=System.currentTimeMillis()+(new Random().nextInt(9999)+100)+"";
                    String itemid1 = itemid.substring(1, 10);


//                 注意一下double需要轉換為Bigdecimal型別


//                public OrdersItem(Integer orderId, Integer productId,
//                String productName,
//                String productImg, Integer skuId, String skuName,
//                BigDecimal productPrice, Integer buyCounts,
//                BigDecimal totalAmount, Date basketDate, Date buyTime,
//                Integer isComment)
                int itemid2=Integer.parseInt(itemid1);
                OrdersItem ordersItem=  new OrdersItem();
                ordersItem.setOrderId(itemid2);
                ordersItem.setProductId(Integer.valueOf(sc.getProductId()));
                ordersItem.setProductName(sc.getProductName());
                ordersItem.setProductImg(sc.getProductImg());
                ordersItem.setSkuId(Integer.valueOf(sc.getSkuId()));
                    System.out.println(sc.getSkuName());
                    ordersItem.setSkuName(sc.getSkuName());
                System.out.println(sc.getSellPrice());
                ordersItem.setProductPrice(new BigDecimal(String.valueOf(sc.getProductPrice())));

                ordersItem.setBuyCounts(cnum);
                ordersItem.setTotalAmount(sc.getProductPrice());
                ordersItem.setBasketDate(new Date());
                ordersItem.setBuyTime(new Date());
                ordersItem.setIsComment(0);

//                ordersItemList.add(ordersItem);
                      int m=ordersItemMapper.insert(ordersItem);

                    }

//                int j = ordersItemMapper.insertList(ordersItemList);
//  扣減庫存???
//                根據套餐Id修改庫存量
                for (ShoppingCartVO sc :shoppingCartVOList
                ) {
                    String skuId = sc.getSkuId();
                    int newStock=sc.getStock()-Integer.valueOf(sc.getCartNum());

//                    Example example = new Example(ProductSku.class);
//                    Example.Criteria criteria = example.createCriteria();
//                    criteria.andEqualTo("skuId",skuId);


//                    ProductSku productSku = productSkuMapper.selectByPrimaryKey(skuId);
                    ProductSku productSku=new ProductSku();
                    productSku.setSkuId(skuId);
                    productSku.setStock(String.valueOf(newStock));
//                    productSku.setSkuImg(null);

                    productSkuMapper.updateByPrimaryKeySelective(productSku);

                }

//  保存訂單成功 洗掉購物車記錄
                for (Integer cid:cids
                     ) {
                    shoppingCartMapper.deleteByPrimaryKey(cid);

                }

                 map.put("orderId",orderId);
                 map.put("productNames",untitled);

              return   map;


            }



        }else{
//            不足
   return null;

        }

        return null;
    }
}

swagger報錯解決

For input String :""

在application.yml加上日志的配置:

logging:
  level:
    io.swagger.models.parameters.AbstractSerializableParameter: error

十六 商品個人中心訂單資訊的查詢

16.1 流程分析

  1. 根據用戶id進行訂單資訊的查詢
  2. 可以關聯進行查詢訂單快照

sql陳述句

    <select id="selectOrders" resultMap="OrdertMap1">
        select o.order_id,
        o.user_id,
        o.untitled,
        o.receiver_name,
        o.receiver_mobile,
        o.receiver_address,
        o.total_amount,
        o.actual_amount,
        o.pay_type,
        o.order_remark,
        o.status,
        o.delivery_type,
        o.delivery_flow_id,
        o.order_freight,
        o.delete_status,
        o.create_time,
        o.update_time,
        o.pay_time,
        o.delivery_time,
        o.finish_time,
        o.cancel_time,
        o.close_type




        from orders o

        where o.user_id=#{userId}
        <if test="status!=null">

            and o.status=#{status}
        </if>
        limit #{start},#{limit}
    </select>


OrderMapper.xml檔案:


    <resultMap id="OrdertMap1" type="com.qfedu.fmmall.entity.OrdersVO">
        <!--
          WARNING - @mbg.generated
        -->
        <result column="order_id" jdbcType="VARCHAR" property="orderId" />
        <result column="user_id" jdbcType="VARCHAR" property="userId" />
        <result column="untitled" jdbcType="VARCHAR" property="untitled" />
        <result column="receiver_name" jdbcType="VARCHAR" property="receiverName" />
        <result column="receiver_mobile" jdbcType="VARCHAR" property="receiverMobile" />
        <result column="receiver_address" jdbcType="VARCHAR" property="receiverAddress" />
        <result column="total_amount" jdbcType="DECIMAL" property="totalAmount" />
        <result column="actual_amount" jdbcType="DECIMAL" property="actualAmount" />
        <result column="pay_type" jdbcType="VARCHAR" property="payType" />
        <result column="order_remark" jdbcType="VARCHAR" property="orderRemark" />
        <result column="status" jdbcType="INTEGER" property="status" />
        <result column="delivery_type" jdbcType="VARCHAR" property="deliveryType" />
        <result column="delivery_flow_id" jdbcType="VARCHAR" property="deliveryFlowId" />
        <result column="order_freight" jdbcType="DECIMAL" property="orderFreight" />
        <result column="delete_status" jdbcType="INTEGER" property="deleteStatus" />
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
        <result column="pay_time" jdbcType="TIMESTAMP" property="payTime" />
        <result column="delivery_time" jdbcType="TIMESTAMP" property="deliveryTime" />
        <result column="finish_time" jdbcType="TIMESTAMP" property="finishTime" />
        <result column="cancel_time" jdbcType="TIMESTAMP" property="cancelTime" />
        <result column="close_type" jdbcType="INTEGER" property="closeType" />


<!--        子查詢實作 根據OrdersVO的orderId進行子查詢-->
        <collection column="ordersItems" property="order_id" select="com.qfedu.fmmall.dao.OrdersItemMapper.selectOrderItemsByOrderId"/>
    </resultMap>

    <select id="selectOrders" resultMap="OrdertMap1">
        select o.order_id,
        o.user_id,
        o.untitled,
        o.receiver_name,
        o.receiver_mobile,
        o.receiver_address,
        o.total_amount,
        o.actual_amount,
        o.pay_type,
        o.order_remark,
        o.status,
        o.delivery_type,
        o.delivery_flow_id,
        o.order_freight,
        o.delete_status,
        o.create_time,
        o.update_time,
        o.pay_time,
        o.delivery_time,
        o.finish_time,
        o.cancel_time,
        o.close_type




        from orders o

        where o.user_id=#{userId}
        <if test="status!=null">

            and o.status=#{status}
        </if>
        limit #{start},#{limit}
    </select>

16.2 介面開發

package com.qfedu.fmmall.dao;

import com.qfedu.fmmall.entity.Orders;
import com.qfedu.fmmall.entity.OrdersVO;
import com.qfedu.fmmall.general.GeneralDao;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface OrdersMapper extends GeneralDao<Orders> {
    List<OrdersVO> selectOrders(@Param("userId") String userId,
                               @Param("status") String status,
                                @Param("start")int start,
                                @Param("limit")int limit);
}

16.2.1 Service層介面開發

  @Override
    public ResultVO selectOrders(String userId, String status, int pageNum, int limit) {
   int start=(pageNum-1)*limit;
        List<OrdersVO> ordersVOS = ordersMapper.selectOrders(userId, status, pageNum, limit);
//   2.查詢總記錄數
        Example example = new Example(Orders.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLike("userId",userId);
        if(status!=null&&!"".equals(status)){
            criteria.andLike("status",status);
        }
//        2.查詢總記錄數
        int count=ordersMapper.selectCountByExample(example);
//        查詢總頁數
        int pageCount=count%limit==0?count/limit:count/limit+1;

//        3.封裝資料
        PageHelper<OrdersVO> ordersVOPageHelper = new PageHelper<>(count, pageCount, ordersVOS);


        return new ResultVO(ResultStatus.OK,"訂單查詢成功",ordersVOPageHelper);
    }

16.2.2 Controller層實作

package com.qfedu.fmmall.controller;

import com.github.wxpay.sdk.WXPay;
import com.qfedu.fmmall.config.MyPayConfig;
import com.qfedu.fmmall.entity.Orders;
import com.qfedu.fmmall.service.OrderService;
import com.qfedu.fmmall.vo.ResultStatus;
import com.qfedu.fmmall.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@CrossOrigin
@RequestMapping("/order")
@Api(value = "https://www.cnblogs.com/smallcutemonkey/p/提供訂單相關的介面",tags = "訂單管理")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @PostMapping("/add/{cids}")
    public ResultVO add(@PathVariable("cids") List<Integer> cids,
                        @RequestBody Orders orders){

        ResultVO resultVO=null;

//        測驗用的OrderId
        try {
            Map<String, String> orderInfo = orderService.addOrder(cids, orders);
            String orderId=orderInfo.get("orderId");


//           訂單快照創建成功,申請支付鏈接

            HashMap<String,String> data=https://www.cnblogs.com/smallcutemonkey/p/new HashMap<>();
//            設定當前訂單資訊
            data.put("body",orderInfo.get("productNames")); //商品描述
            data.put("out_trade_no",orderId);//使用當前用戶訂單編號作為當前支付交易的交易編號
            data.put("fee_type","CNY"); //支付幣種
            data.put("total_fee", orders.getActualAmount()+""); //支付金額
            data.put("trade_type","NATIVE");//交易型別

//            必填選項   用于設定支付完成時的回呼方法介面
            data.put("notify_url","/pay/success");
            WXPay wxPay=new WXPay(new MyPayConfig());
            Map<String, String> resp = wxPay.unifiedOrder(data);

//            把微信支付平臺生成的鏈接獲取到
            orderInfo.put("payUrl",resp.get("code_url"));
            resultVO=new ResultVO(ResultStatus.OK,"提交訂單成功!",orderInfo);
            System.out.println(resp);

//            code_url -> weixin://wxpay/bizpayurl?pr=Iv5Fsq6zz
        } catch (SQLException e) {

            resultVO= new ResultVO(ResultStatus.NO,"下單失敗",null);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultVO;
    }



//    訂單分頁查詢
@RequestMapping(value = "https://www.cnblogs.com/list",method = RequestMethod.GET)

@ApiImplicitParams({
        @ApiImplicitParam(dataType = "string",name = "userId",value = "https://www.cnblogs.com/smallcutemonkey/p/用戶Id",required = true),
        @ApiImplicitParam(dataType = "string",name = "status",value = "https://www.cnblogs.com/smallcutemonkey/p/訂單狀態",required = false),
        @ApiImplicitParam(dataType = "int",name = "pageNum",value = "https://www.cnblogs.com/smallcutemonkey/p/當前頁數",required = true),
        @ApiImplicitParam(dataType = "int",name = "limit",value = "https://www.cnblogs.com/smallcutemonkey/p/頁數大小",required = false),
})
public ResultVO selectOrders(@RequestHeader("token")String token, String userId, String status, int pageNum, int limit) {
    ResultVO resultVO = orderService.selectOrders(userId, status, pageNum, limit);

    return  resultVO;
 }

}

16.2.3前端使用Vue+ElementUI實作分頁功能

1. 引入cdn

   <!-- 引入樣式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">

	<script src="https://www.cnblogs.com/smallcutemonkey/p/static/js/cookie_utils.js"></script>
		<!-- element-ui需要引入vue.js -->
		<script src="https://www.cnblogs.com/smallcutemonkey/p/static/js/vue.min.js"></script>
		<!-- 引入組件庫 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
		<script src="https://www.cnblogs.com/smallcutemonkey/p/static/js/axios.min.js"></script>
		<script src="https://www.cnblogs.com/smallcutemonkey/p/static/js/utils.js"></script>



2. data中定義相關資料


		<script type="text/javascript">
			var baseUrl="http://localhost:8080/";
      var vm=new Vue({
		el:"#app",
		data:{
			token:"",
			username:"",
			pageNum:1,
			limit:6,
			userId:"",
			orders:[],
			count:0,
			status:null,
			

		},
		created(){
		 this.token=getCookieValue("token");
		 this.userId=getCookieValue("userId");

		 this.username=getCookieValue("username");

		//  加載頁面,請求訂單資訊
		var url1=baseUrl+"order/list";
		axios({
			url:url1,
			method:"get",
			headers:{
				token:this.token
			},
			params:{
				userId:this.userId,
				pageNum:this.pageNum,
				limit:this.limit
			}

		}).then((res)=>{
			console.log(res.data);
			if(res.data.code==1){

				this.orders=res.data.data.data;
				console.log(this.orders);
				this.count=res.data.data.count;

			}
		});

	
		},
		methods: {
			// 通過訂單狀態進行查詢
			queryByStatus(status){

			this.status=status;
			console.log(this.status);

// 重新按照狀態查詢一次



								//  加載頁面,請求訂單資訊
		var url1=baseUrl+"order/list";
		axios({
			url:url1,
			method:"get",
			headers:{
				token:this.token
			},
			params:{
				userId:this.userId,
				pageNum:this.pageNum,
				limit:this.limit,
				status:this.status
			}

		}).then((res)=>{
			console.log(res.data);
			if(res.data.code==1){

				this.orders=res.data.data.data;
				console.log(this.orders);
				this.count=res.data.data.count;

			}
		});
			


		},
		
		gotoComment:function(event){
			var index=event.srcElement.dataset.index;
			console.log(index);
			var order=this.orders[index];
			localStorage.setItem("order",JSON.stringify(order));
			location.href="https://www.cnblogs.com/smallcutemonkey/p/user-comment.html";
			
}
	},
		
		
 })

</script>
		



3.分頁的相關的方法

// 通過分頁進行查詢
			pager(page){
				this.pageNum=page;
				//重新加載頁面
				
				//  加載頁面,請求訂單資訊

					// -------------分頁查詢按照狀態進行查詢
			var obj={
				userId:this.userId,
				pageNum:this.pageNum,
				limit:this.limit
			};

			if(this.status!=null){
				obj.status=this.status;

			}

			// ------------
		var url1=baseUrl+"order/list";
		axios({
			url:url1,
			method:"get",
			headers:{
				token:this.token
			},
			params:obj

		}).then((res)=>{
			console.log(res.data);
			if(res.data.code==1){

				this.orders=res.data.data.data;
				console.log(this.orders);
				this.count=res.data.data.count;

			}
		});
				
				
			},
			

4. 分頁的表格

	<table >
						<tr>
							<td>序號</td>
							<td>訂單商品</td>
							<td>訂單狀態</td>
							<td>時間</td>
							<td>操作</td>
						</tr>
						<template v-for="order,index in this.orders">
						
							<tr>
								<td>{{index+1}}</td>
								<td>{{order.untitled}}</td>
								<td>
									<span v-if="order.status=='1'">待付款</span>
									<span v-else-if="order.status=='2'">待發貨</span>
									<span v-else-if="order.status=='3'">待識訓</span>
									<span v-else-if="order.status=='4'">待評價</span>
									<span v-else-if="order.status=='5'">已完成</span>
									<span v-else-if="order.status=='6'">已關閉</span>

									</td>
									
								<td>{{order.createTime}}</td>
								<td>
									<template v-if="order.status=='1'">
									<button >
											去支付

									</button >
									<button  >
											取消訂單
										</button>
									</template>
								
								
							   <template  v-if="order.status=='2'">
									<button  >
										取消訂單
									</button>
										
									</template>

							    <template v-if="order.status=='3'">
									<button >
									確認識訓

								    </button >	
								
							    </template>
									
									
									<template v-if="order.status=='4'">
										<button  @click="gotoComment" :data-index="index">
											去評價
										</button >
									</template>
							
					
								<template v-if="order.status=='6'" || v-if="order.status=='5'" >
										<button >
											洗掉
										</button >
								</template> 
								

									


								</td>
							</tr>


						</template>

						<tr>
							<td colspan="5">
								<!-- 分頁 -->
								<el-pagination
  background
  layout="prev, pager, next"
  :current-page="pageNum"
  :page-size="limit"
  :total="count" @current-change="pager">
</el-pagination>
								
							</td>
						</tr>






					</table>


Linux的常用 的命令的復習

linux中沒有盤符,根路徑用 "/"表示

rm -rf 你的目錄的名字

linux的系統結構和相關的目錄結構

bin,sbin(超級管理員的命令目錄),etc(系統組態檔),lib/lib4(系統所需的依賴庫),boot(系統啟動的相關的檔案),

目錄 說明
bin 系統檔案
sbin 超級管理員系統命令
boot 系統啟動相關的目錄
etc 系統組態檔
lib/lib4 存放系統所需的依賴庫
home 一般用戶所在的檔案夾
root 超級管理員目錄(root用戶目錄)
media 媒體(光驅)
mnt 掛載(u盤,移動硬碟)
tmp/opt 臨時的檔案存盤目錄,比如日志在tmp或者opt目錄下面
usr 用戶目錄,我們通常安裝的軟體,用戶的一些檔案都在此目錄下面
run srv sys var proc dev 系統相關目錄

ls -a #可以顯示隱藏檔案

Linux系統安裝jdk

  1. 通過SecureFx上傳你的linux版本的jdk

  2. 進行解壓tar -zxcf 你的壓縮包的名字

  3. 在/etc/profile目錄進行環境變數的配置,

    加上如下的配置:

    #JAVA_HOME
    export JAVA_HOME=/opt/module/jdk1.8.0_144
    export PATH=$PATH:$JAVA_HOME/bin
    

Linux安裝Tomcat

  1. 通過Secure在windows中上傳你的Tomcat包,

  2. 進行解壓到指定的目錄

  3. 在它的bin目錄下面進行啟動

    ./startup.sh
    
  4. 不使用了可以關閉tomcat

    lsof -i:8080
    kill -9 PID
    
    如果你的專案是部署在Tomcat上面的,你可以把你的專案打成war包,放在tomcat的weapp目錄下面,運行tomcat即可進行該專案

Linux安裝mysql(在線安裝)

通過如下的指定進行安裝:

wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm

然后使用下面指定(如果沒有權限需要su root):

 rpm -ivh mysql57-community-release-el7-10.noarch.rpm 

正式安裝mysql服務:

yum -y install mysql-community-server

報錯:

Error: Package: mysql-community-server-5.7.36-1.el7.x86_64 (mysql57-community)
Requires: systemd

使用命令看你是否安裝了MySQL

rpm -qa|grep -i mysql

已經安裝好的mysql加入開機啟動

systemctl enable mysqld

進行啟動mysql服務:

systemctl start mysqld

20.鋒迷專案的后端云部署

20.1企業專案當中需要進行修改的東西:

  1. application.yml檔案中需要改變連接的url;改成你的資料庫的服務器的ip地址,比如localhost變為你的ip地址
  2. 如果你有微信支付的回呼介面data.put("notify_url","/pay/success");,變成你的云主機的地址,

Maven中先進行clean,然后進行package進行打包的操作,在api中找到你的打包的jar包進行,

20.11在你的Linux中建立一個目錄用來存放你的jar包:

運行這個命令進行運行你的專案:

 java -jar api-2.0.1.jar

api-2.0.1.jar為你的jar包的名字,

如果報錯: no main manifest attribute, in api-2.0.1.jar

可以在你的pom.xml檔案中加上這個配置(在dependencies下面):

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.0.1.RELEASE</version>
                <configuration>
                    <mainClass>com.qfedu.fmmall.ApiApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

然后再次運行上面的命令:java -jar 你的jar包名字,

啟動成功如圖所示:

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

這樣當你ctrl+c你的服務就會停止,

使用這個指令可以使你的服務一直開著:

java -jar api-2.0.1.jar &

注意一下:你的依賴的引入不可以重復

21.前端的專案的部署在云服務器上面

我們的云主機有安裝Tomcat,可以部署在Tomcat上面:

由于上面的Tomcat8080已經啟動了,我們可以修改一下它的conf目錄下面的server.xml檔案:

cd /opt/module/apache-tomcat-8.5.73/
cd conf
#可以查出8080在server.xml的哪行
cat -n server.xml |grep 8080
#可以在server.xml中編輯69行
vim +69 server.xml

1. 修改所有的請求的localhost地址為你的云服務器的地址

2.上傳Tomcat到你的Linux的服務器中,進行解壓

3.把你的前端的專案從windows中上傳到Linux的Tomcat的webapp目錄下面,

4.到bin目錄下面進行啟動命令為:

./startup.sh

5.通過路徑進行訪問你的前端的專案,

#可以查看你的Linux的服務器的ip
ifconfig
#路徑在加上你的Tomcat的埠號9999
http://192.168.48.5:9999/fmall-static/index.html

訪問成功的截圖:

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

Tomcat作為前端專案的弊端

1.前端會有大量的請求,Tomcat的弊端(難以滿足高并發的,大約是2000-3000,使用Niginx可以提高高并發的承受,大約2萬)

  1. Tomcat的核心價值在于能夠便于執行java程式,而不是處理并發
  2. 結論:tomcat不適合部署前端專案

22.Nginx

它是一個高性能的Http和反向代理web服務器

  • Nginx是基于http協議的請求和回應(部署web專案) ---靜態資源
  • 可以作為反向代理服務器 ----負載均衡(代理服務器)

高性能體現:

  1. 穩定性好,可以7*24不間斷的運行
  2. 配置簡潔
  3. 可以承受高并發(5w+)

23.前端專案部署在Nginx上面

  1. 安裝nginx

  2. 將前端專案fmall-static拷貝到nginx的根目錄

  3. 修改nginx/conf里面的nginx.conf檔案:

    location /{
    root fmall-static;
    index index.html index.htm;
    }
    

    24.Linux安裝Nginx(在線安裝)

    24.1 安裝編譯工具(nginx安裝之前需要編譯)

    yum install -y gcc gcc-c++
    

    24.2安裝PCRE

    # 1.下載
    wget http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz
    
    # 2.解壓
    tar -zxvf pcre-8.35.tar.gz
    
    # 3.進入目錄 
    cd pre-8.35
    
    # 4.配置
    ./configure
    
    # 5.編譯安裝
    make && make install
    
    
    
    

    24.3安裝SSL庫

    cd /opt/software
    wget http://www.openssl.org/source/openssl-1.0.1j.tar.gz
    tar -zxvf openssl-1.0.1j.tar.gz
    
    # 4.配置
    ./configure
    
    # 5.編譯安裝
    make && make install
    
    

    24.4安裝zlib庫

    wget http://zlib.net/zlib-1.2.11.tar.gz
    tar -zxvf zlib-1.2.11.tar.gz  -C ../module/
    cd zlib-1.2.11/
    ./configure
    make && make install
    

    24.5下載Nginx

    可以本地上傳或者在線下載

    wget https://nginx.org/download/nginx-1.16.1.tar.gz
    cd nginx-1.16.1/
    
     ./configure --prefix=nginx-1.16.1/ --with-http_stub_status_module --with-http_ssl_module --with-pcre=../pcre-8.35/
     make && make install
    

    成功:

    Configuration summary

    • using PCRE library: ../../pcre-8.35/
    • using system OpenSSL library
    • using system zlib library

    nginx path prefix: "../../nginx-1.16.1/"
    nginx binary file: "../../nginx-1.16.1//sbin/nginx"
    nginx modules path: "../../nginx-1.16.1//modules"
    nginx configuration prefix: "../../nginx-1.16.1//conf"
    nginx configuration file: "../../nginx-1.16.1//conf/nginx.conf"
    nginx pid file: "../../nginx-1.16.1//logs/nginx.pid"
    nginx error log file: "../../nginx-1.16.1//logs/error.log"
    nginx http access log file: "../../nginx-1.16.1//logs/access.log"
    nginx http client request body temporary files: "client_body_temp"

然后make && make install以后沒有報錯出現下面的資訊:

test -d 'nginx-1.16.1//logs'
|| mkdir -p 'nginx-1.16.1//logs'
make[1]: Leaving directory `/opt/module/nginx-1.16.1'

查看成功的nginx:ll

[root@hadoop102 nginx-1.16.1]# ll
total 16
drwxr-xr-x. 2 root root 4096 Dec 25 07:10 conf
drwxr-xr-x. 2 root root 4096 Dec 25 07:10 html
drwxr-xr-x. 2 root root 4096 Dec 25 07:10 logs
drwxr-xr-x. 2 root root 4096 Dec 25 07:10 sbin

啟動nginx:

cd /opt/software/nginx-1.16.1/nginx-1.16.1/sbin
./nginx

然后報錯:

./nginx: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory

解決辦法:

find / -name *libcrypto*  

找到這個路徑:/usr/local/lib64/libcrypto.so.1.1

cd /usr/local/lib64/

查看防火墻的狀態和關閉防火墻:

#查看防火墻狀態
/etc/init.d/iptables status
#關閉防火墻
 service iptables stop
 
 #重新啟動防火墻
 service iptables restart

報錯:

error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory

解決:

ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so.1.1
ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/526782.html

標籤:Java

上一篇:給她講最愛的SpringBoot原始碼

下一篇:day08-XML

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more