最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java開(kāi)發(fā)如何把數(shù)據(jù)庫(kù)里的未付款訂單改成已付款

 更新時(shí)間:2022年11月14日 14:50:35   作者:肥肥技術(shù)宅  
這篇文章主要介紹了Java開(kāi)發(fā)如何把數(shù)據(jù)庫(kù)里的未付款訂單改成已付款,先介紹MD5算法,簡(jiǎn)單的來(lái)說(shuō),MD5能把任意大小、長(zhǎng)度的數(shù)據(jù)轉(zhuǎn)換成固定長(zhǎng)度的一串字符,實(shí)現(xiàn)思路非常簡(jiǎn)單需要的朋友可以參考下

導(dǎo)言

不知道大家在網(wǎng)上購(gòu)物的時(shí)候,有沒(méi)有這樣的念頭,如果能把未付款的訂單偷偷用一條SQL改成已付款,該多么美好啊。那么在實(shí)際開(kāi)發(fā)過(guò)程中,我們應(yīng)當(dāng)如何保證數(shù)據(jù)庫(kù)里的數(shù)據(jù)在保存后不會(huì)被偷偷更改?

理論

在介紹具體的內(nèi)容之間,先介紹MD5算法,簡(jiǎn)單的來(lái)說(shuō),MD5能把任意大小、長(zhǎng)度的數(shù)據(jù)轉(zhuǎn)換成固定長(zhǎng)度的一串字符,經(jīng)常玩大型游戲的朋友應(yīng)該都注意到過(guò),各種補(bǔ)丁包、端游客戶端之類(lèi)的大型文件一般都附有一個(gè)MD5值,用于確保你下載文件的完整性。那么在這里,我們可以借鑒其思想,對(duì)訂單的某些屬性進(jìn)行加密計(jì)算,得出來(lái)一個(gè) MD5值一并保存在數(shù)據(jù)庫(kù)當(dāng)中。從數(shù)據(jù)庫(kù)取出數(shù)據(jù)后第一時(shí)間進(jìn)行校驗(yàn),如果有異常更改,那么及時(shí)拋出異常進(jìn)行人工處理。

實(shí)現(xiàn)

道理我都懂,但是我要如何做呢,別急,且聽(tīng)我一一道來(lái)。

這種需求聽(tīng)起來(lái)并不強(qiáng)綁定于某個(gè)具體的業(yè)務(wù)需求,這就要用到了我們熟悉的鼎鼎有名的AOP(面向切面編程)來(lái)實(shí)現(xiàn)。

