正在显示
9 个修改的文件
包含
227 行增加
和
13 行删除
1 | +package com.tianbo.analysis.annotation; | ||
2 | + | ||
3 | + | ||
4 | +import com.alibaba.fastjson.JSONObject; | ||
5 | +import com.tianbo.analysis.controller.bean.ResponseReason; | ||
6 | +import com.tianbo.analysis.model.ResultJson; | ||
7 | +import com.tianbo.analysis.tools.ResubmitLock; | ||
8 | +import lombok.extern.slf4j.Slf4j; | ||
9 | +import org.aspectj.lang.ProceedingJoinPoint; | ||
10 | +import org.aspectj.lang.annotation.Around; | ||
11 | +import org.aspectj.lang.annotation.Aspect; | ||
12 | +import org.aspectj.lang.reflect.MethodSignature; | ||
13 | +import org.springframework.stereotype.Component; | ||
14 | + | ||
15 | +import java.lang.reflect.Method; | ||
16 | + | ||
17 | +@Slf4j | ||
18 | +@Aspect | ||
19 | +@Component | ||
20 | +public class ReSubmitAspect { | ||
21 | + | ||
22 | + private final static String DATA = "data"; | ||
23 | + private final static Object PRESENT = new Object(); | ||
24 | + | ||
25 | + @Around("@annotation(com.tianbo.analysis.annotation.ReSubmitCheck)") | ||
26 | + public Object handleResubmit(ProceedingJoinPoint joinPoint) throws Throwable { | ||
27 | + Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); | ||
28 | + //获取注解信息 | ||
29 | + ReSubmitCheck annotation = method.getAnnotation(ReSubmitCheck.class); | ||
30 | + int delaySeconds = annotation.delaySeconds(); | ||
31 | + Object[] pointArgs = joinPoint.getArgs(); | ||
32 | + String key = ""; | ||
33 | + //获取第一个参数 | ||
34 | + Object firstParam = pointArgs[0]; | ||
35 | + //解析参数 | ||
36 | + if (firstParam != null) { | ||
37 | + //生成加密参数 使用了content_MD5的加密方式 | ||
38 | + key = ResubmitLock.handleKey(JSONObject.toJSONString(firstParam)); | ||
39 | + } | ||
40 | + | ||
41 | + //执行锁 | ||
42 | + boolean lock = false; | ||
43 | + try { | ||
44 | + //设置解锁key | ||
45 | + lock = ResubmitLock.getInstance().lock(key, PRESENT); | ||
46 | + if (lock) { | ||
47 | + //放行 | ||
48 | + return joinPoint.proceed(); | ||
49 | + } else { | ||
50 | + //响应重复提交异常 | ||
51 | + return new ResultJson(ResponseReason.REAPET_SUBMIT_ERR); | ||
52 | + } | ||
53 | + } finally { | ||
54 | + //设置解锁key和解锁时间 | ||
55 | + ResubmitLock.getInstance().unLock(lock, key, delaySeconds); | ||
56 | + } | ||
57 | + } | ||
58 | +} |
1 | +package com.tianbo.analysis.annotation; | ||
2 | + | ||
3 | + | ||
4 | +import java.lang.annotation.*; | ||
5 | + | ||
6 | +/** | ||
7 | + * @author mrz | ||
8 | + */ | ||
9 | +@Target(ElementType.METHOD) | ||
10 | +@Retention(RetentionPolicy.RUNTIME) | ||
11 | +@Documented | ||
12 | +public @interface ReSubmitCheck { | ||
13 | + /** | ||
14 | + * 延时时间 在延时多久后可以再次提交 | ||
15 | + * | ||
16 | + * @return Time unit is one second | ||
17 | + */ | ||
18 | + int delaySeconds() default 5; | ||
19 | +} |
1 | +package com.tianbo.analysis.controller; | ||
2 | + | ||
3 | +import com.tianbo.analysis.annotation.ReSubmitCheck; | ||
4 | +import com.tianbo.analysis.annotation.UserPermissionCheck; | ||
5 | +import com.tianbo.analysis.dao.SENDPLANMapper; | ||
6 | +import com.tianbo.analysis.model.ResultJson; | ||
7 | +import com.tianbo.analysis.model.SENDPLAN; | ||
8 | +import org.springframework.web.bind.annotation.*; | ||
9 | + | ||
10 | +import javax.annotation.Resource; | ||
11 | +import java.util.List; | ||
12 | + | ||
13 | +@RestController | ||
14 | +@RequestMapping("/sendplan") | ||
15 | +public class SendPlanController { | ||
16 | + | ||
17 | + @Resource | ||
18 | + SENDPLANMapper sendplanMapper; | ||
19 | + | ||
20 | + @UserPermissionCheck | ||
21 | + @PostMapping("add") | ||
22 | + public ResultJson add(@RequestBody SENDPLAN sendplan,@CookieValue("username") String username,@CookieValue("userid") String userid){ | ||
23 | + return sendplanMapper.insertSelective(sendplan)>0? new ResultJson("200","新增成功") : new ResultJson("400","新增失败"); | ||
24 | + } | ||
25 | + | ||
26 | + @UserPermissionCheck | ||
27 | + @PostMapping("del") | ||
28 | + public ResultJson del(@RequestBody SENDPLAN sendplan,@CookieValue("username") String username,@CookieValue("userid") String userid){ | ||
29 | + return sendplanMapper.deleteByPrimaryKey(sendplan.getCarrier())>0? new ResultJson("200","新增成功") : new ResultJson("400","新增失败"); | ||
30 | + } | ||
31 | + | ||
32 | + @ReSubmitCheck | ||
33 | + @GetMapping("list") | ||
34 | + public ResultJson<List<SENDPLAN>> list(@RequestParam(value = "carrier",required = false) String carrier){ | ||
35 | + List result = sendplanMapper.list(carrier); | ||
36 | + return new ResultJson("200","查询成功",result); | ||
37 | + } | ||
38 | +} |
@@ -6,6 +6,7 @@ public enum ResponseReason { | @@ -6,6 +6,7 @@ public enum ResponseReason { | ||
6 | MT8204_EDIT_ERR("8204401","直接改配申请更新失败"), | 6 | MT8204_EDIT_ERR("8204401","直接改配申请更新失败"), |
7 | MT8204_DEL_ERR("8204402","直接改配申请更新失败"), | 7 | MT8204_DEL_ERR("8204402","直接改配申请更新失败"), |
8 | MT8204_SEND_ERR("8204404","直接改配发送失败"), | 8 | MT8204_SEND_ERR("8204404","直接改配发送失败"), |
9 | + REAPET_SUBMIT_ERR("400001","请勿重复提交,请于5秒后尝试"), | ||
9 | MT8204_BATCH_SUCCESS("200","直接改配批量申请操作成功"); | 10 | MT8204_BATCH_SUCCESS("200","直接改配批量申请操作成功"); |
10 | private String code; | 11 | private String code; |
11 | private String msg; | 12 | private String msg; |
1 | package com.tianbo.analysis.dao; | 1 | package com.tianbo.analysis.dao; |
2 | 2 | ||
3 | import com.tianbo.analysis.model.SENDPLAN; | 3 | import com.tianbo.analysis.model.SENDPLAN; |
4 | +import org.apache.ibatis.annotations.Param; | ||
5 | + | ||
6 | +import java.util.List; | ||
4 | 7 | ||
5 | public interface SENDPLANMapper { | 8 | public interface SENDPLANMapper { |
6 | int deleteByPrimaryKey(String carrier); | 9 | int deleteByPrimaryKey(String carrier); |
@@ -8,4 +11,6 @@ public interface SENDPLANMapper { | @@ -8,4 +11,6 @@ public interface SENDPLANMapper { | ||
8 | int insert(SENDPLAN record); | 11 | int insert(SENDPLAN record); |
9 | 12 | ||
10 | int insertSelective(SENDPLAN record); | 13 | int insertSelective(SENDPLAN record); |
11 | -} | ||
14 | + | ||
15 | + List<SENDPLAN> list(@Param("carrier") String carrier); | ||
16 | +} |
1 | +package com.tianbo.analysis.tools; | ||
2 | + | ||
3 | +import lombok.extern.slf4j.Slf4j; | ||
4 | +import org.apache.commons.codec.digest.DigestUtils; | ||
5 | + | ||
6 | +import java.util.Objects; | ||
7 | +import java.util.concurrent.ConcurrentHashMap; | ||
8 | +import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
9 | +import java.util.concurrent.ThreadPoolExecutor; | ||
10 | +import java.util.concurrent.TimeUnit; | ||
11 | + | ||
12 | +/** | ||
13 | + * | ||
14 | + * @author mrz | ||
15 | + * 重复提交判定锁 | ||
16 | + */ | ||
17 | +@Slf4j | ||
18 | +public final class ResubmitLock { | ||
19 | + private static final ConcurrentHashMap<String, Object> LOCK_CACHE = new ConcurrentHashMap<>(200); | ||
20 | + private static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(5, new ThreadPoolExecutor.DiscardPolicy()); | ||
21 | +// private static final Cache<String, Object> CACHES = CacheBuilder.newBuilder() | ||
22 | + // 最大缓存 100 个 | ||
23 | + // .maximumSize(1000) | ||
24 | + // 设置写缓存后 5 秒钟过期 | ||
25 | + // .expireAfterWrite(5, TimeUnit.SECONDS) | ||
26 | + // .build(); | ||
27 | + | ||
28 | + | ||
29 | + private ResubmitLock() { | ||
30 | + } | ||
31 | + | ||
32 | + /** | ||
33 | + * 静态内部类 单例模式 | ||
34 | + * | ||
35 | + * @return | ||
36 | + */ | ||
37 | + private static class SingletonInstance { | ||
38 | + private static final ResubmitLock INSTANCE = new ResubmitLock(); | ||
39 | + } | ||
40 | + | ||
41 | + public static ResubmitLock getInstance() { | ||
42 | + return SingletonInstance.INSTANCE; | ||
43 | + } | ||
44 | + | ||
45 | + | ||
46 | + public static String handleKey(String param) { | ||
47 | + return DigestUtils.md5Hex(param == null ? "" : param); | ||
48 | + } | ||
49 | + | ||
50 | + /** | ||
51 | + * 加锁 putIfAbsent 是原子操作保证线程安全 | ||
52 | + * | ||
53 | + * @param key 对应的key | ||
54 | + * @param value | ||
55 | + * @return | ||
56 | + */ | ||
57 | + public boolean lock(final String key, Object value) { | ||
58 | + return Objects.isNull(LOCK_CACHE.putIfAbsent(key, value)); | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * 延时释放锁 用以控制短时间内的重复提交 | ||
63 | + * | ||
64 | + * @param lock 是否需要解锁 | ||
65 | + * @param key 对应的key | ||
66 | + * @param delaySeconds 延时时间 | ||
67 | + */ | ||
68 | + public void unLock(final boolean lock, final String key, final int delaySeconds) { | ||
69 | + if (lock) { | ||
70 | + EXECUTOR.schedule(() -> { | ||
71 | + LOCK_CACHE.remove(key); | ||
72 | + }, delaySeconds, TimeUnit.SECONDS); | ||
73 | + } | ||
74 | + } | ||
75 | +} |
@@ -446,7 +446,8 @@ GROUP BY | @@ -446,7 +446,8 @@ GROUP BY | ||
446 | createdate, | 446 | createdate, |
447 | status AS status, | 447 | status AS status, |
448 | receiptinformation, | 448 | receiptinformation, |
449 | - 'MT1201' AS messagetype | 449 | + 'MT1201' AS messagetype, |
450 | + PRODUCTNAME | ||
450 | FROM | 451 | FROM |
451 | originmanifestmaster UNION ALL | 452 | originmanifestmaster UNION ALL |
452 | SELECT | 453 | SELECT |
@@ -462,7 +463,8 @@ GROUP BY | @@ -462,7 +463,8 @@ GROUP BY | ||
462 | createdate, | 463 | createdate, |
463 | status, | 464 | status, |
464 | receiptinformation, | 465 | receiptinformation, |
465 | - talltype AS messagetype | 466 | + talltype AS messagetype, |
467 | + PRODUCTNAME | ||
466 | FROM | 468 | FROM |
467 | tallymaster | 469 | tallymaster |
468 | WHERE | 470 | WHERE |
@@ -494,7 +496,8 @@ GROUP BY | @@ -494,7 +496,8 @@ GROUP BY | ||
494 | createdate, | 496 | createdate, |
495 | status, | 497 | status, |
496 | receiption as receiptinformation, | 498 | receiption as receiptinformation, |
497 | - 'MT1201-1' as messagetype | 499 | + 'MT1201-1' as messagetype, |
500 | + PRODUCTNAME | ||
498 | from originmanifestsecondary | 501 | from originmanifestsecondary |
499 | where originmanifestmasterautoid= #{autoid} | 502 | where originmanifestmasterautoid= #{autoid} |
500 | UNION ALL | 503 | UNION ALL |
@@ -506,7 +509,8 @@ GROUP BY | @@ -506,7 +509,8 @@ GROUP BY | ||
506 | createdate, | 509 | createdate, |
507 | status, | 510 | status, |
508 | receiptinformation, | 511 | receiptinformation, |
509 | - 'MT5201-1' as messagetype | 512 | + 'MT5201-1' as messagetype, |
513 | + PRODUCTNAME | ||
510 | from tallysecondary | 514 | from tallysecondary |
511 | where tallymasterid= #{autoid} | 515 | where tallymasterid= #{autoid} |
512 | </select> | 516 | </select> |
@@ -590,7 +590,8 @@ select * from( | @@ -590,7 +590,8 @@ select * from( | ||
590 | status AS status, | 590 | status AS status, |
591 | concat( receiptinformation, arrived_ahead ) AS receiptinformation, | 591 | concat( receiptinformation, arrived_ahead ) AS receiptinformation, |
592 | 'MT2201' AS messagetype, | 592 | 'MT2201' AS messagetype, |
593 | - customsstatus | 593 | + customsstatus, |
594 | + PRODUCTNAME | ||
594 | FROM | 595 | FROM |
595 | preparemaster | 596 | preparemaster |
596 | <include refid="TreeCondition" /> | 597 | <include refid="TreeCondition" /> |
@@ -609,7 +610,8 @@ select * from( | @@ -609,7 +610,8 @@ select * from( | ||
609 | status, | 610 | status, |
610 | receiptinformation, | 611 | receiptinformation, |
611 | 'MT3201' AS messagetype, | 612 | 'MT3201' AS messagetype, |
612 | - arrived_ahead AS customsstatus | 613 | + arrived_ahead AS customsstatus, |
614 | + PRODUCTNAME | ||
613 | FROM | 615 | FROM |
614 | arrivedmaster | 616 | arrivedmaster |
615 | <include refid="TreeCondition" /> | 617 | <include refid="TreeCondition" /> |
@@ -628,7 +630,8 @@ select * from( | @@ -628,7 +630,8 @@ select * from( | ||
628 | status, | 630 | status, |
629 | receiption AS receiptinformation, | 631 | receiption AS receiptinformation, |
630 | 'MT4201' AS messagetype, | 632 | 'MT4201' AS messagetype, |
631 | - '' AS customsstatus | 633 | + '' AS customsstatus, |
634 | + PRODUCTNAME | ||
632 | FROM | 635 | FROM |
633 | departuresloading | 636 | departuresloading |
634 | <where> | 637 | <where> |
@@ -660,7 +663,8 @@ select * from( | @@ -660,7 +663,8 @@ select * from( | ||
660 | status, | 663 | status, |
661 | receiptinformation, | 664 | receiptinformation, |
662 | talltype AS messagetype, | 665 | talltype AS messagetype, |
663 | - '' AS customsstatus | 666 | + '' AS customsstatus, |
667 | + PRODUCTNAME | ||
664 | FROM | 668 | FROM |
665 | tallymaster | 669 | tallymaster |
666 | <where> | 670 | <where> |
@@ -694,7 +698,8 @@ select * from( | @@ -694,7 +698,8 @@ select * from( | ||
694 | status, | 698 | status, |
695 | receiptinformation, | 699 | receiptinformation, |
696 | 'MT2201-1' as messagetype, | 700 | 'MT2201-1' as messagetype, |
697 | - customsstatus | 701 | + customsstatus, |
702 | + PRODUCTNAME | ||
698 | from preparesecondary | 703 | from preparesecondary |
699 | where PREPAREMASTERID= #{autoid} | 704 | where PREPAREMASTERID= #{autoid} |
700 | 705 | ||
@@ -709,7 +714,8 @@ select * from( | @@ -709,7 +714,8 @@ select * from( | ||
709 | status, | 714 | status, |
710 | receiption as receiptinformation, | 715 | receiption as receiptinformation, |
711 | 'MT3201-1' as messagetype, | 716 | 'MT3201-1' as messagetype, |
712 | - '' as customsstatus | 717 | + '' as customsstatus, |
718 | + PRODUCTNAME | ||
713 | from arrivedsecondary | 719 | from arrivedsecondary |
714 | where ARRIVEDMASTERID= #{autoid} | 720 | where ARRIVEDMASTERID= #{autoid} |
715 | UNION ALL | 721 | UNION ALL |
@@ -723,7 +729,8 @@ select * from( | @@ -723,7 +729,8 @@ select * from( | ||
723 | status, | 729 | status, |
724 | receiptinformation, | 730 | receiptinformation, |
725 | 'MT5202-1' as messagetype, | 731 | 'MT5202-1' as messagetype, |
726 | - '' as customsstatus | 732 | + '' as customsstatus, |
733 | + PRODUCTNAME | ||
727 | from tallysecondary | 734 | from tallysecondary |
728 | where tallymasterID= #{autoid} | 735 | where tallymasterID= #{autoid} |
729 | </select> | 736 | </select> |
@@ -25,4 +25,11 @@ | @@ -25,4 +25,11 @@ | ||
25 | </if> | 25 | </if> |
26 | </trim> | 26 | </trim> |
27 | </insert> | 27 | </insert> |
28 | -</mapper> | ||
28 | + | ||
29 | + <select id="list" parameterType="java.lang.String" resultMap="BaseResultMap"> | ||
30 | + select CARRIER from CGONMS.SENDPLAN | ||
31 | + <if test="carrier != null and carrier != ''" > | ||
32 | + where CARRIER = #{carrier,jdbcType=VARCHAR} | ||
33 | + </if> | ||
34 | + </select> | ||
35 | +</mapper> |
-
请 注册 或 登录 后发表评论