主頁 >  其他 > 傳智健康day04 預約管理-套餐管理

傳智健康day04 預約管理-套餐管理

2022-01-21 07:25:11 其他

1. 圖片存盤方案

1.1 介紹

在實際開發中,我們會有很多處理不同功能的服務器,例如:

應用服務器:負責部署我們的應用

資料庫服務器:運行我們的資料庫

檔案服務器:負責存盤用戶上傳檔案的服務器

分服務器處理的目的是讓服務器各司其職,從而提高我們專案的運行效率,

常見的圖片存盤方案:

方案一:使用nginx搭建圖片服務器

方案二:使用開源的分布式檔案存盤系統,例如Fastdfs、HDFS等

方案三:使用云存盤,例如阿里云、七牛云等

1.2 七牛云存盤

七牛云(隸屬于上海七牛資訊技術有限公司)是國內領先的以視覺智能和資料智能為核心的企業級云計 算服務商,同時也是國內知名智能視頻云服務商,累計為 70 多萬家企業提供服務,覆寫了國內80%網 民,圍繞富媒體場景推出了物件存盤、融合 CDN 加速、容器云、大資料平臺、深度學習平臺等產品、 并提供一站式智能視頻云解決方案,為各行業及應用提供可持續發展的智能視頻云生態,幫助企業快速 上云,創造更廣闊的商業價值,

官網:https://www.qiniu.com/

通過七牛云官網介紹我們可以知道其提供了多種服務,我們主要使用的是七牛云提供的物件存盤服務來 存盤圖片,

1.2.1 注冊、登錄

要使用七牛云的服務,首先需要注冊成為會員,地址:https://portal.qiniu.com/signup

注冊完成后就可以使用剛剛注冊的郵箱和密碼登錄到七牛云:

登錄成功后根據提示進行實名認證,實名認證成功后點擊頁面右上角管理控制臺:

1.2.2 新建存盤空間

要進行圖片存盤,我們需要在七牛云管理控制臺新建存盤空間,點擊管理控制臺首頁物件存盤下的立即 添加按鈕,頁面跳轉到新建存盤空間頁面:

可以創建多個存盤空間,各個存盤空間是相互獨立的,

1.2.3 查看存盤空間資訊

存盤空間創建后,會在左側的空間管理串列選單中展示創建的存盤空間名稱,點擊存盤空間名稱可以查看當前存盤空間的相關資訊

1.2.4 開發者中心

可以通過七牛云提供的開發者中心學習如何操作七牛云服務,地址:https://developer.qiniu.com/

點擊物件存盤,跳轉到物件存盤開發頁面,地址:https://developer.qiniu.com/kodo

七牛云提供了多種方式操作物件存盤服務,本專案采用ava SDK方式,地址:https://developer.qiniu.com/kodo/1239/java

使用Java SDK操作七牛云需要匯入如下maven坐標:

<dependency>
  <groupId>com.qiniu</groupId>
  <artifactId>qiniu-java-sdk</artifactId>
  <version>7.7.0</version>
</dependency>

1.2.5 鑒權

Java SDK的所有的功能,都需要合法的授權,授權憑證的簽算需要七牛賬號下的一對有效的Access Key 和Secret Key,這對密鑰可以在七牛云管理控制臺的個人中心(https://portal.qiniu.com/user/key)獲得,如下圖:

1.2.6 Java SDK操作七牛云

本章節我們就需要使用七牛云提供的Java SDK完成圖片上傳和洗掉,我們可以參考官方提供的例子,

//構造一個帶指定 Region 物件的配置類
Configuration cfg = new Configuration(Region.region0());
//...其他引數參考類注釋
UploadManager uploadManager = new UploadManager(cfg);
//...生成上傳憑證,然后準備上傳
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
//如果是Windows情況下,格式是 D:\\qiniu\\test.png
String localFilePath = "/home/qiniu/test.png";
//默認不指定key的情況下,以檔案內容的hash值作為檔案名
String key = null;
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
    Response response = uploadManager.put(localFilePath, key, upToken);
    //決議上傳成功的結果
    DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
    System.out.println(putRet.key);
    System.out.println(putRet.hash);
} catch (QiniuException ex) {
    Response r = ex.response;
    System.err.println(r.toString());
    try {
        System.err.println(r.bodyString());
    } catch (QiniuException ex2) {
        //ignore
    }
}

//構造一個帶指定 Region 物件的配置類
Configuration cfg = new Configuration(Region.region0());
//...其他引數參考類注釋
String accessKey = "your access key";
String secretKey = "your secret key";
String bucket = "your bucket name";
String key = "your file key";
Auth auth = Auth.create(accessKey, secretKey);
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
    bucketManager.delete(bucket, key);
} catch (QiniuException ex) {
    //如果遇到例外,說明洗掉失敗
    System.err.println(ex.code());
    System.err.println(ex.response.toString());
}