首先定義四個(gè)類(lèi)型的注解作為AOP的切入點(diǎn)。@Sign@Validate都是作用在方法層面的,分別用于對(duì)方法的入?yún)⑦M(jìn)行加簽和驗(yàn)證方法的返回值的簽名。@SignField用于注解關(guān)鍵的不容篡改的字段。@ValidateField用于注解保存計(jì)算后得出的簽名值。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Sign {
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Validate {
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SignField {
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidField {
}

以訂單的實(shí)體為例 sn,amt,status,userId就是關(guān)鍵字段,絕不能允許有人在落單到數(shù)據(jù)庫(kù)后對(duì)這些字段偷偷篡改。

public class Order {
    @SignField
    private String sn;
    @SignField
    private String amt;
    @SignField
    private int status;
    @SignField
    private int userId;
    @ValidField
    private String sign;
}

下面就到了重頭戲的部分,如何通過(guò)AOP來(lái)進(jìn)行實(shí)現(xiàn)。

1. 定義切入點(diǎn)

@Pointcut("execution(@com.example.demo.annotations.Sign * *(..))")
public void signPointCut() {
 
}
 
@Pointcut("execution(@com.example.demo.annotations.Validate * *(..))")
public void validatePointCut() {
 
}

2.環(huán)繞切入點(diǎn)

@Around("signPointCut()")
public Object signAround(ProceedingJoinPoint pjp) throws Throwable {
    Object[] args = pjp.getArgs();
    for (Object o : args) {
        System.out.println(o);
        sign(o);
    }
    Object res = pjp.proceed(args);
    return res;
}
 
@Around("validatePointCut()")
public Object validateAround(ProceedingJoinPoint pjp) throws Throwable {
    Object[] args = pjp.getArgs();
    Object res = pjp.proceed(args);
    valid(res);
    return res;
}

3. 簽名的實(shí)現(xiàn)

1.獲取需要簽名字段

private Map<String, String> getSignMap(Object o) throws IllegalAccessException {
    Map<String, String> fieldNameToValue = new HashMap<>();
    for (Field f : o.getClass().getDeclaredFields()) {
        System.out.println(f.getName());
        for (Annotation annotation : f.getDeclaredAnnotations()) {
            if (annotation.annotationType().equals(SignField.class)) {
                String value = "";
                f.setAccessible(true);
                fieldNameToValue.put(f.getName(), f.get(o).toString());
            }
        }
    }
    return fieldNameToValue;
}

2.計(jì)算出簽名值,這里在屬性名和屬性值以外加入了我的昵稱(chēng)以防止他人猜測(cè),同時(shí)使用了自定義的分隔符來(lái)加強(qiáng)密碼強(qiáng)度。

private String getSign(Map<String, String> fieldNameToValue) {
    List<String> names = new ArrayList<>(fieldNameToValue.keySet());
    StringBuilder sb = new StringBuilder();
    for (String name : names)
        sb.append(name).append("@").append(fieldNameToValue.get(name));
    System.out.println(sb.append("日暮與星辰之間").toString());
    String signValue = DigestUtils.md5DigestAsHex(sb.toString().getBytes(StandardCharsets.UTF_8));
    return signValue;
}

找到保存簽名的字段

private Field getValidateFiled(Object o) {
    for (Field f : o.getClass().getDeclaredFields()) {
        for (Annotation annotation : f.getDeclaredAnnotations()) {
            if (annotation.annotationType().equals(ValidField.class)) {
                return f;
            }
        }
    }
    return null;
}

對(duì)保存簽名的字段進(jìn)行賦值

public void sign(Object o) throws IllegalAccessException {
    Map<String, String> fieldNameToValue = getSignMap(o);
    if (fieldNameToValue.isEmpty()) {
        return;
    }
    Field validateField = getValidateFiled(o);
    if (validateField == null)
        return;
    String signValue = getSign(fieldNameToValue);
    validateField.setAccessible(true);
    validateField.set(o, signValue);
}

對(duì)從數(shù)據(jù)庫(kù)中取出的對(duì)象進(jìn)行驗(yàn)證

public void valid(Object o) throws IllegalAccessException {
    Map<String, String> fieldNameToValue = getSignMap(o);
    if (fieldNameToValue.isEmpty()) {
        return;
    }
    Field validateField = getValidateFiled(o);
    validateField.setAccessible(true);
    String signValue = getSign(fieldNameToValue);
    if (!Objects.equals(signValue, validateField.get(o))) {
        throw new RuntimeException("數(shù)據(jù)非法");
    }
 
}

使用示例

對(duì)將要保存到數(shù)據(jù)庫(kù)的對(duì)象進(jìn)行簽名

@Sign
public Order save( Order order){
    orderList.add(order);
    return order;
}

驗(yàn)證從數(shù)據(jù)庫(kù)中取出的對(duì)象是否合理

@Validate
public Order query(@ String sn){
   return orderList.stream().filter(e -> e.getSn().equals(sn)).findFirst().orElse(null);
}

到此這篇關(guān)于把數(shù)據(jù)庫(kù)里的未付款訂單改成已付款,會(huì)發(fā)生什么的文章就介紹到這了,更多相關(guān)數(shù)據(jù)庫(kù)未付款訂單改成已付款內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot跨域訪問(wèn)cros與@CrossOrigin注解詳析

    springboot跨域訪問(wèn)cros與@CrossOrigin注解詳析

    這篇文章主要給大家介紹了關(guān)于springboot跨域訪問(wèn)cros與@CrossOrigin注解的相關(guān)資料,跨域是指不同域名之間相互訪問(wèn),它是瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript施加的安全限制,需要的朋友可以參考下
    2023-12-12
  • maven依賴的配置和排除依賴過(guò)程

    maven依賴的配置和排除依賴過(guò)程

    這篇文章主要介紹了maven依賴的配置和排除依賴過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • SpringBoot登錄判斷過(guò)程代碼實(shí)例

    SpringBoot登錄判斷過(guò)程代碼實(shí)例

    這篇文章主要介紹了SpringBoot登錄判斷代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • 淺談hibernate之映射文件VS映射注解

    淺談hibernate之映射文件VS映射注解

    下面小編就為大家?guī)?lái)一篇淺談hibernate之映射文件VS映射注解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • java分割字符串多種方法(附例子)

    java分割字符串多種方法(附例子)

    這篇文章主要給大家介紹了關(guān)于java分割字符串多種方法的相關(guān)資料,Java中有多種方法可以實(shí)現(xiàn)字符串分割,文中將每張方法都給出了代碼示例,需要的朋友可以參考下
    2023-10-10
  • idea解決Git分支合并沖突問(wèn)題

    idea解決Git分支合并沖突問(wèn)題

    這篇文章主要介紹了idea解決Git分支合并沖突問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 解析ConcurrentHashMap:成員屬性、內(nèi)部類(lèi)、構(gòu)造方法

    解析ConcurrentHashMap:成員屬性、內(nèi)部類(lèi)、構(gòu)造方法

    ConcurrentHashMap是由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成。Segment的結(jié)構(gòu)和HashMap類(lèi)似,是一種數(shù)組和鏈表結(jié)構(gòu),今天給大家普及java面試常見(jiàn)問(wèn)題---ConcurrentHashMap知識(shí),一起看看吧
    2021-06-06
  • JMeter連接Mysql數(shù)據(jù)庫(kù)的實(shí)現(xiàn)步驟

    JMeter連接Mysql數(shù)據(jù)庫(kù)的實(shí)現(xiàn)步驟

    本文主要介紹了JMeter操作Mysql數(shù)據(jù)庫(kù),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Java并發(fā)CopyOnWrite容器原理解析

    Java并發(fā)CopyOnWrite容器原理解析

    這篇文章主要介紹了Java并發(fā)CopyOnWrite容器原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Jackson處理Optional時(shí)遇到問(wèn)題的解決與分析

    Jackson處理Optional時(shí)遇到問(wèn)題的解決與分析

    Optional是Java實(shí)現(xiàn)函數(shù)式編程的強(qiáng)勁一步,并且?guī)椭诜妒街袑?shí)現(xiàn),但是Optional的意義顯然不止于此,下面這篇文章主要給大家介紹了關(guān)于Jackson處理Optional時(shí)遇到問(wèn)題的解決與分析的相關(guān)資料,需要的朋友可以參考下
    2022-02-02

最新評(píng)論

阿拉善盟| 渑池县| 高碑店市| 安图县| 松原市| 古田县| 乌海市| 高尔夫| 吴川市| 启东市| 隆尧县| 长沙市| 望奎县| 仁化县| 新营市| 茂名市| 泽普县| 上栗县| 吴旗县| 都匀市| 太湖县| 习水县| 明水县| 涿鹿县| 聊城市| 渑池县| 温泉县| 勐海县| 慈溪市| 宜城市| 贞丰县| 泸定县| 修文县| 土默特右旗| 左权县| 星座| 刚察县| 武川县| 武汉市| 峨眉山市| 阆中市|