1.2.7 封裝工具類

為了方便操作七牛云存盤服務,我們可以將官方提供的案例簡單改造成一個工具類,在我們的專案中直接使用此工具類來操作就可以:

package com.itterence.utils;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;

/**
 * 七牛云工具類
 */
public class QiniuUtils {
    public static String accessKey = "G78D_qC2JG3V9WBW9lxysK9OZeslRJtJZI85orM_";
    public static String secretKey = "-ptaWzGugFgUbFNBu8OWoSqbaTfiAPvdz9EJaLtr";
    public static String bucket = "itterence-health";

    public static void upload2Qiniu(String filePath,String fileName){
        //構造一個帶指定Zone物件的配置類
        Configuration cfg = new Configuration(Zone.zone1());
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(filePath, fileName, upToken);
            //決議上傳成功的結果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException ex) {
            Response r = ex.response;
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
    }

    //上傳檔案
    public static void upload2Qiniu(byte[] bytes, String fileName){
        //構造一個帶指定Zone物件的配置類
        Configuration cfg = new Configuration(Zone.zone1());
        //...其他引數參考類注釋
        UploadManager uploadManager = new UploadManager(cfg);

        //默認不指定key的情況下,以檔案內容的hash值作為檔案名
        String key = fileName;
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(bytes, key, upToken);
            //決議上傳成功的結果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            System.out.println(putRet.key);
            System.out.println(putRet.hash);
        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
    }

    //洗掉檔案
    public static void deleteFileFromQiniu(String fileName){
        //構造一個帶指定Zone物件的配置類
        Configuration cfg = new Configuration(Zone.zone1());
        String key = fileName;
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            bucketManager.delete(bucket, key);
        } catch (QiniuException ex) {
            //如果遇到例外,說明洗掉失敗
            System.err.println(ex.code());
            System.err.println(ex.response.toString());
        }
    }
}

注:此處我遇到了maven依賴的問題,在test目錄下import com.google.gson.Gson;沒問題,在java目錄中報紅色錯誤,提示沒有依賴,然后我查看maven工具內,這個包的狀態為runtime,這就是無法編譯問題所在

最終在父工程pom.xml中 添加了com.google.code.gson包

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
    <scope>compile</scope>
</dependency>

將此工具類放在health_common工程中,后續會使用到,

2. 新增套餐

2.1 需求分析

套餐其實就是檢查組的集合,例如有一個套餐為“入職體檢套餐”,這個體檢套餐可以包括多個檢查組:一般檢查、血常規、尿常規、肝功三項等,所以在添加套餐時需要選擇這個套餐包括的檢查組,

套餐對應的物體類為Setmeal,對應的資料表為t_setmeal,套餐和檢查組為多對多關系,所以需要中間表t_setmeal_checkgroup進行關聯,

2.2 完善頁面

套餐管理頁面對應的是setmeal.html頁面,根據產品設計的原型已經完成了頁面基本結構的撰寫,現在 需要完善頁面動態效果,

2.2.1 彈出新增視窗

頁面中已經提供了新增視窗,只是出于隱藏狀態,只需要將控制展示狀態的屬性dialogFormVisible改為true介面顯示出新增視窗,點擊新建按鈕時系結的方法為handleCreate,所以在handleCreate方法中修改dialogFormVisible屬性的值為true即可,同時為了增加用戶體驗度,需要每次點擊新建按鈕時清空表單輸入項,

由于新增套餐時還需要選擇此套餐包含的檢查組,所以新增套餐視窗分為兩部分資訊:基本資訊和檢查 組資訊,如下圖:

新建按鈕系結單擊事件,對應的處理函式為handleCreate

<el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
// 重置表單
resetForm() {
    this.formData = {};
    this.activeName='first';
    this.checkgroupIds = [];
    this.imageUrl = null;
},
// 彈出添加視窗
handleCreate() {
    this.dialogFormVisible = true;
    this.resetForm();
},

2.2.2 動態展示檢查組串列

現在雖然已經完成了新增視窗的彈出,但是在檢查組資訊標簽頁中需要動態展示所有的檢查組資訊串列資料,并且可以進行勾選,

具體操作步驟如下:

(1)定義模型資料

tableData:[],//添加表單視窗中檢查組串列資料
checkgroupIds:[],//添加表單視窗中檢查組復選框對應id

(2)動態展示檢查組串列資料,資料來源于上面定義的tableData模型資料

<table class="datatable">
    <thead>
    <tr>
        <th>選擇</th>
        <th>專案編碼</th>
        <th>專案名稱</th>
        <th>專案說明</th>
    </tr>
    </thead>
    <tbody>
    <tr v-for="c in tableData">
        <td>
            <input :id="c.id" v-model="checkgroupIds" type="checkbox" :value="c.id">
        </td>
        <td><label :for="c.id">{{c.code}}</label></td>
        <td><label :for="c.id">{{c.name}}</label></td>
        <td><label :for="c.id">{{c.remark}}</label></td>
    </tr>
    </tbody>
</table>

(3)完善handleCreate方法,發送ajax請求查詢所有檢查組資料并將結果賦值給tableData模型資料用 于頁面表格展示

// 彈出添加視窗
handleCreate() {
    this.dialogFormVisible = true;
    this.resetForm();
    axios.get("/checkgroup/findAll.do").then((res)=> {
        if(res.data.flag){
            this.tableData = res.data.data;
        }else{
            this.$message.error(res.data.message);
        }
    });
},

(4)分別在CheckGroupController、CheckGroupService、CheckGroupServiceImpl、 CheckGroupDao、CheckGroupDao.xml中擴展方法查詢所有檢查組資料

CheckGroupController:

//查詢所有
@RequestMapping("/findAll")
public Result findAll(){
    List<CheckGroup> checkGroupList = checkGroupService.findAll();
    if(checkGroupList != null && checkGroupList.size() > 0){
        Result result = new Result(true, MessageConstant.QUERY_CHECKGROUP_SUCCESS);
        result.setData(checkGroupList);
        return result;
    }
    return new Result(false,MessageConstant.QUERY_CHECKGROUP_FAIL);
}

CheckGroupService:

List<CheckGroup> findAll();

CheckGroupServiceImpl:

public List<CheckGroup> findAll() {
    return checkGroupDao.findAll();
}

CheckGroupDao:

List<CheckGroup> findAll();

CheckGroupDao.xml:

<select id="findAll" resultType="com.itterence.pojo.CheckGroup">
    select * from t_checkgroup
</select>

2.2.3 圖片上傳并預覽

此處使用的是ElementUI提供的上傳組件el-upload,提供了多種不同的上傳效果,上傳成功后可以進行預覽,

實作步驟:

(1)定義模型資料,用于后面上傳檔案的圖片預覽:

imageUrl:null,//模型資料,用于上傳圖片完成后圖片預覽

(2)定義上傳組件:

<!--
    el-upload:上傳組件
    action:上傳的提交地址
    auto-upload:選中檔案后是否自動上傳
    name:上傳檔案的名稱,服務端可以根據名稱獲得上傳的檔案物件
    show-file-list:是否顯示已上傳檔案串列
    on-success:檔案上傳成功時的鉤子
    before-upload:上傳檔案之前的鉤子
-->

<el-upload
        class="avatar-uploader"
        action="/setmeal/upload.do"
        :auto-upload="autoUpload"
        name="imgFile"
        :show-file-list="false"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload">
    <img v-if="imageUrl" :src="imageUrl" class="avatar">
    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>

(3)定義對應的鉤子函式:

//檔案上傳成功后的鉤子,response為服務端回傳的值,file為當前上傳的檔案封裝成的js物件
handleAvatarSuccess(response, file) {
    //為模型資料imageUrl賦值,用于頁面圖片預覽
    this.imageUrl = 'http://r5u9a5ajg.hb-bkt.clouddn.com/' + response.data;
    this.$message({
        type:response.flag ? 'success':'error',
        message:response.message
    });
    //設定模型資料(圖片名稱),后續提交ajax請求時會提交到后臺最終保存到資料庫
    this.formData.img = response.data;
},
//上傳圖片之前執行
beforeAvatarUpload(file) {
  const isJPG = file.type === 'image/jpeg';
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isJPG) {
    this.$message.error('上傳套餐圖片只能是 JPG 格式!');
  }
  if (!isLt2M) {
    this.$message.error('上傳套餐圖片大小不能超過 2MB!');
  }
  return isJPG && isLt2M;
},

(4)創建SetmealController,接收上傳的檔案

package com.itterence.controller;

import com.itterence.constant.MessageConstant;
import com.itterence.entity.Result;
import com.itterence.utils.QiniuUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;

/**
 * 體檢套餐管理
 */

@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    //檔案上傳
    @RequestMapping("/upload")
    public Result upload(@RequestParam("imgFile") MultipartFile imgFile){
        System.out.println(imgFile);
        String originalFilename = imgFile.getOriginalFilename();//原始檔案名 3bd90d2c-4e82-42a1-a401-882c88b06a1a2.jpg
        int lastIndex= originalFilename.lastIndexOf(".");
        String extention = originalFilename.substring(lastIndex);//.jpg
        String fileName = UUID.randomUUID().toString() + extention;//	FuM1Sa5TtL_ekLsdkYWcf5pyjKGu.jpg
        try {
            //將檔案上傳到七牛云服務器
            QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName);
        } catch (IOException e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.PIC_UPLOAD_FAIL);
        }
        return new Result(true, MessageConstant.PIC_UPLOAD_SUCCESS,fileName);
    }

}

注意:別忘了在spring組態檔中組態檔上傳組件

<!--檔案上傳組件-->
<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="104857600" />
    <property name="maxInMemorySize" value="4096" />
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

2.2.4 提交請求

當用戶點擊新增視窗中的確定按鈕時發送ajax請求將資料提交到后臺進行資料庫操作,提交到后臺的資料分為兩部分:套餐基本資訊(對應的模型資料為formData)和檢查組id陣列(對應的模型資料為checkgroupIds),

為確定按鈕系結單擊事件,對應的處理函式為handleAdd

<el-button type="primary" @click="handleAdd()">確定</el-button>
//添加
handleAdd () {
	//發送ajax請求,將表單資料(套餐基本資訊、檢查組ID)提交到后臺進行處理
	axios.post("/setmeal/add.do?checkgroupIds=" + this.checkgroupIds,this.formData).then((res) => {
		//關閉新增視窗
		this.dialogFormVisible = false;
		if(res.data.flag){
			//執行成功
			this.$message({
				type:'success',
				message:res.data.message
			});
		}else{
			//執行失敗
			this.$message.error(res.data.message);
		}
	}).finally(() => {
		this.findPage();
	});
},

2.3 后臺代碼

2.3.1 Controller

在SetmealController中增加方法

@Reference
private SetmealService setmealService;

//新增套餐
@RequestMapping("/add")
public Result add(@RequestBody Setmeal setmeal, Integer[] checkgroupIds){
    try{
        setmealService.add(setmeal,checkgroupIds);
    }catch (Exception e){
        e.printStackTrace();
        return new Result(false,MessageConstant.ADD_SETMEAL_FAIL);
    }
    return new Result(true,MessageConstant.ADD_SETMEAL_SUCCESS);
}

2.3.2 服務介面

創建SetmealService介面并提供新增方法

package com.itterence.service;

import com.itterence.pojo.Setmeal;

/**
 * 體檢套餐服務介面
 */
public interface SetmealService {
    public void add(Setmeal setmeal, Integer[] checkgroupIds);
}

2.3.3 服務實作類

創建SetmealServiceImpl服務實作類并實作新增方法

package com.itterence.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.itterence.dao.SetmealDao;
import com.itterence.pojo.Setmeal;
import com.itterence.service.SetmealService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;

/**
 * 體檢套餐服務
 */
@Service(interfaceClass = SetmealService.class)
@Transactional
public class SetmealServiceImpl implements SetmealService{
    @Autowired
    private SetmealDao setmealDao;


    //新增套餐資訊,同時需要關聯檢查組
    public void add(Setmeal setmeal, Integer[] checkgroupIds) {
        setmealDao.add(setmeal);
        this.setSetmealAndCheckGroup(setmeal.getId(),checkgroupIds);
    }

    //設定套餐和檢查組多對多關系,操作t_setmeal_checkgroup
    public void setSetmealAndCheckGroup(Integer setmealId,Integer[] checkgroupIds){
        if(checkgroupIds != null && checkgroupIds.length > 0){
            for (Integer checkgroupId : checkgroupIds) {
                Map<String,Integer> map = new HashMap<>();
                map.put("setmealId",setmealId);
                map.put("checkgroupId",checkgroupId);
                setmealDao.setSetmealAndCheckGroup(map);
            }
        }
    }
}

2.3.4 Dao介面

創建SetmealDao介面并提供相關方法

package com.itterence.dao;

import com.itterence.pojo.Setmeal;

import java.util.Map;

public interface SetmealDao {
    public void add(Setmeal setmeal);
    public void setSetmealAndCheckGroup(Map<String, Integer> map);
}

2.3.5 Mapper映射檔案

創建SetmealDao.xml檔案并定義相關SQL陳述句

<?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.itterence.dao.SetmealDao">
    <!--插入套餐資料-->
    <insert id="add" parameterType="com.itterence.pojo.Setmeal">
        <!--通過mybatis框架提供的selectKey標簽獲得自增產生的ID值-->
        <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
            select LAST_INSERT_ID()
        </selectKey>
        insert into t_setmeal(code,name,sex,helpCode,remark,attention,age,price,img)
                      values
        (#{code},#{name},#{sex},#{helpCode},#{remark},#{attention},#{age},#{price},#{img})
    </insert>

    <!--設定套餐和檢查組多對多關系-->
    <insert id="setSetmealAndCheckGroup" parameterType="map">
        insert into t_setmeal_checkgroup(setmeal_id,checkgroup_id)
        values
        (#{setmealId},#{checkgroupId})
    </insert>
    
</mapper>

2.4 完善檔案上傳

前面我們已經完成了檔案上傳,將圖片存盤在了七牛云服務器中,但是這個程序存在一個問題,就是如果用戶只上傳了圖片而沒有最終保存套餐資訊到我們的資料庫,這時我們上傳的圖片就變為了垃圾圖片,對于這些垃圾圖片我們需要定時清理來釋放磁盤空間,這就需要我們能夠區分出來哪些是垃圾圖片,哪些不是垃圾圖片,如何實作呢?

方案就是利用redis來保存圖片名稱,具體做法為:

1、當用戶上傳圖片后,將圖片名稱保存到redis的一個Set集合中,例如集合名稱為 setmealPicResources

2、當用戶添加套餐后,將圖片名稱保存到redis的另一個Set集合中,例如集合名稱為 setmealPicDbResources

3、計算setmealPicResources集合與setmealPicDbResources集合的差值,結果就是垃圾圖片的名稱集合,清理這些圖片即可 本小節我們先來完成前面2個環節,第3個環節(清理圖片環節)在后面會通過定時任務再實作,

實作步驟:

(1)在health_backend專案中提供Spring組態檔spring-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans.xsd
        				http://www.springframework.org/schema/mvc
                         http://www.springframework.org/schema/mvc/spring-mvc.xsd
        				http://code.alibabatech.com/schema/dubbo
                         http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        				http://www.springframework.org/schema/context
                         http://www.springframework.org/schema/context/spring-context.xsd">

    <!--Jedis連接池的相關配置-->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal">
            <value>200</value>
        </property>
        <property name="maxIdle">
            <value>50</value>
        </property>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
    </bean>
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="127.0.0.1" />
        <constructor-arg name="port" value="6379" type="int" />
        <constructor-arg name="timeout" value="30000" type="int" />
    </bean>
</beans>

在health_backend專案中spring-mvc.xml中參考spring-redis.xml

<import resource="spring-redis.xml"/>

(2)在health_common工程中提供Redis常量類

package com.itterence.constant;

public class RedisConstant {
    //套餐圖片所有圖片名稱
    public static final String SETMEAL_PIC_RESOURCES = "setmealPicResources";
    //套餐圖片保存在資料庫中的圖片名稱
    public static final String SETMEAL_PIC_DB_RESOURCES = "setmealPicDbResources";
}

(3)完善SetmealController,在檔案上傳成功后將圖片名稱保存到redis集合中

//使用JedisPool操作Redis服務
@Autowired
private JedisPool jedisPool;

//檔案上傳
@RequestMapping("/upload")
public Result upload(@RequestParam("imgFile") MultipartFile imgFile){
    System.out.println(imgFile);
    String originalFilename = imgFile.getOriginalFilename();//原始檔案名 3bd90d2c-4e82-42a1-a401-882c88b06a1a2.jpg
    int lastIndex = originalFilename.lastIndexOf(".");
    String extention = originalFilename.substring(lastIndex);//.jpg
    String fileName = UUID.randomUUID().toString() + extention;//	FuM1Sa5TtL_ekLsdkYWcf5pyjKGu.jpg
    try {
        //將檔案上傳到七牛云服務器
        QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName);
        jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);
    } catch (IOException e) {
        e.printStackTrace();
        return new Result(false, MessageConstant.PIC_UPLOAD_FAIL);
    }
    return new Result(true, MessageConstant.PIC_UPLOAD_SUCCESS,fileName);
}

(4)在health_service_provider專案中提供Spring組態檔spring-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans.xsd
        				http://www.springframework.org/schema/mvc
                         http://www.springframework.org/schema/mvc/spring-mvc.xsd
        				http://code.alibabatech.com/schema/dubbo
                         http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        				http://www.springframework.org/schema/context
                         http://www.springframework.org/schema/context/spring-context.xsd">

    <!--Jedis連接池的相關配置-->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal">
            <value>200</value>
        </property>
        <property name="maxIdle">
            <value>50</value>
        </property>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
    </bean>
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="127.0.0.1" />
        <constructor-arg name="port" value="6379" type="int" />
        <constructor-arg name="timeout" value="30000" type="int" />
    </bean>
</beans>

(5)完善SetmealServiceImpl服務類,在保存完成套餐資訊后將圖片名稱存盤到redis集合中

@Autowired
private JedisPool jedisPool;
//新增套餐
public void add(Setmeal setmeal, Integer[] checkgroupIds) {
    setmealDao.add(setmeal);
    if(checkgroupIds != null && checkgroupIds.length > 0){
        setSetmealAndCheckGroup(setmeal.getId(),checkgroupIds);
    }
    //將圖片名稱保存到Redis
    savePic2Redis(setmeal.getImg());
}
//將圖片名稱保存到Redis
private void savePic2Redis(String pic){
    jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES,pic);
}

3. 體檢套餐分頁

3.1 完善頁面

3.1.1 定義分頁相關模型資料

pagination: {//分頁相關屬性
    currentPage: 1,
    pageSize:10,
    total:100,
    queryString:null,
},
dataList: [],//串列資料

3.1.2 定義分頁方法

在頁面中提供了findPage方法用于分頁查詢,為了能夠在setmeal.html頁面加載后直接可以展示分頁資料,可以在VUE提供的鉤子函式created中呼叫findPage方法

//鉤子函式,VUE物件初始化完成后自動執行
created() {
    this.findPage();
},
//分頁查詢
findPage() {
    //分頁引數
    var param = {
        currentPage:this.pagination.currentPage,//頁碼
        pageSize:this.pagination.pageSize,//每頁顯示的記錄數
        queryString:this.pagination.queryString//查詢條件
    };
    //請求后臺
    axios.post("/setmeal/findPage.do",param).then((response)=> {
        //為模型資料賦值,基于VUE的雙向系結展示到頁面
        this.dataList = response.data.rows;
        this.pagination.total = response.data.total;
    });
},

3.1.3 完善分頁方法執行時機

除了在created鉤子函式中呼叫findPage方法查詢分頁資料之外,當用戶點擊查詢按鈕或者點擊分頁條中的頁碼時也需要呼叫findPage方法重新發起查詢請求,

為查詢按鈕系結單擊事件,呼叫findPage方法

<el-button @click="findPage()" class="dalfBut">查詢</el-button>

為分頁條組件系結current-change事件,此事件是分頁條組件自己定義的事件,當頁碼改變時觸發,對 應的處理函式為handleCurrentChange

<el-pagination
    class="pagiantion"
    @current-change="handleCurrentChange"
    :current-page="pagination.currentPage"
    :page-size="pagination.pageSize"
    layout="total, prev, pager, next, jumper"
    :total="pagination.total">
</el-pagination>

定義handleCurrentChange方法

//切換頁碼
handleCurrentChange(currentPage) {
    //currentPage為切換后的頁碼
    this.pagination.currentPage = currentPage;
    this.findPage();
}

3.2 后臺代碼

3.2.1 Controller

在SetmealController中增加分頁查詢方法

//分頁查詢
@RequestMapping("/findPage")
public PageResult findPage(@RequestBody QueryPageBean queryPageBean){
	return setmealService.pageQuery(queryPageBean);
}

3.2.2 服務介面

在SetmealService服務介面中擴展分頁查詢方法

public PageResult pageQuery(QueryPageBean queryPageBean);

3.2.3 服務實作類

在SetmealServiceImpl服務實作類中實作分頁查詢方法,基于Mybatis分頁助手插件實作分頁

@Override
public PageResult pageQuery(QueryPageBean queryPageBean) {
	Integer currentPage = queryPageBean.getCurrentPage();
	Integer pageSize = queryPageBean.getPageSize();
	String queryString = queryPageBean.getQueryString();
	PageHelper.startPage(currentPage,pageSize);
	Page<Setmeal> page = setmealDao.findByCondition(queryString);
	return new PageResult(page.getTotal(),page.getResult());
}

3.2.4 Dao介面

在SetmealDao介面中擴展分頁查詢方法

public Page<Setmeal> findByCondition(String queryString);

3.2.5 Mapper映射檔案

在SetmealDao.xml檔案中增加SQL定義

<!--根據條件進行查詢-->
<select id="findByCondition" parameterType="string" resultType="com.itterence.pojo.Setmeal">
	select * from t_setmeal
	<if test="value != null and value != '' and value.length > 0">
		where code = #{value} or name = #{value} or helpCode = #{value}
	</if>
</select>

4. 定時任務組件Quartz

4.1 Quartz介紹

Quartz是Job scheduling(作業調度)領域的一個開源專案,Quartz既可以單獨使用也可以跟spring框架整合使用,在實際開發中一般會使用后者,使用Quartz可以開發一個或者多個定時任務,每個定時任務可以單獨指定執行的時間,例如每隔1小時執行一次、每個月第一天上午10點執行一次、每個月最后一天下午5點執行一次等,

官網:http://www.quartz-scheduler.org/

maven坐標:

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.1</version>
</dependency>

4.2 Quartz入門案例

本案例基于Quartz和spring整合的方式使用,具體步驟:

(1)創建maven工程quartzdemo,匯入Quartz和spring相關坐標,pom.xml檔案如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itterence</groupId>
    <artifactId>quartz_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>
    </dependencies>
</project>

(2)自定義一個Job

package com.itterence.jobs;

public class JobDemo {
    public void run(){
        System.out.println("job execute...");
    }
}

(3)提供Spring組態檔spring-jobs.xml,配置自定義Job、任務描述、觸發器、調度工廠等

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/mvc
						http://www.springframework.org/schema/mvc/spring-mvc.xsd
						http://code.alibabatech.com/schema/dubbo
						http://code.alibabatech.com/schema/dubbo/dubbo.xsd
						http://www.springframework.org/schema/context
						http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 注冊自定義Job -->
    <bean id="jobDemo" class="com.itterence.jobs.JobDemo"></bean>
    <!-- 注冊JobDetail,作用是負責通過反射呼叫指定的Job -->
    <bean id="jobDetail"
          class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 注入目標物件 -->
        <property name="targetObject" ref="jobDemo"/>
        <!-- 注入目標方法 -->
        <property name="targetMethod" value="run"/>
    </bean>
    <!-- 注冊一個觸發器,指定任務觸發的時間 -->
    <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <!-- 注入JobDetail -->
        <property name="jobDetail" ref="jobDetail"/>
        <!-- 指定觸發的時間,基于Cron運算式 -->
        <property name="cronExpression">
            <value>0/10 * * * * ?</value>
        </property>
    </bean>
    <!-- 注冊一個統一的調度工廠,通過這個調度工廠調度任務 -->
    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!-- 注入多個觸發器 -->
        <property name="triggers">
            <list>
                <ref bean="myTrigger"/>
            </list>
        </property>
    </bean>
</beans>

(4)撰寫main方法進行測驗

package com.itterence;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("spring-jobs.xml");
    }
}

執行上面main方法觀察控制臺,可以發現每隔10秒會輸出一次,說明每隔10秒自定義Job被呼叫一次,

4.3 cron運算式

上面的入門案例中我們指定了一個運算式:0/10 * * * * ?

這種運算式稱為cron運算式,通過cron運算式可以靈活的定義出符合要求的程式執行的時間,本小節我們就來學習一下cron運算式的使用方法,如下圖:

cron運算式分為七個域,之間使用空格分隔,其中最后一個域(年)可以為空,每個域都有自己允許的值和一些特殊字符構成,使用這些特殊字符可以使我們定義的運算式更加靈活,
下面是對這些特殊字符的介紹:
逗號(,):指定一個值串列,例如使用在月域上1,4,5,7表示1月、4月、5月和7月
橫杠(-):指定一個范圍,例如在時域上3-6表示3點到6點(即3點、4點、5點、6點)
星號(*):表示這個域上包含所有合法的值,例如,在月份域上使用星號意味著每個月都會觸發
斜線(/):表示遞增,例如使用在秒域上0/15表示每15秒
問號(?):只能用在日和周域上,但是不能在這兩個域上同時使用,表示不指定
井號(#):只能使用在周域上,用于指定月份中的第幾周的哪一天,例如6#3,意思是某月的第三個周五 (6=星期五,3意味著月份中的第三周)
L:某域上允許的最后一個值,只能使用在日和周域上,當用在日域上,表示的是在月域上指定的月份的最后一天,用于周域上時,表示周的最后一天,就是星期六
W:W 字符代表著作業日 (星期一到星期五),只能用在日域上,它用來指定離指定日的最近的一個作業日

4.4 cron運算式在線生成器

前面介紹了cron運算式,但是自己撰寫運算式還是有一些困難的,我們可以借助一些cron運算式在線生 成器來根據我們的需求生成運算式即可,

http://qqe2.com/cron

5. 定時清理垃圾圖片

前面我們已經完成了體檢套餐的管理,在新增套餐時套餐的基本資訊和圖片是分兩次提交到后臺進行操作的,也就是用戶首先將圖片上傳到七牛云服務器,然后再提交新增視窗中錄入的其他資訊,如果用戶 只是上傳了圖片而沒有提交錄入的其他資訊,此時的圖片就變為了垃圾圖片,因為在資料庫中并沒有記 錄它的存在,此時我們要如何處理這些垃圾圖片呢?

解決方案就是通過定時任務組件定時清理這些垃圾圖片,為了能夠區分出來哪些圖片是垃圾圖片,我們 在檔案上傳成功后將圖片保存到了一個redis集合中,當套餐資料插入到資料庫后我們又將圖片名稱保存 到了另一個redis集合中,通過計算這兩個集合的差值就可以獲得所有垃圾圖片的名稱,

本章節我們就會基于Quartz定時任務,通過計算redis兩個集合的差值找出所有的垃圾圖片,就可以將 垃圾圖片清理掉, 操作步驟:

(1)創建maven工程health_jobs,打包方式為war,匯入Quartz等相關坐標

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>health_parent</artifactId>
        <groupId>com.itterence</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>health_jobs</artifactId>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.itterence</groupId>
            <artifactId>health_common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.itterence</groupId>
            <artifactId>health_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定埠 -->
                    <port>83</port>
                    <!-- 請求路徑 -->
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

(2)配置web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!-- 加載spring容器 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

(3)配置log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

(4)配置applicationContext-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans.xsd
        				http://www.springframework.org/schema/mvc
                          http://www.springframework.org/schema/mvc/spring-mvc.xsd
        				http://code.alibabatech.com/schema/dubbo
                          http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        				http://www.springframework.org/schema/context
                          http://www.springframework.org/schema/context/spring-context.xsd">

    <!--Jedis連接池的相關配置-->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal">
            <value>200</value>
        </property>
        <property name="maxIdle">
            <value>50</value>
        </property>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
    </bean>
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="127.0.0.1" />
        <constructor-arg name="port" value="6379" type="int" />
        <constructor-arg name="timeout" value="30000" type="int" />
    </bean>
</beans>

(5)配置applicationContext-jobs.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
							http://www.springframework.org/schema/beans/spring-beans.xsd
							http://www.springframework.org/schema/mvc
							http://www.springframework.org/schema/mvc/spring-mvc.xsd
							http://code.alibabatech.com/schema/dubbo
							http://code.alibabatech.com/schema/dubbo/dubbo.xsd
							http://www.springframework.org/schema/context
							http://www.springframework.org/schema/context/spring-context.xsd">
    <!--開啟spring注解使用-->
    <context:annotation-config></context:annotation-config>
    <!--注冊自定義Job-->
    <bean id="clearImgJob" class="com.itterence.jobs.ClearImgJob"></bean>

    <bean id="jobDetail"
          class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 注入目標物件 -->
        <property name="targetObject" ref="clearImgJob"/>
        <!-- 注入目標方法 -->
        <property name="targetMethod" value="clearImg"/>
    </bean>
    <!-- 注冊一個觸發器,指定任務觸發的時間 -->
    <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <!-- 注入JobDetail -->
        <property name="jobDetail" ref="jobDetail"/>
        <!-- 指定觸發的時間,基于Cron運算式 -->
        <property name="cronExpression">
            <!--
            <value>0 0 2 * * ?</value>
            -->
            <value>0/10 * * * * ?</value>
        </property>
    </bean>
    <!-- 注冊一個統一的調度工廠,通過這個調度工廠調度任務 -->
    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!-- 注入多個觸發器 -->
        <property name="triggers">
            <list>
                <ref bean="myTrigger"/>
            </list>
        </property>
    </bean>
</beans>

(6)創建ClearImgJob定時任務類

package com.itterence.jobs;

import com.itterence.constant.RedisConstant;
import com.itterence.utils.QiniuUtils;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.JedisPool;

import java.util.Set;

/**
 * 自定義Job,實作定時清理垃圾圖片
 */
public class ClearImgJob {
    @Autowired
    private JedisPool jedisPool;
    public void clearImg(){
        //根據Redis中保存的兩個set集合進行差值計算,獲得垃圾圖片名稱集合
        Set<String> set =
                jedisPool.getResource().sdiff(RedisConstant.SETMEAL_PIC_RESOURCES,
                        RedisConstant.SETMEAL_PIC_DB_RESOURCES);
        if(set != null){
            for (String picName : set) {
                //洗掉七牛云服務器上的圖片
                QiniuUtils.deleteFileFromQiniu(picName);
                //從Redis集合中洗掉圖片名稱
                jedisPool.getResource().
                        srem(RedisConstant.SETMEAL_PIC_RESOURCES,picName);
            }
        }
    }

}

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

標籤:其他

上一篇:帶你分析Spark原始碼,0基礎也能看懂(1)

下一篇:Flume日志采集、聚合和傳輸系統

標籤雲
其他(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)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more