├── src
├── main
│ ├── resources
│ │ ├── application.properties
│ │ ├── db
│ │ │ ├── ddl_create_database_01.sql
│ │ │ ├── dml_create_user_04.sql
│ │ │ ├── dml_create_fund_02.sql
│ │ │ └── dml_create_msg_log_03.sql
│ │ ├── static
│ │ │ └── css
│ │ │ │ └── fonts
│ │ │ │ └── fonts
│ │ │ │ ├── element-icons.ttf
│ │ │ │ └── element-icons.woff
│ │ ├── templates
│ │ │ ├── 404.html
│ │ │ ├── error.html
│ │ │ └── index.html
│ │ └── application-dev.properties
│ └── java
│ │ └── com
│ │ └── wangzaiplus
│ │ └── test
│ │ ├── designpattern
│ │ ├── factory
│ │ │ ├── IPay.java
│ │ │ ├── ALiPay.java
│ │ │ ├── UnionPay.java
│ │ │ ├── WeChatPay.java
│ │ │ ├── factorymethod
│ │ │ │ ├── FactoryMethod.java
│ │ │ │ ├── AFactory.java
│ │ │ │ ├── BFactory.java
│ │ │ │ └── PayService.java
│ │ │ ├── PayTypeEnum.java
│ │ │ └── simplefactory
│ │ │ │ ├── PayFactory.java
│ │ │ │ └── PayService.java
│ │ ├── strategy
│ │ │ ├── PayStrategy.java
│ │ │ ├── Main.java
│ │ │ ├── WxPayStrategy.java
│ │ │ ├── UnionPayStrategy.java
│ │ │ ├── AliPayStrategy.java
│ │ │ └── PayContext.java
│ │ ├── staticproxy
│ │ │ ├── PayService.java
│ │ │ ├── PayServiceImpl.java
│ │ │ ├── Test.java
│ │ │ └── PayProxy.java
│ │ └── dynamicproxy
│ │ │ ├── PayService.java
│ │ │ ├── PayServiceImpl.java
│ │ │ ├── Test.java
│ │ │ └── PayProxy.java
│ │ ├── service
│ │ ├── strategy
│ │ │ ├── CalculateService.java
│ │ │ ├── CalculateStrategy.java
│ │ │ ├── AddCalculateServiceImpl.java
│ │ │ ├── DivideCalculateServiceImpl.java
│ │ │ ├── MultiplyCalculateServiceImpl.java
│ │ │ ├── SubtractCalculateServiceImpl.java
│ │ │ └── CalculateServiceFactory.java
│ │ ├── batch
│ │ │ ├── BatchProcessMapper.java
│ │ │ └── mapperproxy
│ │ │ │ └── MapperProxy.java
│ │ ├── LoginLogService.java
│ │ ├── LoginService.java
│ │ ├── TokenService.java
│ │ ├── TestService.java
│ │ ├── MsgLogService.java
│ │ ├── FundService.java
│ │ ├── UserService.java
│ │ ├── impl
│ │ │ ├── LoginLogServiceImpl.java
│ │ │ ├── MsgLogServiceImpl.java
│ │ │ ├── TestServiceImpl.java
│ │ │ ├── TokenServiceImpl.java
│ │ │ └── UserServiceImpl.java
│ │ ├── threadpool
│ │ │ ├── TestJob.java
│ │ │ ├── ThreadPoolFactory.java
│ │ │ ├── LockSupportTest.java
│ │ │ └── Test.java
│ │ └── LoginServiceImpl.java
│ │ ├── annotation
│ │ ├── ColNum.java
│ │ ├── ApiIdempotent.java
│ │ └── AccessLimit.java
│ │ ├── mapper
│ │ ├── LoginLogMapper.java
│ │ ├── MsgLogMapper.java
│ │ ├── UserMapper.java
│ │ ├── FundMapper.java
│ │ ├── UserMapperWithAnnotation.java
│ │ ├── LoginLogMapper.xml
│ │ ├── MsgLogMapper.xml
│ │ ├── UserMapper.xml
│ │ └── FundMapper.xml
│ │ ├── dto
│ │ ├── FundRankDto.java
│ │ ├── FundTypeDto.java
│ │ ├── FundYieldDto.java
│ │ ├── FundJsonResponseDto.java
│ │ ├── SearchFormDto.java
│ │ ├── UserDto.java
│ │ └── FundDto.java
│ │ ├── pojo
│ │ ├── CalculateDto.java
│ │ ├── LoginLog.java
│ │ ├── User.java
│ │ ├── Mail.java
│ │ ├── Fund.java
│ │ └── MsgLog.java
│ │ ├── mq
│ │ ├── BaseConsumer.java
│ │ ├── consumer
│ │ │ ├── LoginLogConsumer.java
│ │ │ ├── MailConsumer.java
│ │ │ └── SimpleMailConsumer.java
│ │ ├── MessageHelper.java
│ │ ├── listener
│ │ │ ├── MailListener.java
│ │ │ └── LoginLogListener.java
│ │ └── BaseConsumerProxy.java
│ │ ├── controller
│ │ ├── ViewController.java
│ │ ├── Test.java
│ │ ├── TokenController.java
│ │ ├── LoginController.java
│ │ ├── RedissonController.java
│ │ ├── UserController.java
│ │ ├── FundController.java
│ │ ├── StrategyController.java
│ │ └── TestController.java
│ │ ├── util
│ │ ├── PageUtils.java
│ │ ├── ConfigUtil.java
│ │ ├── ListUtils.java
│ │ ├── SpringContextUtil.java
│ │ ├── ViewUtils.java
│ │ ├── IpUtil.java
│ │ ├── RegexUtil.java
│ │ ├── SerializableUtil.java
│ │ ├── JsonUtil.java
│ │ ├── MailUtil.java
│ │ ├── BeanUtils.java
│ │ ├── RandomUtil.java
│ │ ├── JedisUtil.java
│ │ ├── OkHttpUtils.java
│ │ ├── JodaTimeUtil.java
│ │ └── FundUtils.java
│ │ ├── exception
│ │ ├── ServiceException.java
│ │ └── MyControllerAdvice.java
│ │ ├── config
│ │ ├── RedissonConfig.java
│ │ ├── JedisConfig.java
│ │ ├── OkHttpConfig.java
│ │ └── RabbitConfig.java
│ │ ├── common
│ │ ├── ResponseCode.java
│ │ ├── ServerResponse.java
│ │ └── Constant.java
│ │ ├── interceptor
│ │ ├── ApiIdempotentInterceptor.java
│ │ └── AccessLimitInterceptor.java
│ │ ├── task
│ │ └── ResendMsg.java
│ │ └── TestApplication.java
└── test
│ └── java
│ └── com
│ └── wangzaiplus
│ └── test
│ ├── TestApplicationTests.java
│ ├── util
│ └── MailUtilTest.java
│ └── controller
│ └── test
│ └── TestControllerTest.java
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ ├── maven-wrapper.properties
│ └── MavenWrapperDownloader.java
├── .gitignore
├── pom.xml
└── mvnw.cmd
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.profiles.active=dev
--------------------------------------------------------------------------------
/src/main/resources/db/ddl_create_database_01.sql:
--------------------------------------------------------------------------------
1 | create database test;
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangzaiplus/springboot/HEAD/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/src/main/resources/static/css/fonts/fonts/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangzaiplus/springboot/HEAD/src/main/resources/static/css/fonts/fonts/element-icons.ttf
--------------------------------------------------------------------------------
/src/main/resources/static/css/fonts/fonts/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangzaiplus/springboot/HEAD/src/main/resources/static/css/fonts/fonts/element-icons.woff
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/IPay.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory;
2 |
3 | public interface IPay {
4 |
5 | boolean pay();
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/resources/templates/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 404
6 |
7 |
8 | 404
9 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/templates/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | error
6 |
7 |
8 | error
9 |
10 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/strategy/PayStrategy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.strategy;
2 |
3 | public interface PayStrategy {
4 |
5 | void pay(String userId);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/strategy/CalculateService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.strategy;
2 |
3 | public interface CalculateService {
4 |
5 | int calculate(int a, int b);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/staticproxy/PayService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.staticproxy;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public interface PayService {
6 |
7 | void pay(String username, BigDecimal money);
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/ALiPay.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory;
2 |
3 | public class ALiPay implements IPay{
4 |
5 | @Override
6 | public boolean pay() {
7 | // 支付相关逻辑...
8 | return true;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/UnionPay.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory;
2 |
3 | public class UnionPay implements IPay{
4 |
5 | @Override
6 | public boolean pay() {
7 | // 支付相关逻辑...
8 | return true;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/WeChatPay.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory;
2 |
3 | public class WeChatPay implements IPay{
4 |
5 | @Override
6 | public boolean pay() {
7 | // 支付相关逻辑...
8 | return true;
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/annotation/ColNum.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.annotation;
2 |
3 | import java.lang.annotation.*;
4 |
5 | @Documented
6 | @Retention(RetentionPolicy.RUNTIME)
7 | @Target(ElementType.FIELD)
8 | public @interface ColNum {
9 |
10 | int colNum();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/LoginLogMapper.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mapper;
2 |
3 | import com.wangzaiplus.test.pojo.LoginLog;
4 |
5 | public interface LoginLogMapper {
6 |
7 | void insert(LoginLog loginLog);
8 |
9 | LoginLog selectByMsgId(String msgId);
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/batch/BatchProcessMapper.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.batch;
2 |
3 | import java.util.List;
4 |
5 | public interface BatchProcessMapper {
6 |
7 | void batchInsert(List list);
8 |
9 | void batchUpdate(List list);
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/LoginLogService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.pojo.LoginLog;
4 |
5 | public interface LoginLogService {
6 |
7 | void insert(LoginLog loginLog);
8 |
9 | LoginLog selectByMsgId(String msgId);
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/LoginService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.dto.UserDto;
5 |
6 | public interface LoginService {
7 |
8 | ServerResponse doLogin(UserDto userDto);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/factorymethod/FactoryMethod.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory.factorymethod;
2 |
3 | import com.wangzaiplus.test.designpattern.factory.IPay;
4 |
5 | public interface FactoryMethod {
6 |
7 | IPay createPay(String payType);
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/strategy/Main.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.strategy;
2 |
3 | public class Main {
4 |
5 | public static void main(String[] args) {
6 | PayContext payContext = new PayContext();
7 | payContext.pay("3", "aaa");
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/dynamicproxy/PayService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.dynamicproxy;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public interface PayService {
6 |
7 | void pay(String username, BigDecimal money);
8 |
9 | void a();
10 |
11 | void b();
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/dto/FundRankDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.dto;
2 |
3 | import lombok.*;
4 |
5 | @Getter
6 | @Setter
7 | @NoArgsConstructor
8 | @AllArgsConstructor
9 | @ToString
10 | @Builder
11 | public class FundRankDto {
12 |
13 | private Integer rank;
14 | private String desc;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/dto/FundTypeDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.dto;
2 |
3 | import lombok.*;
4 |
5 | @Getter
6 | @Setter
7 | @NoArgsConstructor
8 | @AllArgsConstructor
9 | @ToString
10 | @Builder
11 | public class FundTypeDto {
12 |
13 | private Integer type;
14 | private String desc;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/dto/FundYieldDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.dto;
2 |
3 | import lombok.*;
4 |
5 | @Getter
6 | @Setter
7 | @NoArgsConstructor
8 | @AllArgsConstructor
9 | @ToString
10 | @Builder
11 | public class FundYieldDto {
12 |
13 | private String yield;
14 | private String desc;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/pojo/CalculateDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.pojo;
2 |
3 | import lombok.*;
4 |
5 | @Getter
6 | @Setter
7 | @NoArgsConstructor
8 | @AllArgsConstructor
9 | @ToString
10 | @Builder
11 | public class CalculateDto {
12 |
13 | Integer type;
14 | Integer a;
15 | Integer b;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/strategy/WxPayStrategy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.strategy;
2 |
3 | public class WxPayStrategy implements PayStrategy {
4 |
5 | @Override
6 | public void pay(String userId) {
7 | System.out.println("WxPayStrategy userId: " + userId);
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/strategy/UnionPayStrategy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.strategy;
2 |
3 | public class UnionPayStrategy implements PayStrategy {
4 |
5 | @Override
6 | public void pay(String userId) {
7 | System.out.println("UnionPayStrategy userId: " + userId);
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/BaseConsumer.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq;
2 |
3 | import com.rabbitmq.client.Channel;
4 | import org.springframework.amqp.core.Message;
5 |
6 | import java.io.IOException;
7 |
8 | public interface BaseConsumer {
9 |
10 | void consume(Message message, Channel channel) throws IOException;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/TokenService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 |
7 | public interface TokenService {
8 |
9 | ServerResponse createToken();
10 |
11 | void checkToken(HttpServletRequest request);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/dto/FundJsonResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.dto;
2 |
3 | import lombok.*;
4 |
5 | @Getter
6 | @Setter
7 | @NoArgsConstructor
8 | @AllArgsConstructor
9 | @ToString
10 | @Builder
11 | public class FundJsonResponseDto {
12 |
13 | private Integer total;
14 | private Integer pageIndex;
15 | private String data;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/TestService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.pojo.Mail;
5 |
6 | public interface TestService {
7 |
8 | ServerResponse testIdempotence();
9 |
10 | ServerResponse accessLimit();
11 |
12 | ServerResponse send(Mail mail);
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/factorymethod/AFactory.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory.factorymethod;
2 |
3 | import com.wangzaiplus.test.designpattern.factory.IPay;
4 |
5 | public class AFactory implements FactoryMethod {
6 |
7 | @Override
8 | public IPay createPay(String payType) {
9 | return null;
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/factorymethod/BFactory.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory.factorymethod;
2 |
3 | import com.wangzaiplus.test.designpattern.factory.IPay;
4 |
5 | public class BFactory implements FactoryMethod {
6 |
7 | @Override
8 | public IPay createPay(String payType) {
9 | return null;
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/ViewController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 |
6 | @Controller
7 | public class ViewController {
8 |
9 | @GetMapping("home")
10 | public String index() {
11 | return "index";
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/staticproxy/PayServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.staticproxy;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class PayServiceImpl implements PayService {
6 |
7 | @Override
8 | public void pay(String username, BigDecimal money) {
9 | System.out.println(username + "支付了" + money + "元钱");
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/strategy/AliPayStrategy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.strategy;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | @Component
6 | public class AliPayStrategy implements PayStrategy {
7 |
8 | @Override
9 | public void pay(String userId) {
10 | System.out.println("AliPayStrategy userId: " + userId);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/factorymethod/PayService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory.factorymethod;
2 |
3 | import com.wangzaiplus.test.designpattern.factory.IPay;
4 |
5 | public class PayService {
6 |
7 | public void pay(String payType) {
8 | FactoryMethod aFactory = new AFactory();
9 | IPay pay = aFactory.createPay(payType);
10 |
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/staticproxy/Test.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.staticproxy;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class Test {
6 |
7 | public static void main(String[] args) {
8 | PayService payService = new PayServiceImpl();
9 | PayProxy payProxy = new PayProxy(payService);
10 | payProxy.pay("马云", BigDecimal.TEN);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | /target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 |
5 | ### STS ###
6 | .apt_generated
7 | .classpath
8 | .factorypath
9 | .project
10 | .settings
11 | .springBeans
12 | .sts4-cache
13 |
14 | ### IntelliJ IDEA ###
15 | .idea
16 | *.iws
17 | *.iml
18 | *.ipr
19 |
20 | ### NetBeans ###
21 | /nbproject/private/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
26 | /build/
27 |
28 | ### VS Code ###
29 | .vscode/
30 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/dto/SearchFormDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.dto;
2 |
3 | import lombok.*;
4 |
5 | import java.util.List;
6 |
7 | @Getter
8 | @Setter
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @ToString
12 | @Builder
13 | public class SearchFormDto {
14 |
15 | private List typeList;
16 | private List yieldList;
17 | private List rankList;
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/wangzaiplus/test/TestApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class TestApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/annotation/ApiIdempotent.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * 在需要保证 接口幂等性 的Controller的方法上使用此注解
10 | */
11 | @Target({ElementType.METHOD})
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface ApiIdempotent {
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/MsgLogService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.pojo.MsgLog;
4 |
5 | import java.util.Date;
6 | import java.util.List;
7 |
8 | public interface MsgLogService {
9 |
10 | void updateStatus(String msgId, Integer status);
11 |
12 | MsgLog selectByMsgId(String msgId);
13 |
14 | List selectTimeoutMsg();
15 |
16 | void updateTryCount(String msgId, Date tryTime);
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/Test.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import org.springframework.boot.ApplicationArguments;
4 | import org.springframework.boot.ApplicationRunner;
5 |
6 | /**
7 | * TODO
8 | *
9 | * @author: 北瓜
10 | * @date: 2021/8/23 21:40
11 | */
12 | public class Test implements ApplicationRunner {
13 |
14 | @Override
15 | public void run(ApplicationArguments args) throws Exception {
16 |
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/PageUtils.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import com.github.pagehelper.PageInfo;
4 | import org.springframework.beans.BeanUtils;
5 |
6 | import java.util.List;
7 |
8 | public class PageUtils {
9 |
10 | public static PageInfo merge(PageInfo pageInfo, List list) {
11 | PageInfo target = new PageInfo();
12 | BeanUtils.copyProperties(pageInfo, target);
13 | target.setList(list);
14 | return target;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/java/com/wangzaiplus/test/util/MailUtilTest.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class MailUtilTest {
11 |
12 | @Test
13 | public void send() {
14 | }
15 |
16 | @Test
17 | public void sendAttachment() {
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/annotation/AccessLimit.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * 在需要保证 接口防刷限流 的Controller的方法上使用此注解
10 | */
11 | @Target({ElementType.METHOD})
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface AccessLimit {
14 |
15 | int maxCount();// 最大访问次数
16 |
17 | int seconds();// 固定时间, 单位: s
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/FundService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.dto.FundDto;
5 | import com.wangzaiplus.test.dto.SearchFormDto;
6 |
7 | import java.util.List;
8 |
9 | public interface FundService {
10 |
11 | ServerResponse rank(FundDto fundDto);
12 |
13 | ServerResponse search(SearchFormDto searchFormDto);
14 |
15 | void update(List list);
16 |
17 | ServerResponse getSearchFormDto();
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/MsgLogMapper.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mapper;
2 |
3 | import com.wangzaiplus.test.pojo.MsgLog;
4 | import com.wangzaiplus.test.service.batch.BatchProcessMapper;
5 |
6 | import java.util.List;
7 |
8 | public interface MsgLogMapper extends BatchProcessMapper {
9 |
10 | void insert(MsgLog msgLog);
11 |
12 | void updateStatus(MsgLog msgLog);
13 |
14 | List selectTimeoutMsg();
15 |
16 | void updateTryCount(MsgLog msgLog);
17 |
18 | MsgLog selectByPrimaryKey(String msgId);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/dynamicproxy/PayServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.dynamicproxy;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class PayServiceImpl implements PayService {
6 |
7 | @Override
8 | public void pay(String username, BigDecimal money) {
9 | System.out.println(username + "支付了" + money + "元钱");
10 | }
11 |
12 | @Override
13 | public void a() {
14 | System.out.println("a");
15 | }
16 |
17 | @Override
18 | public void b() {
19 | System.out.println("b");
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/strategy/CalculateStrategy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.strategy;
2 |
3 | import com.google.common.collect.Maps;
4 |
5 | import java.util.Map;
6 |
7 | public class CalculateStrategy {
8 |
9 | private static Map map = Maps.newConcurrentMap();
10 |
11 | public static void register(Integer type, CalculateService calculateService) {
12 | map.put(type, calculateService);
13 | }
14 |
15 | public static CalculateService getCalculateService(Integer type) {
16 | return map.get(type);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/staticproxy/PayProxy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.staticproxy;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class PayProxy implements PayService {
6 |
7 | private PayService payService;
8 |
9 | public PayProxy(PayService payService) {
10 | this.payService = payService;
11 | }
12 |
13 | @Override
14 | public void pay(String username, BigDecimal money) {
15 | System.out.println(username + "发起支付...");
16 |
17 | payService.pay(username, money);
18 |
19 | System.out.println("支付状态: 成功");
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/PayTypeEnum.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory;
2 |
3 | /**
4 | * 支付方式
5 | */
6 | public enum PayTypeEnum {
7 |
8 | ALI_PAY("1", "支付宝支付"),
9 | WE_CHAT_PAY("2", "微信支付"),
10 | UNION_PAY("3", "银联支付"),
11 | ;
12 |
13 | private String code;
14 | private String msg;
15 |
16 | PayTypeEnum(String code, String msg) {
17 | this.code = code;
18 | this.msg = msg;
19 | }
20 |
21 | public String getCode() {
22 | return code;
23 | }
24 |
25 | public String getMsg() {
26 | return msg;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/pojo/LoginLog.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.pojo;
2 |
3 | import lombok.*;
4 |
5 | import java.io.Serializable;
6 | import java.util.Date;
7 |
8 | @Getter
9 | @Setter
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | @ToString
13 | public class LoginLog implements Serializable {
14 |
15 | private static final long serialVersionUID = 9035584359424322830L;
16 |
17 | private Integer id;
18 | private Integer userId;
19 | private Integer type;
20 | private String description;
21 | private Date createTime;
22 | private Date updateTime;
23 | private String msgId;// 消息id
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/pojo/User.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.pojo;
2 |
3 | import lombok.*;
4 |
5 | import java.util.Date;
6 |
7 | @Getter
8 | @Setter
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @ToString
12 | @Builder
13 | public class User {
14 |
15 | private Integer id;
16 | private String username;
17 | private String password;
18 | private String passwordSalt;
19 | private String ip;
20 | private String mobile;
21 | private String mail;
22 | private Integer type;
23 | private Integer status;
24 | private Integer isDeleted;
25 | private Date createdTime;
26 | private Date updatedTime;
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/dto/UserDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.dto;
2 |
3 | import lombok.*;
4 |
5 | import java.util.Date;
6 |
7 | @Getter
8 | @Setter
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @ToString
12 | @Builder
13 | public class UserDto {
14 |
15 | private Integer id;
16 | private String username;
17 | private String password;
18 | private String passwordSalt;
19 | private String ip;
20 | private String mobile;
21 | private String mail;
22 | private Integer type;
23 | private Integer status;
24 | private Integer isDeleted;
25 | private Date createdTime;
26 | private Date updatedTime;
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/dynamicproxy/Test.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.dynamicproxy;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class Test {
6 |
7 | public static void main(String[] args) {
8 | // PayService service = new PayServiceImpl();
9 | // PayProxy payProxy = new PayProxy(service);
10 | // PayService payService = (PayService) payProxy.getProxy();
11 | // payService.pay("马云", BigDecimal.TEN);
12 |
13 | PayProxy payProxy2 = new PayProxy(new PayServiceImpl());
14 | PayServiceImpl payService2 = (PayServiceImpl) payProxy2.getPayProxy();
15 | payService2.pay("马云2", BigDecimal.TEN);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/pojo/Mail.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.pojo;
2 |
3 | import lombok.*;
4 |
5 | import javax.validation.constraints.NotBlank;
6 | import javax.validation.constraints.Pattern;
7 |
8 | @Getter
9 | @Setter
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | @ToString
13 | @Builder
14 | public class Mail {
15 |
16 | @Pattern(regexp = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$", message = "邮箱格式不正确")
17 | private String to;
18 |
19 | @NotBlank(message = "标题不能为空")
20 | private String title;
21 |
22 | @NotBlank(message = "正文不能为空")
23 | private String content;
24 |
25 | private String msgId;// 消息id
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.pojo.User;
5 |
6 | import java.util.List;
7 |
8 | public interface UserService {
9 |
10 | List getAll();
11 |
12 | User getOne(Integer id);
13 |
14 | void add(User user);
15 |
16 | void update(User user);
17 |
18 | void delete(Integer id);
19 |
20 | User getByUsernameAndPassword(String username, String password);
21 |
22 | ServerResponse login(String username, String password);
23 |
24 | void batchInsert(List list);
25 |
26 | void batchUpdate(List list);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/strategy/AddCalculateServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.strategy;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import org.springframework.beans.factory.InitializingBean;
5 | import org.springframework.stereotype.Service;
6 |
7 | @Service("addCalculateServiceImpl")
8 | public class AddCalculateServiceImpl implements CalculateService, InitializingBean {
9 |
10 | @Override
11 | public int calculate(int a, int b) {
12 | return a + b;
13 | }
14 |
15 | @Override
16 | public void afterPropertiesSet() throws Exception {
17 | CalculateStrategy.register(Constant.CalculateTypeEnum.ADD.getType(), this);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/simplefactory/PayFactory.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory.simplefactory;
2 |
3 | import com.wangzaiplus.test.designpattern.factory.*;
4 |
5 | public class PayFactory {
6 |
7 | public static IPay createPay(String payType) {
8 | if (PayTypeEnum.ALI_PAY.getCode().equals(payType)) {
9 | return new ALiPay();
10 | }
11 |
12 | if (PayTypeEnum.WE_CHAT_PAY.getCode().equals(payType)) {
13 | return new WeChatPay();
14 | }
15 |
16 | if (PayTypeEnum.UNION_PAY.getCode().equals(payType)) {
17 | return new UnionPay();
18 | }
19 |
20 | return null;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/strategy/DivideCalculateServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.strategy;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import org.springframework.beans.factory.InitializingBean;
5 | import org.springframework.stereotype.Service;
6 |
7 | @Service("divideCalculateServiceImpl")
8 | public class DivideCalculateServiceImpl implements CalculateService, InitializingBean {
9 |
10 | @Override
11 | public int calculate(int a, int b) {
12 | return a / b;
13 | }
14 |
15 | @Override
16 | public void afterPropertiesSet() throws Exception {
17 | CalculateStrategy.register(Constant.CalculateTypeEnum.DIVIDE.getType(), this);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/strategy/MultiplyCalculateServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.strategy;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import org.springframework.beans.factory.InitializingBean;
5 | import org.springframework.stereotype.Service;
6 |
7 | @Service("multiplyCalculateServiceImpl")
8 | public class MultiplyCalculateServiceImpl implements CalculateService, InitializingBean {
9 |
10 | @Override
11 | public int calculate(int a, int b) {
12 | return a * b;
13 | }
14 |
15 | @Override
16 | public void afterPropertiesSet() throws Exception {
17 | CalculateStrategy.register(Constant.CalculateTypeEnum.MULTIPLY.getType(), this);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/strategy/SubtractCalculateServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.strategy;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import org.springframework.beans.factory.InitializingBean;
5 | import org.springframework.stereotype.Service;
6 |
7 | @Service("subtractCalculateServiceImpl")
8 | public class SubtractCalculateServiceImpl implements CalculateService, InitializingBean {
9 |
10 | @Override
11 | public int calculate(int a, int b) {
12 | return a - b;
13 | }
14 |
15 | @Override
16 | public void afterPropertiesSet() throws Exception {
17 | CalculateStrategy.register(Constant.CalculateTypeEnum.SUBTRACT.getType(), this);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mapper;
2 |
3 | import com.wangzaiplus.test.pojo.User;
4 | import com.wangzaiplus.test.service.batch.BatchProcessMapper;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | public interface UserMapper extends BatchProcessMapper {
10 |
11 | List selectAll();
12 |
13 | User selectOne(Integer id);
14 |
15 | void insert(User user);
16 |
17 | void update(User user);
18 |
19 | void delete(Integer id);
20 |
21 | User selectByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
22 |
23 | User selectByUsername(@Param("username") String username);
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/TokenController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.service.TokenService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 |
10 | @RestController
11 | @RequestMapping("/token")
12 | public class TokenController {
13 |
14 | @Autowired
15 | private TokenService tokenService;
16 |
17 | @GetMapping
18 | public ServerResponse token() {
19 | return tokenService.createToken();
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/impl/LoginLogServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.impl;
2 |
3 | import com.wangzaiplus.test.mapper.LoginLogMapper;
4 | import com.wangzaiplus.test.pojo.LoginLog;
5 | import com.wangzaiplus.test.service.LoginLogService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Service;
8 |
9 | @Service
10 | public class LoginLogServiceImpl implements LoginLogService {
11 |
12 | @Autowired
13 | private LoginLogMapper loginLogMapper;
14 |
15 | @Override
16 | public void insert(LoginLog loginLog) {
17 | loginLogMapper.insert(loginLog);
18 | }
19 |
20 | @Override
21 | public LoginLog selectByMsgId(String msgId) {
22 | return loginLogMapper.selectByMsgId(msgId);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/threadpool/TestJob.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.threadpool;
2 |
3 | import java.util.concurrent.CountDownLatch;
4 |
5 | public class TestJob implements Runnable{
6 |
7 | private CountDownLatch countDownLatch;
8 |
9 | public TestJob(CountDownLatch countDownLatch) {
10 | this.countDownLatch = countDownLatch;
11 | }
12 |
13 | @Override
14 | public void run() {
15 | try {
16 | System.out.println("开始干活...");
17 | Thread.sleep(3000);
18 | Test.a = Test.a + 1;
19 | System.out.println("干完了.a: " + Test.a + ", " + countDownLatch.getCount());
20 | countDownLatch.countDown();
21 | } catch (InterruptedException e) {
22 | e.printStackTrace();
23 | }
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/threadpool/ThreadPoolFactory.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.threadpool;
2 |
3 | import java.util.concurrent.ArrayBlockingQueue;
4 | import java.util.concurrent.ThreadPoolExecutor;
5 | import java.util.concurrent.TimeUnit;
6 |
7 | public class ThreadPoolFactory {
8 |
9 | private static final int testCorePoolSize = 2;
10 | private static final int testMaxPoolSize = 4;
11 | private static final long testKeepAliveTime = 2;
12 | private static final int testBlockingQueueSize = 20;
13 |
14 | public static ThreadPoolExecutor testThreadPool() {
15 | return new ThreadPoolExecutor(testCorePoolSize,
16 | testMaxPoolSize,
17 | testKeepAliveTime,
18 | TimeUnit.SECONDS, new ArrayBlockingQueue(testBlockingQueueSize));
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/resources/db/dml_create_user_04.sql:
--------------------------------------------------------------------------------
1 | drop table if exists t_user;
2 |
3 | create table t_user(
4 | id int not null auto_increment comment '主键',
5 | username varchar(255) not null comment '用户名',
6 | password varchar(255) not null comment '密码',
7 | password_salt varchar(255) not null comment '密码随机盐值',
8 | ip varchar(255) comment 'IP地址',
9 | mobile varchar(11) comment '手机号',
10 | mail varchar(255) comment '邮箱',
11 | type int default 0 not null comment '类型(0:普通用户,1:超级管理员)',
12 | status int default 0 not null comment '状态(0:正常,1:黑名单,2:已注销)',
13 | is_deleted int default 0 not null comment '是否删除(0:有效,1:无效删除)',
14 | created_time datetime default now() not null comment '创建时间',
15 | updated_time datetime default now() not null comment '更新时间',
16 | primary key(id)
17 | ) comment = '用户表';
18 |
19 | create unique index unq_idx_username on t_user(username);
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/exception/ServiceException.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.exception;
2 |
3 | /**
4 | * 业务逻辑异常
5 | */
6 | public class ServiceException extends RuntimeException{
7 |
8 | private String code;
9 | private String msg;
10 |
11 | public ServiceException() {
12 | }
13 |
14 | public ServiceException(String msg) {
15 | this.msg = msg;
16 | }
17 |
18 | public ServiceException(String code, String msg) {
19 | this.code = code;
20 | this.msg = msg;
21 | }
22 |
23 | public String getCode() {
24 | return code;
25 | }
26 |
27 | public void setCode(String code) {
28 | this.code = code;
29 | }
30 |
31 | public String getMsg() {
32 | return msg;
33 | }
34 |
35 | public void setMsg(String msg) {
36 | this.msg = msg;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/pojo/Fund.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.pojo;
2 |
3 | import lombok.*;
4 |
5 | import java.math.BigDecimal;
6 | import java.util.Date;
7 |
8 | @Getter
9 | @Setter
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | @ToString
13 | @Builder
14 | public class Fund {
15 |
16 | private Integer id;
17 | private String code;
18 | private String name;
19 | private BigDecimal netValue;
20 | private String yieldOfOneYear;
21 | private String yieldOfTwoYear;
22 | private String yieldOfThreeYear;
23 | private String yieldOfFiveYear;
24 | private int type;
25 | private Date establishedTime;
26 | private String asset;
27 | private String manager;
28 | private Integer status;
29 | private Integer isDeleted;
30 | private Date createdTime;
31 | private Date updatedTime;
32 |
33 | private Integer tempRank;
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/FundMapper.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mapper;
2 |
3 | import com.wangzaiplus.test.dto.FundDto;
4 | import com.wangzaiplus.test.pojo.Fund;
5 | import com.wangzaiplus.test.service.batch.BatchProcessMapper;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import java.util.List;
9 |
10 | @Repository
11 | public interface FundMapper extends BatchProcessMapper {
12 |
13 | List selectAll();
14 |
15 | Fund selectOne(Integer id);
16 |
17 | void insert(Fund fund);
18 |
19 | void update(Fund fund);
20 |
21 | void delete(Integer id);
22 |
23 | Fund selectByCodeAndType(Fund fund);
24 |
25 | List selectByType(FundDto fundDto);
26 |
27 | List selectTempRankByType(FundDto fundDto);
28 |
29 | List selectFundTypeList();
30 |
31 | List selectByNameOrCode(FundDto fundDto);
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/ConfigUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import java.io.FileNotFoundException;
4 | import java.io.IOException;
5 | import java.util.Properties;
6 |
7 | public class ConfigUtil {
8 |
9 | public ConfigUtil() {
10 | }
11 |
12 | private static Properties props = new Properties();
13 |
14 | static {
15 | try {
16 | props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties"));
17 | } catch (FileNotFoundException e) {
18 | e.printStackTrace();
19 | } catch (IOException e) {
20 | e.printStackTrace();
21 | }
22 | }
23 |
24 | public static String getValue(String key) {
25 | return props.getProperty(key);
26 | }
27 |
28 | public static void updateProperties(String key, String value) {
29 | props.setProperty(key, value);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/com/wangzaiplus/test/controller/test/TestControllerTest.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller.test;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.boot.test.web.client.TestRestTemplate;
8 | import org.springframework.test.context.junit4.SpringRunner;
9 |
10 | @RunWith(SpringRunner.class)
11 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
12 | public class TestControllerTest {
13 |
14 | @Autowired
15 | private TestRestTemplate testRestTemplate;
16 |
17 | @Test
18 | public void testLogin() {
19 | for (int i = 0; i < 100; i++) {
20 | testRestTemplate.postForObject("/user/login?username={username}&password={password}", null, String.class, "wangzaiplus", "123456");
21 | }
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/config/RedissonConfig.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.config;
2 |
3 | import org.redisson.Redisson;
4 | import org.redisson.api.RedissonClient;
5 | import org.redisson.config.Config;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class RedissonConfig {
12 |
13 | @Value("${spring.redis.host}")
14 | private String host;
15 |
16 | @Value("${spring.redis.port}")
17 | private String port;
18 |
19 | @Value("${spring.redis.password}")
20 | private String password;
21 |
22 | @Bean
23 | public RedissonClient redissonClient() {
24 | Config config = new Config();
25 | config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
26 | return Redisson.create(config);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.dto.UserDto;
5 | import com.wangzaiplus.test.service.LoginService;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.PostMapping;
9 | import org.springframework.web.bind.annotation.RequestBody;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | @RestController
14 | @RequestMapping("/login")
15 | @Slf4j
16 | public class LoginController {
17 |
18 | @Autowired
19 | private LoginService loginService;
20 |
21 | @PostMapping("/doLogin")
22 | public ServerResponse doLogin(@RequestBody UserDto userDto) {
23 | return loginService.doLogin(userDto);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/factory/simplefactory/PayService.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.factory.simplefactory;
2 |
3 | import com.wangzaiplus.test.designpattern.factory.IPay;
4 | import com.wangzaiplus.test.exception.ServiceException;
5 | import org.apache.commons.lang3.StringUtils;
6 |
7 | public class PayService {
8 |
9 | public void pay(String payType) {
10 | if (StringUtils.isBlank(payType)) {
11 | throw new ServiceException("支付方式异常");
12 | }
13 |
14 | boolean isPaySuccess = isPaySuccess(payType);
15 | if (isPaySuccess) {
16 | // 巴拉巴拉
17 | } else {
18 | // 巴拉巴拉
19 | }
20 | }
21 |
22 | private boolean isPaySuccess(String payType) {
23 | IPay iPay = PayFactory.createPay(payType);
24 | if (null == iPay) {
25 | throw new ServiceException("支付方式异常");
26 | }
27 |
28 | return iPay.pay();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/ListUtils.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import org.apache.commons.collections4.CollectionUtils;
5 |
6 | import java.util.List;
7 | import java.util.stream.Collectors;
8 |
9 | public class ListUtils {
10 |
11 | public List intersection(List> lists, boolean removeDuplication) {
12 | if (CollectionUtils.isEmpty(lists)) {
13 | return null;
14 | }
15 |
16 | int size = lists.size();
17 | List list = lists.get(Constant.INDEX_ZERO);
18 | if (size == Constant.NUMBER_ONE) {
19 | return list;
20 | }
21 |
22 | for (int i = 1; i < size; i++) {
23 | list.retainAll(lists.get(i));
24 | }
25 |
26 | if (removeDuplication) {
27 | list = list.stream().distinct().collect(Collectors.toList());
28 | }
29 |
30 | return list;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/consumer/LoginLogConsumer.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq.consumer;
2 |
3 | import com.rabbitmq.client.Channel;
4 | import com.wangzaiplus.test.mq.BaseConsumer;
5 | import com.wangzaiplus.test.mq.MessageHelper;
6 | import com.wangzaiplus.test.pojo.LoginLog;
7 | import com.wangzaiplus.test.service.LoginLogService;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.springframework.amqp.core.Message;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.stereotype.Component;
12 |
13 | @Component
14 | @Slf4j
15 | public class LoginLogConsumer implements BaseConsumer {
16 |
17 | @Autowired
18 | private LoginLogService loginLogService;
19 |
20 | @Override
21 | public void consume(Message message, Channel channel) {
22 | log.info("收到消息: {}", message.toString());
23 | LoginLog loginLog = MessageHelper.msgToObj(message, LoginLog.class);
24 | loginLogService.insert(loginLog);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/exception/MyControllerAdvice.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.exception;
2 |
3 | import com.wangzaiplus.test.common.ResponseCode;
4 | import com.wangzaiplus.test.common.ServerResponse;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.web.bind.annotation.ControllerAdvice;
7 | import org.springframework.web.bind.annotation.ExceptionHandler;
8 | import org.springframework.web.bind.annotation.ResponseBody;
9 |
10 | @ControllerAdvice
11 | @Slf4j
12 | public class MyControllerAdvice {
13 |
14 | @ResponseBody
15 | @ExceptionHandler(ServiceException.class)
16 | public ServerResponse serviceExceptionHandler(ServiceException se) {
17 | return ServerResponse.error(se.getMsg());
18 | }
19 |
20 | @ResponseBody
21 | @ExceptionHandler(Exception.class)
22 | public ServerResponse exceptionHandler(Exception e) {
23 | log.error("Exception: ", e);
24 | return ServerResponse.error(ResponseCode.SERVER_ERROR.getMsg());
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/threadpool/LockSupportTest.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.threadpool;
2 |
3 | import java.util.concurrent.locks.LockSupport;
4 |
5 | public class LockSupportTest {
6 |
7 | private static final char[] a = "abcd".toCharArray();
8 | private static final char[] A = "ABCD".toCharArray();
9 |
10 | private static Thread aThread;
11 | private static Thread AThread;
12 |
13 | public static void main(String[] args) {
14 | aThread = new Thread(() -> {
15 | for (char c : a) {
16 | System.out.println(c);
17 | LockSupport.unpark(AThread);
18 | LockSupport.park();
19 | }
20 | });
21 |
22 | AThread = new Thread(() -> {
23 | for (char c : A) {
24 | LockSupport.park();
25 | System.out.println(c);
26 | LockSupport.unpark(aThread);
27 | }
28 | });
29 |
30 | aThread.start();
31 | AThread.start();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/SpringContextUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.ApplicationContextAware;
6 | import org.springframework.stereotype.Component;
7 |
8 | @Component
9 | public class SpringContextUtil implements ApplicationContextAware {
10 |
11 | private static ApplicationContext applicationContext;
12 |
13 | @Override
14 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
15 | SpringContextUtil.applicationContext = applicationContext;
16 | }
17 |
18 | public static ApplicationContext getApplicationContext() {
19 | return applicationContext;
20 | }
21 |
22 | public static Object getBean(String name) {
23 | return applicationContext.getBean(name);
24 | }
25 |
26 | public static T getBean(Class clazz) {
27 | return applicationContext.getBean(clazz);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/threadpool/Test.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.threadpool;
2 |
3 | import java.util.concurrent.CountDownLatch;
4 | import java.util.concurrent.ThreadPoolExecutor;
5 |
6 | public class Test {
7 |
8 | public static volatile int a = 0;
9 |
10 | public static void main(String[] args) {
11 | doJob();
12 | }
13 |
14 | private static void doJob() {
15 | CountDownLatch countDownLatch = new CountDownLatch(5);
16 | ThreadPoolExecutor pool = ThreadPoolFactory.testThreadPool();
17 | for (int i = 0; i < 5; i++) {
18 | System.out.println(a);
19 | if (a >= 3) {
20 | System.out.println("over");
21 | break;
22 | }
23 |
24 | pool.execute(new TestJob(countDownLatch));
25 | }
26 |
27 | try {
28 | countDownLatch.await();
29 | } catch (InterruptedException e) {
30 | e.printStackTrace();
31 | }
32 | pool.shutdown();
33 |
34 | System.out.println("doJob end");
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/consumer/MailConsumer.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq.consumer;
2 |
3 | import com.rabbitmq.client.Channel;
4 | import com.wangzaiplus.test.exception.ServiceException;
5 | import com.wangzaiplus.test.mq.BaseConsumer;
6 | import com.wangzaiplus.test.mq.MessageHelper;
7 | import com.wangzaiplus.test.pojo.Mail;
8 | import com.wangzaiplus.test.util.MailUtil;
9 | import lombok.extern.slf4j.Slf4j;
10 | import org.springframework.amqp.core.Message;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.stereotype.Component;
13 |
14 | @Component
15 | @Slf4j
16 | public class MailConsumer implements BaseConsumer {
17 |
18 | @Autowired
19 | private MailUtil mailUtil;
20 |
21 | public void consume(Message message, Channel channel) {
22 | Mail mail = MessageHelper.msgToObj(message, Mail.class);
23 | log.info("收到消息: {}", mail.toString());
24 |
25 | boolean success = mailUtil.send(mail);
26 | if (!success) {
27 | throw new ServiceException("send mail error");
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/dynamicproxy/PayProxy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.dynamicproxy;
2 |
3 | import java.lang.reflect.InvocationHandler;
4 | import java.lang.reflect.Method;
5 | import java.lang.reflect.Proxy;
6 |
7 | public class PayProxy {
8 |
9 | private Object target;
10 |
11 | public PayProxy(Object target) {
12 | this.target = target;
13 | }
14 |
15 | public Object getPayProxy() {
16 | ClassLoader classLoader = target.getClass().getClassLoader();
17 | Class[] interfaces = target.getClass().getInterfaces();
18 |
19 | Object proxy = Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
20 | @Override
21 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
22 | System.out.println("start...");
23 |
24 | Object result = method.invoke(target, args);
25 |
26 | System.out.println("stop");
27 | return result;
28 | }
29 | });
30 |
31 | return proxy;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/resources/db/dml_create_fund_02.sql:
--------------------------------------------------------------------------------
1 | drop table if exists fund;
2 |
3 | create table fund(
4 | id int not null auto_increment comment '主键',
5 | code varchar(255) not null comment '基金代码',
6 | name varchar(255) not null comment '基金名称',
7 | net_value decimal(10, 4) not null comment '单位净值',
8 | yield_of_one_year varchar(255) not null comment '近1年收益率',
9 | yield_of_two_year varchar(255) not null comment '近2年收益率',
10 | yield_of_three_year varchar(255) not null comment '近3年收益率',
11 | yield_of_five_year varchar(255) not null comment '近5年收益率',
12 | type int not null comment '基金类型(1:股票型,2:混合型,3:债券型,4:指数型,5:QDII)',
13 | established_time datetime comment '成立时间',
14 | asset varchar(255) comment '基金规模,资产',
15 | manager varchar(255) comment '基金经理',
16 | status int default 1 not null comment '基金状态(1:正常开放,2:暂停交易)',
17 | is_deleted int default 0 not null comment '是否删除(0:有效,1:无效删除)',
18 | created_time datetime default now() not null comment '创建时间',
19 | updated_time datetime default now() not null comment '更新时间',
20 | primary key(id)
21 | ) comment = '基金表';
22 |
23 | create unique index unq_idx_type_code on fund(type, code);
24 | create index idx_type_name_code on fund(type, name, code);
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/MessageHelper.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq;
2 |
3 | import com.wangzaiplus.test.util.JsonUtil;
4 | import org.springframework.amqp.core.Message;
5 | import org.springframework.amqp.core.MessageBuilder;
6 | import org.springframework.amqp.core.MessageDeliveryMode;
7 | import org.springframework.amqp.core.MessageProperties;
8 |
9 | public class MessageHelper {
10 |
11 | public static Message objToMsg(Object obj) {
12 | if (null == obj) {
13 | return null;
14 | }
15 |
16 | Message message = MessageBuilder.withBody(JsonUtil.objToStr(obj).getBytes()).build();
17 | message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);// 消息持久化
18 | message.getMessageProperties().setContentType(MessageProperties.CONTENT_TYPE_JSON);
19 |
20 | return message;
21 | }
22 |
23 | public static T msgToObj(Message message, Class clazz) {
24 | if (null == message || null == clazz) {
25 | return null;
26 | }
27 |
28 | String str = new String(message.getBody());
29 | T obj = JsonUtil.strToObj(str, clazz);
30 |
31 | return obj;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/designpattern/strategy/PayContext.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.designpattern.strategy;
2 |
3 | import com.wangzaiplus.test.designpattern.factory.PayTypeEnum;
4 | import com.wangzaiplus.test.exception.ServiceException;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.stereotype.Component;
7 |
8 | import java.util.Map;
9 | import java.util.concurrent.ConcurrentHashMap;
10 |
11 | //@Component
12 | public class PayContext {
13 |
14 | // @Autowired
15 | // private Map map;
16 |
17 | private static Map map2 = new ConcurrentHashMap<>();
18 | static {
19 | map2.put(PayTypeEnum.ALI_PAY.getCode(), new AliPayStrategy());
20 | map2.put(PayTypeEnum.WE_CHAT_PAY.getCode(), new WxPayStrategy());
21 | map2.put(PayTypeEnum.UNION_PAY.getCode(), new UnionPayStrategy());
22 | }
23 |
24 | public void pay(String payType, String userId) {
25 | PayStrategy payStrategy = map2.get(payType);
26 | if (null == payStrategy) {
27 | throw new ServiceException("payType: " + payType + " not supported");
28 | }
29 |
30 | payStrategy.pay(userId);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/UserMapperWithAnnotation.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mapper;
2 |
3 | import com.wangzaiplus.test.pojo.User;
4 | import org.apache.ibatis.annotations.*;
5 | import org.apache.ibatis.type.JdbcType;
6 |
7 | import java.util.List;
8 |
9 | public interface UserMapperWithAnnotation {
10 |
11 | @Select("select * from user")
12 | @Results({
13 | @Result(property = "username", column = "username", jdbcType = JdbcType.VARCHAR),
14 | @Result(property = "password", column = "password")
15 | })
16 | List selectAll();
17 |
18 | @Select("select * from user where id = #{id}")
19 | @Results({
20 | @Result(property = "username", column = "username", jdbcType = JdbcType.VARCHAR),
21 | @Result(property = "password", column = "password")
22 | })
23 | User selectOne(Integer id);
24 |
25 | @Insert("insert into user(username, password) values(#{username}, #{password})")
26 | void insert(User user);
27 |
28 | @Update("update user set username=#{username}, password=#{password} where id = #{id}")
29 | void update(User user);
30 |
31 | @Delete("delete from user where id = #{id}")
32 | void delete(Integer id);
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/pojo/MsgLog.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.pojo;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import com.wangzaiplus.test.util.JodaTimeUtil;
5 | import com.wangzaiplus.test.util.JsonUtil;
6 | import lombok.*;
7 |
8 | import java.util.Date;
9 |
10 | @Getter
11 | @Setter
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @ToString
15 | public class MsgLog {
16 |
17 | private String msgId;
18 | private String msg;
19 | private String exchange;
20 | private String routingKey;
21 | private Integer status;
22 | private Integer tryCount;
23 | private Date nextTryTime;
24 | private Date createTime;
25 | private Date updateTime;
26 |
27 | public MsgLog(String msgId, Object msg, String exchange, String routingKey) {
28 | this.msgId = msgId;
29 | this.msg = JsonUtil.objToStr(msg);
30 | this.exchange = exchange;
31 | this.routingKey = routingKey;
32 |
33 | this.status = Constant.MsgLogStatus.DELIVERING;
34 | this.tryCount = 0;
35 |
36 | Date date = new Date();
37 | this.createTime = date;
38 | this.updateTime = date;
39 | this.nextTryTime = (JodaTimeUtil.plusMinutes(date, 1));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/ViewUtils.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 |
5 | public class ViewUtils {
6 |
7 | private static final String VIEW_PREFIX = "/templates";
8 | private static final String VIEW_SUFFIX = ".html";
9 |
10 | private static final String ERROR = "error";
11 | private static final String NOT_FOUND = "404";
12 |
13 | private static final String TO_ERROR = "/common/error";
14 | private static final String TO_404 = "/common/404";
15 |
16 | private static final String ERROR_PAGE = VIEW_PREFIX + TO_ERROR + VIEW_SUFFIX;
17 | private static final String NOT_FOUND_PAGE = VIEW_PREFIX + TO_404 + VIEW_SUFFIX;
18 |
19 | private static final String PATH_SEPARATOR = "/";
20 |
21 | public static String to(String view) {
22 | if (StringUtils.isBlank(view) || ERROR.equals(view)) {
23 | return ERROR_PAGE;
24 | }
25 |
26 | if (NOT_FOUND.equals(view)) {
27 | return NOT_FOUND_PAGE;
28 | }
29 |
30 | if (!view.startsWith(PATH_SEPARATOR)) {
31 | view = PATH_SEPARATOR + view;
32 | }
33 |
34 | return VIEW_PREFIX + view + VIEW_SUFFIX;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/IpUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | public class IpUtil {
6 |
7 | /**
8 | * 获取客户端真实ip地址
9 | *
10 | * @param request
11 | * @return
12 | */
13 | public static String getIpAddress(HttpServletRequest request) {
14 | String ip = request.getHeader("x-forwarded-for");
15 |
16 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
17 | ip = request.getHeader("Proxy-Client-IP");
18 | }
19 |
20 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
21 | ip = request.getHeader("WL-Proxy-Client-IP");
22 | }
23 |
24 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
25 | ip = request.getHeader("HTTP_CLIENT_IP");
26 | }
27 |
28 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
29 | ip = request.getHeader("HTTP_X_FORWARDED_FOR");
30 | }
31 |
32 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
33 | ip = request.getRemoteAddr();
34 | }
35 |
36 | return ip;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/common/ResponseCode.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.common;
2 |
3 | /**
4 | * 响应状态码
5 | */
6 | public enum ResponseCode {
7 |
8 | // 系统模块
9 | SUCCESS(0, "操作成功"),
10 | ERROR(1, "操作失败"),
11 | SERVER_ERROR(500, "服务器异常"),
12 |
13 | // 通用模块 1xxxx
14 | ILLEGAL_ARGUMENT(10000, "参数不合法"),
15 | REPETITIVE_OPERATION(10001, "请勿重复操作"),
16 | ACCESS_LIMIT(10002, "请求太频繁, 请稍后再试"),
17 | MAIL_SEND_SUCCESS(10003, "邮件发送成功"),
18 |
19 | // 用户模块 2xxxx
20 | NEED_LOGIN(20001, "登录失效"),
21 | USERNAME_OR_PASSWORD_EMPTY(20002, "用户名或密码不能为空"),
22 | USERNAME_OR_PASSWORD_WRONG(20003, "用户名或密码错误"),
23 | USER_NOT_EXISTS(20004, "用户不存在"),
24 | WRONG_PASSWORD(20005, "密码错误"),
25 |
26 | // 订单模块 4xxxx
27 |
28 | ;
29 |
30 | ResponseCode(Integer code, String msg) {
31 | this.code = code;
32 | this.msg = msg;
33 | }
34 |
35 | private Integer code;
36 |
37 | private String msg;
38 |
39 | public Integer getCode() {
40 | return code;
41 | }
42 |
43 | public void setCode(Integer code) {
44 | this.code = code;
45 | }
46 |
47 | public String getMsg() {
48 | return msg;
49 | }
50 |
51 | public void setMsg(String msg) {
52 | this.msg = msg;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/listener/MailListener.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq.listener;
2 |
3 | import com.rabbitmq.client.Channel;
4 | import com.wangzaiplus.test.config.RabbitConfig;
5 | import com.wangzaiplus.test.mq.BaseConsumer;
6 | import com.wangzaiplus.test.mq.BaseConsumerProxy;
7 | import com.wangzaiplus.test.mq.consumer.MailConsumer;
8 | import com.wangzaiplus.test.service.MsgLogService;
9 | import org.springframework.amqp.core.Message;
10 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.stereotype.Component;
13 |
14 | import java.io.IOException;
15 |
16 | @Component
17 | public class MailListener {
18 |
19 | @Autowired
20 | private MailConsumer mailConsumer;
21 |
22 | @Autowired
23 | private MsgLogService msgLogService;
24 |
25 | @RabbitListener(queues = RabbitConfig.MAIL_QUEUE_NAME)
26 | public void consume(Message message, Channel channel) throws IOException {
27 | BaseConsumerProxy baseConsumerProxy = new BaseConsumerProxy(mailConsumer, msgLogService);
28 | BaseConsumer proxy = (BaseConsumer) baseConsumerProxy.getProxy();
29 | if (null != proxy) {
30 | proxy.consume(message, channel);
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/listener/LoginLogListener.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq.listener;
2 |
3 | import com.rabbitmq.client.Channel;
4 | import com.wangzaiplus.test.config.RabbitConfig;
5 | import com.wangzaiplus.test.mq.BaseConsumer;
6 | import com.wangzaiplus.test.mq.BaseConsumerProxy;
7 | import com.wangzaiplus.test.mq.consumer.LoginLogConsumer;
8 | import com.wangzaiplus.test.service.MsgLogService;
9 | import org.springframework.amqp.core.Message;
10 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.stereotype.Component;
13 |
14 | import java.io.IOException;
15 |
16 | @Component
17 | public class LoginLogListener {
18 |
19 | @Autowired
20 | private LoginLogConsumer loginLogConsumer;
21 |
22 | @Autowired
23 | private MsgLogService msgLogService;
24 |
25 | @RabbitListener(queues = RabbitConfig.LOGIN_LOG_QUEUE_NAME)
26 | public void consume(Message message, Channel channel) throws IOException {
27 | BaseConsumerProxy baseConsumerProxy = new BaseConsumerProxy(loginLogConsumer, msgLogService);
28 | BaseConsumer proxy = (BaseConsumer) baseConsumerProxy.getProxy();
29 | if (null != proxy) {
30 | proxy.consume(message, channel);
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/LoginServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service;
2 |
3 | import com.wangzaiplus.test.common.ResponseCode;
4 | import com.wangzaiplus.test.common.ServerResponse;
5 | import com.wangzaiplus.test.dto.UserDto;
6 | import com.wangzaiplus.test.mapper.UserMapper;
7 | import com.wangzaiplus.test.pojo.User;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.apache.commons.lang3.StringUtils;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.stereotype.Service;
12 |
13 | @Service
14 | @Slf4j
15 | public class LoginServiceImpl implements LoginService {
16 |
17 | @Autowired
18 | private UserMapper userMapper;
19 |
20 | @Override
21 | public ServerResponse doLogin(UserDto userDto) {
22 | String username = userDto.getUsername();
23 | String password = userDto.getPassword();
24 |
25 | if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
26 | return ServerResponse.error(ResponseCode.USERNAME_OR_PASSWORD_EMPTY.getMsg());
27 | }
28 |
29 | User user = userMapper.selectByUsernameAndPassword(username, password);
30 | if (null == user) {
31 | return ServerResponse.error(ResponseCode.USERNAME_OR_PASSWORD_WRONG.getMsg());
32 | }
33 | return null;
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/config/JedisConfig.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.config;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import redis.clients.jedis.JedisPool;
7 | import redis.clients.jedis.JedisPoolConfig;
8 |
9 | @Configuration
10 | public class JedisConfig {
11 |
12 | @Value("${spring.redis.host}")
13 | private String host;
14 |
15 | @Value("${spring.redis.port}")
16 | private int port;
17 |
18 | @Value("${spring.redis.password}")
19 | private String password;
20 |
21 | @Value("${spring.redis.jedis.pool.max-idle}")
22 | private int maxIdle;
23 |
24 | @Value("${spring.redis.jedis.pool.max-wait}")
25 | private long maxWait;
26 |
27 | @Value("${spring.redis.jedis.pool.min-idle}")
28 | private int minIdle;
29 |
30 | @Value("${spring.redis.timeout}")
31 | private int timeout;
32 |
33 | @Bean
34 | public JedisPool redisPoolFactory() {
35 | JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
36 | jedisPoolConfig.setMaxIdle(maxIdle);
37 | jedisPoolConfig.setMaxWaitMillis(maxWait);
38 | jedisPoolConfig.setMinIdle(minIdle);
39 |
40 | JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password);
41 |
42 | return jedisPool;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/batch/mapperproxy/MapperProxy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.batch.mapperproxy;
2 |
3 | import com.google.common.collect.Lists;
4 | import com.wangzaiplus.test.service.batch.BatchProcessMapper;
5 | import org.apache.commons.collections4.CollectionUtils;
6 |
7 | import java.util.List;
8 |
9 | import static com.wangzaiplus.test.common.Constant.MAX_SIZE_PER_TIME;
10 |
11 | public class MapperProxy implements BatchProcessMapper {
12 |
13 | private BatchProcessMapper batchProcessMapper;
14 |
15 | public MapperProxy(BatchProcessMapper batchProcessMapper) {
16 | this.batchProcessMapper = batchProcessMapper;
17 | }
18 |
19 | @Override
20 | public void batchInsert(List list) {
21 | if (CollectionUtils.isEmpty(list)) {
22 | return;
23 | }
24 |
25 | List> partition = Lists.partition(list, MAX_SIZE_PER_TIME);
26 | for (List batchList : partition) {
27 | batchProcessMapper.batchInsert(batchList);
28 | }
29 | }
30 |
31 | @Override
32 | public void batchUpdate(List list) {
33 | if (CollectionUtils.isEmpty(list)) {
34 | return;
35 | }
36 |
37 | List> partition = Lists.partition(list, MAX_SIZE_PER_TIME);
38 | for (List batchList : partition) {
39 | batchProcessMapper.batchUpdate(batchList);
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/LoginLogMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | id, user_id, type, description, create_time, update_time
15 |
16 |
17 |
18 | INSERT INTO login_log(user_id, type, description, create_time, update_time)
19 | VALUES (#{userId}, #{type}, #{description}, #{createTime}, #{updateTime})
20 |
21 |
22 |
27 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/RedissonController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import org.redisson.api.RLock;
4 | import org.redisson.api.RedissonClient;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RestController;
8 |
9 | import java.util.concurrent.TimeUnit;
10 |
11 | @RestController
12 | @RequestMapping("/redisson")
13 | public class RedissonController {
14 |
15 | @Autowired(required = false)
16 | private RedissonClient redissonClient;
17 |
18 | @RequestMapping("testRedisson")
19 | public String testRedisson() {
20 | RLock lock = redissonClient.getLock("testRedissonLock");
21 | boolean locked = false;
22 | try {
23 | locked = lock.tryLock(0, 10, TimeUnit.SECONDS);
24 | if (locked) {
25 | Thread.sleep(30000);
26 | return "ok.......................................";
27 | } else {
28 | return "获取锁失败.......................................";
29 | }
30 | } catch (InterruptedException e) {
31 | e.printStackTrace();
32 | return "获取锁异常.......................................";
33 | } finally {
34 | if (!locked) {
35 | return "获取锁失败";
36 | }
37 | lock.unlock();
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/impl/MsgLogServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.impl;
2 |
3 | import com.wangzaiplus.test.mapper.MsgLogMapper;
4 | import com.wangzaiplus.test.pojo.MsgLog;
5 | import com.wangzaiplus.test.service.MsgLogService;
6 | import com.wangzaiplus.test.util.JodaTimeUtil;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Service;
9 |
10 | import java.util.Date;
11 | import java.util.List;
12 |
13 | @Service
14 | public class MsgLogServiceImpl implements MsgLogService {
15 |
16 | @Autowired
17 | private MsgLogMapper msgLogMapper;
18 |
19 | @Override
20 | public void updateStatus(String msgId, Integer status) {
21 | MsgLog msgLog = new MsgLog();
22 | msgLog.setMsgId(msgId);
23 | msgLog.setStatus(status);
24 | msgLog.setUpdateTime(new Date());
25 | msgLogMapper.updateStatus(msgLog);
26 | }
27 |
28 | @Override
29 | public MsgLog selectByMsgId(String msgId) {
30 | return msgLogMapper.selectByPrimaryKey(msgId);
31 | }
32 |
33 | @Override
34 | public List selectTimeoutMsg() {
35 | return msgLogMapper.selectTimeoutMsg();
36 | }
37 |
38 | @Override
39 | public void updateTryCount(String msgId, Date tryTime) {
40 | Date nextTryTime = JodaTimeUtil.plusMinutes(tryTime, 1);
41 |
42 | MsgLog msgLog = new MsgLog();
43 | msgLog.setMsgId(msgId);
44 | msgLog.setNextTryTime(nextTryTime);
45 |
46 | msgLogMapper.updateTryCount(msgLog);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/resources/db/dml_create_msg_log_03.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `user` (
2 | `id` int(11) NOT NULL AUTO_INCREMENT,
3 | `username` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
4 | `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
5 | PRIMARY KEY (`id`),
6 | UNIQUE KEY `unq_username` (`username`)
7 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
8 |
9 | CREATE TABLE `login_log` (
10 | `id` int(11) NOT NULL AUTO_INCREMENT,
11 | `user_id` int(11) NOT NULL COMMENT '用户id',
12 | `type` int(11) NOT NULL COMMENT '日志类型:1登录 2登出',
13 | `description` varchar(255) DEFAULT NULL COMMENT '日志描述',
14 | `create_time` datetime DEFAULT NULL COMMENT '创建时间',
15 | `update_time` datetime DEFAULT NULL COMMENT '更新时间',
16 | PRIMARY KEY (`id`)
17 | ) ENGINE=InnoDB AUTO_INCREMENT=2045 DEFAULT CHARSET=utf8mb4 COMMENT='登录日志表';
18 |
19 | CREATE TABLE `msg_log` (
20 | `msg_id` varchar(255) NOT NULL DEFAULT '' COMMENT '消息唯一标识',
21 | `msg` text COMMENT '消息体, json格式化',
22 | `exchange` varchar(255) NOT NULL DEFAULT '' COMMENT '交换机',
23 | `routing_key` varchar(255) NOT NULL DEFAULT '' COMMENT '路由键',
24 | `status` int(11) NOT NULL DEFAULT '0' COMMENT '状态: 0投递中 1投递成功 2投递失败 3已消费',
25 | `try_count` int(11) NOT NULL DEFAULT '0' COMMENT '重试次数',
26 | `next_try_time` datetime DEFAULT NULL COMMENT '下一次重试时间',
27 | `create_time` datetime DEFAULT NULL COMMENT '创建时间',
28 | `update_time` datetime DEFAULT NULL COMMENT '更新时间',
29 | PRIMARY KEY (`msg_id`),
30 | UNIQUE KEY `unq_msg_id` (`msg_id`) USING BTREE
31 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='消息投递日志';
32 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.pojo.User;
5 | import com.wangzaiplus.test.service.UserService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.web.bind.annotation.*;
8 |
9 | import java.util.List;
10 |
11 | @RestController
12 | @RequestMapping("/user")
13 | public class UserController {
14 |
15 | @Autowired
16 | private UserService userService;
17 |
18 | @GetMapping("users")
19 | public String getAll() {
20 | List users = userService.getAll();
21 | return users.toString();
22 | }
23 |
24 | @GetMapping("{id}")
25 | public String getOne(@PathVariable Integer id) {
26 | User user = userService.getOne(id);
27 | if (null != user) {
28 | return user.toString();
29 | } else {
30 | return "not exists";
31 | }
32 | }
33 |
34 | @PostMapping
35 | public String add(User user) {
36 | userService.add(user);
37 | return "nice";
38 | }
39 |
40 | @PutMapping
41 | public String update(User user) {
42 | userService.update(user);
43 | return "nice";
44 | }
45 |
46 | @DeleteMapping("{id}")
47 | public String delete(@PathVariable Integer id) {
48 | userService.delete(id);
49 | return "nice";
50 | }
51 |
52 | @PostMapping("login")
53 | public ServerResponse login(String username, String password) {
54 | return userService.login(username, password);
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/strategy/CalculateServiceFactory.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.strategy;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import com.wangzaiplus.test.exception.ServiceException;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.beans.factory.annotation.Qualifier;
7 | import org.springframework.stereotype.Component;
8 |
9 | @Component
10 | public class CalculateServiceFactory {
11 |
12 | @Autowired
13 | @Qualifier("addCalculateServiceImpl")
14 | private CalculateService addCalculateServiceImpl;
15 |
16 | @Autowired
17 | @Qualifier("subtractCalculateServiceImpl")
18 | private CalculateService subtractCalculateServiceImpl;
19 |
20 | @Autowired
21 | @Qualifier("multiplyCalculateServiceImpl")
22 | private CalculateService multiplyCalculateServiceImpl;
23 |
24 | @Autowired
25 | @Qualifier("divideCalculateServiceImpl")
26 | private CalculateService divideCalculateServiceImpl;
27 |
28 | public CalculateService getCalculateService(Integer type) {
29 | CalculateService calculateService;
30 |
31 | if (Constant.CalculateTypeEnum.ADD.getType().equals(type)) {
32 | calculateService = addCalculateServiceImpl;
33 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
34 | calculateService = subtractCalculateServiceImpl;
35 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
36 | calculateService = multiplyCalculateServiceImpl;
37 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
38 | calculateService = divideCalculateServiceImpl;
39 | } else {
40 | throw new ServiceException("type error: " + type);
41 | }
42 |
43 | return calculateService;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/FundController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import com.wangzaiplus.test.common.ServerResponse;
4 | import com.wangzaiplus.test.dto.FundDto;
5 | import com.wangzaiplus.test.dto.SearchFormDto;
6 | import com.wangzaiplus.test.service.FundService;
7 | import com.wangzaiplus.test.util.FundUtils;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.web.bind.annotation.PostMapping;
11 | import org.springframework.web.bind.annotation.RequestBody;
12 | import org.springframework.web.bind.annotation.RequestMapping;
13 | import org.springframework.web.bind.annotation.RestController;
14 |
15 | import java.util.List;
16 |
17 | @RestController
18 | @RequestMapping("/fund")
19 | @Slf4j
20 | public class FundController {
21 |
22 | @Autowired
23 | private FundService fundService;
24 |
25 | @PostMapping("getFundDtoList")
26 | public ServerResponse getFundDtoList(@RequestBody FundDto fundDto) {
27 | List fundDtoList = FundUtils.getFundDtoList(fundDto.getType());
28 | fundService.update(fundDtoList);
29 | return ServerResponse.success("success");
30 | }
31 |
32 | @PostMapping("rank")
33 | public ServerResponse rank(@RequestBody FundDto fundDto) {
34 | long start = System.currentTimeMillis();
35 | ServerResponse response = fundService.rank(fundDto);
36 | log.info("rank costs: {} ms", System.currentTimeMillis() - start);
37 | return response;
38 | }
39 |
40 | @PostMapping("search")
41 | public ServerResponse search(@RequestBody SearchFormDto searchFormDto) {
42 | return fundService.search(searchFormDto);
43 | }
44 |
45 | @PostMapping("getSearchFormDto")
46 | public ServerResponse getSearchFormDto() {
47 | return fundService.getSearchFormDto();
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/interceptor/ApiIdempotentInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.interceptor;
2 |
3 | import com.wangzaiplus.test.annotation.ApiIdempotent;
4 | import com.wangzaiplus.test.service.TokenService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.method.HandlerMethod;
7 | import org.springframework.web.servlet.HandlerInterceptor;
8 | import org.springframework.web.servlet.ModelAndView;
9 |
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.lang.reflect.Method;
13 |
14 | /**
15 | * 接口幂等性拦截器
16 | */
17 | public class ApiIdempotentInterceptor implements HandlerInterceptor {
18 |
19 | @Autowired
20 | private TokenService tokenService;
21 |
22 | @Override
23 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
24 | if (!(handler instanceof HandlerMethod)) {
25 | return true;
26 | }
27 |
28 | HandlerMethod handlerMethod = (HandlerMethod) handler;
29 | Method method = handlerMethod.getMethod();
30 |
31 | ApiIdempotent methodAnnotation = method.getAnnotation(ApiIdempotent.class);
32 | if (methodAnnotation != null) {
33 | check(request);// 幂等性校验, 校验通过则放行, 校验失败则抛出异常, 并通过统一异常处理返回友好提示
34 | }
35 |
36 | return true;
37 | }
38 |
39 | private void check(HttpServletRequest request) {
40 | tokenService.checkToken(request);
41 | }
42 |
43 | @Override
44 | public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
45 | }
46 |
47 | @Override
48 | public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/resources/application-dev.properties:
--------------------------------------------------------------------------------
1 | server.port=8088
2 | spring.resources.static-locations=classpath:/templates/,classpath:/static/
3 | spring.mvc.view.suffix=.html
4 |
5 | # redis
6 | spring.redis.host=localhost
7 | spring.redis.port=6379
8 | spring.redis.password=root
9 | spring.redis.jedis.pool.max-idle=32
10 | spring.redis.jedis.pool.max-wait=-1
11 | spring.redis.jedis.pool.min-idle=0
12 | spring.redis.timeout=0
13 |
14 | # mysql
15 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
16 | spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&autoR&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
17 | spring.datasource.username=root
18 | spring.datasource.password=root
19 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
20 |
21 | # show sql in console
22 | logging.level.com.wangzaiplus.test.mapper=debug
23 |
24 | # rabbitmq
25 | spring.rabbitmq.host=localhost
26 | spring.rabbitmq.port=5672
27 | spring.rabbitmq.username=guest
28 | spring.rabbitmq.password=guest
29 | # ����confirms�ص� P -> Exchange
30 | spring.rabbitmq.publisher-confirms=true
31 | # ����returnedMessage�ص� Exchange -> Queue
32 | spring.rabbitmq.publisher-returns=true
33 | # �����ֶ�ȷ��(ack) Queue -> C
34 | spring.rabbitmq.listener.simple.acknowledge-mode=manual
35 | spring.rabbitmq.listener.simple.prefetch=100
36 |
37 | # mail
38 | spring.mail.host=smtp.163.com
39 | spring.mail.username=18621142249@163.com
40 | spring.mail.password=123456wangzai
41 | spring.mail.from=18621142249@163.com
42 | spring.mail.properties.mail.smtp.auth=true
43 | spring.mail.properties.mail.smtp.starttls.enable=true
44 | spring.mail.properties.mail.smtp.starttls.required=true
45 | spring.mail.properties.mail.smtp.ssl.enable=true
46 |
47 | ok.http.connect-timeout=30
48 | ok.http.read-timeout=30
49 | ok.http.write-timeout=30
50 | # ���ӳ�������Ŀ������ӵ��������
51 | ok.http.max-idle-connections=200
52 | # ���ӿ���ʱ�����Ϊ 300 ��
53 | ok.http.keep-alive-duration=300
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/impl/TestServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.impl;
2 |
3 | import com.wangzaiplus.test.mq.MessageHelper;
4 | import com.wangzaiplus.test.common.ResponseCode;
5 | import com.wangzaiplus.test.common.ServerResponse;
6 | import com.wangzaiplus.test.config.RabbitConfig;
7 | import com.wangzaiplus.test.mapper.MsgLogMapper;
8 | import com.wangzaiplus.test.pojo.Mail;
9 | import com.wangzaiplus.test.pojo.MsgLog;
10 | import com.wangzaiplus.test.service.TestService;
11 | import com.wangzaiplus.test.util.RandomUtil;
12 | import org.springframework.amqp.rabbit.connection.CorrelationData;
13 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
14 | import org.springframework.beans.factory.annotation.Autowired;
15 | import org.springframework.stereotype.Service;
16 |
17 | @Service
18 | public class TestServiceImpl implements TestService {
19 |
20 | @Autowired
21 | private MsgLogMapper msgLogMapper;
22 |
23 | @Autowired
24 | private RabbitTemplate rabbitTemplate;
25 |
26 | @Override
27 | public ServerResponse testIdempotence() {
28 | return ServerResponse.success("testIdempotence: success");
29 | }
30 |
31 | @Override
32 | public ServerResponse accessLimit() {
33 | return ServerResponse.success("accessLimit: success");
34 | }
35 |
36 | @Override
37 | public ServerResponse send(Mail mail) {
38 | String msgId = RandomUtil.UUID32();
39 | mail.setMsgId(msgId);
40 |
41 | MsgLog msgLog = new MsgLog(msgId, mail, RabbitConfig.MAIL_EXCHANGE_NAME, RabbitConfig.MAIL_ROUTING_KEY_NAME);
42 | msgLogMapper.insert(msgLog);// 消息入库
43 |
44 | CorrelationData correlationData = new CorrelationData(msgId);
45 | rabbitTemplate.convertAndSend(RabbitConfig.MAIL_EXCHANGE_NAME, RabbitConfig.MAIL_ROUTING_KEY_NAME, MessageHelper.objToMsg(mail), correlationData);// 发送消息
46 |
47 | return ServerResponse.success(ResponseCode.MAIL_SEND_SUCCESS.getMsg());
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/task/ResendMsg.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.task;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import com.wangzaiplus.test.mq.MessageHelper;
5 | import com.wangzaiplus.test.pojo.MsgLog;
6 | import com.wangzaiplus.test.service.MsgLogService;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.amqp.rabbit.connection.CorrelationData;
9 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.scheduling.annotation.Scheduled;
12 | import org.springframework.stereotype.Component;
13 |
14 | import java.util.List;
15 |
16 | //@Component
17 | @Slf4j
18 | public class ResendMsg {
19 |
20 | @Autowired
21 | private MsgLogService msgLogService;
22 |
23 | @Autowired
24 | private RabbitTemplate rabbitTemplate;
25 |
26 | // 最大投递次数
27 | private static final int MAX_TRY_COUNT = 3;
28 |
29 | /**
30 | * 每30s拉取投递失败的消息, 重新投递
31 | */
32 | @Scheduled(cron = "0/30 * * * * ?")
33 | public void resend() {
34 | log.info("开始执行定时任务(重新投递消息)");
35 |
36 | List msgLogs = msgLogService.selectTimeoutMsg();
37 | msgLogs.forEach(msgLog -> {
38 | String msgId = msgLog.getMsgId();
39 | if (msgLog.getTryCount() >= MAX_TRY_COUNT) {
40 | msgLogService.updateStatus(msgId, Constant.MsgLogStatus.DELIVER_FAIL);
41 | log.info("超过最大重试次数, 消息投递失败, msgId: {}", msgId);
42 | } else {
43 | msgLogService.updateTryCount(msgId, msgLog.getNextTryTime());// 投递次数+1
44 |
45 | CorrelationData correlationData = new CorrelationData(msgId);
46 | rabbitTemplate.convertAndSend(msgLog.getExchange(), msgLog.getRoutingKey(), MessageHelper.objToMsg(msgLog.getMsg()), correlationData);// 重新投递
47 |
48 | log.info("第 " + (msgLog.getTryCount() + 1) + " 次重新投递消息");
49 | }
50 | });
51 |
52 | log.info("定时任务执行结束(重新投递消息)");
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/consumer/SimpleMailConsumer.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq.consumer;
2 |
3 | import com.rabbitmq.client.Channel;
4 | import com.wangzaiplus.test.common.Constant;
5 | import com.wangzaiplus.test.config.RabbitConfig;
6 | import com.wangzaiplus.test.mq.MessageHelper;
7 | import com.wangzaiplus.test.pojo.Mail;
8 | import com.wangzaiplus.test.pojo.MsgLog;
9 | import com.wangzaiplus.test.service.MsgLogService;
10 | import com.wangzaiplus.test.util.MailUtil;
11 | import lombok.extern.slf4j.Slf4j;
12 | import org.springframework.amqp.core.Message;
13 | import org.springframework.amqp.core.MessageProperties;
14 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
15 | import org.springframework.beans.factory.annotation.Autowired;
16 | import org.springframework.stereotype.Component;
17 |
18 | import java.io.IOException;
19 |
20 | @Component
21 | @Slf4j
22 | public class SimpleMailConsumer {
23 |
24 | @Autowired
25 | private MsgLogService msgLogService;
26 |
27 | @Autowired
28 | private MailUtil mailUtil;
29 |
30 | @RabbitListener(queues = RabbitConfig.MAIL_QUEUE_NAME)
31 | public void consume(Message message, Channel channel) throws IOException {
32 | Mail mail = MessageHelper.msgToObj(message, Mail.class);
33 | log.info("收到消息: {}", mail.toString());
34 |
35 | String msgId = mail.getMsgId();
36 |
37 | MsgLog msgLog = msgLogService.selectByMsgId(msgId);
38 | if (null == msgLog || msgLog.getStatus().equals(Constant.MsgLogStatus.CONSUMED_SUCCESS)) {// 消费幂等性
39 | log.info("重复消费, msgId: {}", msgId);
40 | return;
41 | }
42 |
43 | MessageProperties properties = message.getMessageProperties();
44 | long tag = properties.getDeliveryTag();
45 |
46 | boolean success = mailUtil.send(mail);
47 | if (success) {
48 | msgLogService.updateStatus(msgId, Constant.MsgLogStatus.CONSUMED_SUCCESS);
49 | channel.basicAck(tag, false);// 消费确认
50 | } else {
51 | channel.basicNack(tag, false, true);
52 | }
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/impl/TokenServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.impl;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import com.wangzaiplus.test.common.ResponseCode;
5 | import com.wangzaiplus.test.common.ServerResponse;
6 | import com.wangzaiplus.test.exception.ServiceException;
7 | import com.wangzaiplus.test.service.TokenService;
8 | import com.wangzaiplus.test.util.JedisUtil;
9 | import com.wangzaiplus.test.util.RandomUtil;
10 | import org.apache.commons.lang3.StringUtils;
11 | import org.apache.commons.lang3.text.StrBuilder;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.stereotype.Service;
14 |
15 | import javax.servlet.http.HttpServletRequest;
16 |
17 | @Service
18 | public class TokenServiceImpl implements TokenService {
19 |
20 | private static final String TOKEN_NAME = "token";
21 |
22 | @Autowired
23 | private JedisUtil jedisUtil;
24 |
25 | @Override
26 | public ServerResponse createToken() {
27 | String str = RandomUtil.UUID32();
28 | StrBuilder token = new StrBuilder();
29 | token.append(Constant.Redis.TOKEN_PREFIX).append(str);
30 |
31 | jedisUtil.set(token.toString(), token.toString(), Constant.Redis.EXPIRE_TIME_MINUTE);
32 |
33 | return ServerResponse.success(token.toString());
34 | }
35 |
36 | @Override
37 | public void checkToken(HttpServletRequest request) {
38 | String token = request.getHeader(TOKEN_NAME);
39 | if (StringUtils.isBlank(token)) {// header中不存在token
40 | token = request.getParameter(TOKEN_NAME);
41 | if (StringUtils.isBlank(token)) {// parameter中也不存在token
42 | throw new ServiceException(ResponseCode.ILLEGAL_ARGUMENT.getMsg());
43 | }
44 | }
45 |
46 | if (!jedisUtil.exists(token)) {
47 | throw new ServiceException(ResponseCode.REPETITIVE_OPERATION.getMsg());
48 | }
49 |
50 | Long del = jedisUtil.del(token);
51 | if (del <= 0) {
52 | throw new ServiceException(ResponseCode.REPETITIVE_OPERATION.getMsg());
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/dto/FundDto.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.dto;
2 |
3 | import com.wangzaiplus.test.annotation.ColNum;
4 | import lombok.*;
5 |
6 | import java.math.BigDecimal;
7 | import java.util.Date;
8 | import java.util.List;
9 | import java.util.Objects;
10 |
11 | @Getter
12 | @Setter
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @ToString
16 | @Builder
17 | public class FundDto {
18 |
19 | private Integer id;
20 | @ColNum(colNum = 1)
21 | private String code;
22 | @ColNum(colNum = 2)
23 | private String name;
24 | @ColNum(colNum = 3)
25 | private BigDecimal netValue;
26 | @ColNum(colNum = 4)
27 | private String yieldOfOneYear;
28 | @ColNum(colNum = 5)
29 | private String yieldOfTwoYear;
30 | @ColNum(colNum = 6)
31 | private String yieldOfThreeYear;
32 | @ColNum(colNum = 7)
33 | private String yieldOfFiveYear;
34 | private int type;
35 | private String typeDesc;
36 | private Date establishedTime;
37 | private String asset;
38 | private String manager;
39 | private Integer status;
40 | private Integer isDeleted;
41 | private Date createdTime;
42 | private Date updatedTime;
43 |
44 | private String orderBy;
45 | private String sort;
46 | private Integer limit;
47 |
48 | List orderByList;
49 |
50 | private String nameOrCode;
51 | private Integer tempRank;
52 | private String rankOne;
53 | private String rankTwo;
54 | private String rankThree;
55 | private String rankFive;
56 |
57 | private Integer pageNum;
58 | private Integer pageSize;
59 |
60 | private String replacementSource;
61 | private String replacementTarget;
62 |
63 | @Override
64 | public boolean equals(Object obj) {
65 | if (this == obj) {
66 | return true;
67 | }
68 |
69 | if (!(obj instanceof FundDto)) {
70 | return false;
71 | }
72 |
73 | FundDto dto = (FundDto) obj;
74 | return Objects.equals(this.getCode(), dto.getCode());
75 | }
76 |
77 | @Override
78 | public int hashCode() {
79 | return Objects.hash(getCode());
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/common/ServerResponse.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.common;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 |
5 | import java.io.Serializable;
6 |
7 | public class ServerResponse implements Serializable{
8 |
9 | private static final long serialVersionUID = 7498483649536881777L;
10 |
11 | private Integer status;
12 |
13 | private String msg;
14 |
15 | private Object data;
16 |
17 | public ServerResponse() {
18 | }
19 |
20 | public ServerResponse(Integer status, String msg, Object data) {
21 | this.status = status;
22 | this.msg = msg;
23 | this.data = data;
24 | }
25 |
26 | @JsonIgnore
27 | public boolean isSuccess() {
28 | return this.status == ResponseCode.SUCCESS.getCode();
29 | }
30 |
31 | public static ServerResponse success() {
32 | return new ServerResponse(ResponseCode.SUCCESS.getCode(), null, null);
33 | }
34 |
35 | public static ServerResponse success(String msg) {
36 | return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg, null);
37 | }
38 |
39 | public static ServerResponse success(Object data) {
40 | return new ServerResponse(ResponseCode.SUCCESS.getCode(), null, data);
41 | }
42 |
43 | public static ServerResponse success(String msg, Object data) {
44 | return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg, data);
45 | }
46 |
47 | public static ServerResponse error(String msg) {
48 | return new ServerResponse(ResponseCode.ERROR.getCode(), msg, null);
49 | }
50 |
51 | public static ServerResponse error(Object data) {
52 | return new ServerResponse(ResponseCode.ERROR.getCode(), null, data);
53 | }
54 |
55 | public static ServerResponse error(String msg, Object data) {
56 | return new ServerResponse(ResponseCode.ERROR.getCode(), msg, data);
57 | }
58 |
59 | public Integer getStatus() {
60 | return status;
61 | }
62 |
63 | public void setStatus(Integer status) {
64 | this.status = status;
65 | }
66 |
67 | public String getMsg() {
68 | return msg;
69 | }
70 |
71 | public void setMsg(String msg) {
72 | this.msg = msg;
73 | }
74 |
75 | public Object getData() {
76 | return data;
77 | }
78 |
79 | public void setData(Object data) {
80 | this.data = data;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/TestApplication.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test;
2 |
3 | import com.wangzaiplus.test.interceptor.AccessLimitInterceptor;
4 | import com.wangzaiplus.test.interceptor.ApiIdempotentInterceptor;
5 | import org.mybatis.spring.annotation.MapperScan;
6 | import org.springframework.boot.SpringApplication;
7 | import org.springframework.boot.autoconfigure.SpringBootApplication;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.scheduling.annotation.EnableAsync;
10 | import org.springframework.scheduling.annotation.EnableScheduling;
11 | import org.springframework.web.cors.CorsConfiguration;
12 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
13 | import org.springframework.web.filter.CorsFilter;
14 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
15 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
16 |
17 | @SpringBootApplication
18 | @MapperScan("com.wangzaiplus.test.mapper")
19 | @EnableScheduling
20 | @EnableAsync
21 | public class TestApplication extends WebMvcConfigurerAdapter {
22 |
23 | public static void main(String[] args) {
24 | SpringApplication.run(TestApplication.class, args);
25 | }
26 |
27 | /**
28 | * 跨域
29 | * @return
30 | */
31 | @Bean
32 | public CorsFilter corsFilter() {
33 | final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
34 | final CorsConfiguration corsConfiguration = new CorsConfiguration();
35 | corsConfiguration.setAllowCredentials(true);
36 | corsConfiguration.addAllowedOrigin("*");
37 | corsConfiguration.addAllowedHeader("*");
38 | corsConfiguration.addAllowedMethod("*");
39 | urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
40 | return new CorsFilter(urlBasedCorsConfigurationSource);
41 | }
42 |
43 | @Override
44 | public void addInterceptors(InterceptorRegistry registry) {
45 | // 接口幂等性拦截器
46 | registry.addInterceptor(apiIdempotentInterceptor());
47 | // 接口防刷限流拦截器
48 | registry.addInterceptor(accessLimitInterceptor());
49 |
50 | super.addInterceptors(registry);
51 | }
52 |
53 | @Bean
54 | public ApiIdempotentInterceptor apiIdempotentInterceptor() {
55 | return new ApiIdempotentInterceptor();
56 | }
57 |
58 | @Bean
59 | public AccessLimitInterceptor accessLimitInterceptor() {
60 | return new AccessLimitInterceptor();
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/RegexUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 |
5 | import java.util.regex.Pattern;
6 |
7 | public class RegexUtil {
8 |
9 | // 正则表达式: 验证手机号
10 | public static final String REGEX_MOBILE = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$";
11 | // 验证邮箱
12 | public static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
13 | // 验证汉字
14 | public static final String REGEX_CHINESE = "^[\u4e00-\u9fa5],{0,}$";
15 | // 验证身份证
16 | public static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)";
17 | // 验证URL
18 | public static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
19 | // 验证IP地址
20 | public static final String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)";
21 |
22 | /**
23 | * 手机号
24 | *
25 | * @param mobile
26 | * @return
27 | */
28 | public static boolean isMobile(String mobile) {
29 | return StringUtils.isNotBlank(mobile) && Pattern.matches(REGEX_MOBILE, mobile);
30 | }
31 |
32 | /**
33 | * 邮箱
34 | *
35 | * @param email
36 | * @return
37 | */
38 | public static boolean isEmail(String email) {
39 | return StringUtils.isNotBlank(email) && Pattern.matches(REGEX_EMAIL, email);
40 | }
41 |
42 | /**
43 | * 汉字
44 | *
45 | * @param chinese
46 | * @return
47 | */
48 | public static boolean isChinese(String chinese) {
49 | return StringUtils.isNotBlank(chinese) && Pattern.matches(REGEX_CHINESE, chinese);
50 | }
51 |
52 | /**
53 | * 身份证
54 | *
55 | * @param idCard
56 | * @return
57 | */
58 | public static boolean isIDCard(String idCard) {
59 | return StringUtils.isNotBlank(idCard) && Pattern.matches(REGEX_ID_CARD, idCard);
60 | }
61 |
62 | /**
63 | * URL
64 | *
65 | * @param url
66 | * @return
67 | */
68 | public static boolean isUrl(String url) {
69 | return StringUtils.isNotBlank(url) && Pattern.matches(REGEX_URL, url);
70 | }
71 |
72 | /**
73 | * IP地址
74 | *
75 | * @param ipAddr
76 | * @return
77 | */
78 | public static boolean isIPAddr(String ipAddr) {
79 | return StringUtils.isNotBlank(ipAddr) && Pattern.matches(REGEX_IP_ADDR, ipAddr);
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/SerializableUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.io.*;
7 |
8 | /**
9 | * Serializable工具(JDK)
10 | */
11 | public class SerializableUtil {
12 |
13 | private static final Logger LOGGER = LoggerFactory.getLogger(SerializableUtil.class);
14 |
15 | /**
16 | * 序列化
17 | *
18 | * @param object
19 | * @return
20 | */
21 | public static byte[] serializable(Object object) {
22 | ByteArrayOutputStream baos = null;
23 | ObjectOutputStream oos = null;
24 | try {
25 | baos = new ByteArrayOutputStream();
26 | oos = new ObjectOutputStream(baos);
27 | oos.writeObject(object);
28 | return baos.toByteArray();
29 | } catch (IOException e) {
30 | LOGGER.error("serializable异常: " + e.getMessage());
31 | throw new RuntimeException("serializable异常: " + e.getMessage());
32 | } finally {
33 | try {
34 | if (oos != null) {
35 | oos.close();
36 | }
37 | if (baos != null) {
38 | baos.close();
39 | }
40 | } catch (IOException e) {
41 | LOGGER.error("serializable异常: " + e.getMessage());
42 | throw new RuntimeException("serializable异常: " + e.getMessage());
43 | }
44 | }
45 | }
46 |
47 | /**
48 | * 反序列化
49 | *
50 | * @param bytes
51 | * @return
52 | */
53 | public static Object unserializable(byte[] bytes) {
54 | ByteArrayInputStream bais = null;
55 | ObjectInputStream ois = null;
56 | try {
57 | bais = new ByteArrayInputStream(bytes);
58 | ois = new ObjectInputStream(bais);
59 | return ois.readObject();
60 | } catch (Exception e) {
61 | throw new RuntimeException("unserializable异常: " + e.getMessage());
62 | } finally {
63 | try {
64 | if (ois != null) {
65 | ois.close();
66 | }
67 | if (bais != null) {
68 | bais.close();
69 | }
70 | } catch (IOException e) {
71 | LOGGER.error("unserializable异常: " + e.getMessage());
72 | throw new RuntimeException("unserializable异常: " + e.getMessage());
73 | }
74 | }
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/MsgLogMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | msg_id, msg, exchange, routing_key, status, try_count, next_try_time, create_time, update_time
18 |
19 |
20 |
21 | INSERT INTO msg_log(msg_id, msg, exchange, routing_key, status, try_count, next_try_time, create_time, update_time)
22 | VALUES (#{msgId}, #{msg}, #{exchange}, #{routingKey}, #{status}, #{tryCount}, #{nextTryTime}, #{createTime}, #{updateTime})
23 |
24 |
25 |
26 | update msg_log set status = #{status}, update_time = now()
27 | where msg_id = #{msgId}
28 |
29 |
30 |
36 |
37 |
38 | update msg_log set try_count = try_count + 1, next_try_time = #{nextTryTime}, update_time = now()
39 | where msg_id = #{msgId}
40 |
41 |
42 |
48 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/JsonUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.core.type.TypeReference;
5 | import com.fasterxml.jackson.databind.DeserializationFeature;
6 | import com.fasterxml.jackson.databind.ObjectMapper;
7 | import com.fasterxml.jackson.databind.SerializationFeature;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.apache.commons.lang3.StringUtils;
10 |
11 | import java.text.SimpleDateFormat;
12 |
13 | @Slf4j
14 | public class JsonUtil {
15 |
16 | private static ObjectMapper objectMapper = new ObjectMapper();
17 | private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
18 |
19 | static {
20 | // 对象的所有字段全部列入
21 | objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
22 | // 取消默认转换timestamps形式
23 | objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
24 | // 忽略空bean转json的错误
25 | objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
26 | // 统一日期格式
27 | objectMapper.setDateFormat(new SimpleDateFormat(DATE_FORMAT));
28 | // 忽略在json字符串中存在, 但在java对象中不存在对应属性的情况, 防止错误
29 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
30 | }
31 |
32 | public static String objToStr(T obj) {
33 | if (null == obj) {
34 | return null;
35 | }
36 |
37 | try {
38 | return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
39 | } catch (Exception e) {
40 | log.warn("objToStr error: ", e);
41 | return null;
42 | }
43 | }
44 |
45 | public static T strToObj(String str, Class clazz) {
46 | if (StringUtils.isBlank(str) || null == clazz) {
47 | return null;
48 | }
49 |
50 | try {
51 | return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
52 | } catch (Exception e) {
53 | log.warn("strToObj error: ", e);
54 | return null;
55 | }
56 | }
57 |
58 | public static T strToObj(String str, TypeReference typeReference) {
59 | if (StringUtils.isBlank(str) || null == typeReference) {
60 | return null;
61 | }
62 |
63 | try {
64 | return (T) (typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference));
65 | } catch (Exception e) {
66 | log.error("strToObj error", e);
67 | return null;
68 | }
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/MailUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import com.wangzaiplus.test.pojo.Mail;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.core.io.FileSystemResource;
8 | import org.springframework.mail.MailException;
9 | import org.springframework.mail.SimpleMailMessage;
10 | import org.springframework.mail.javamail.JavaMailSender;
11 | import org.springframework.mail.javamail.MimeMessageHelper;
12 | import org.springframework.stereotype.Component;
13 |
14 | import javax.mail.internet.MimeMessage;
15 | import java.io.File;
16 |
17 | @Component
18 | @Slf4j
19 | public class MailUtil {
20 |
21 | @Value("${spring.mail.from}")
22 | private String from;
23 |
24 | @Autowired
25 | private JavaMailSender mailSender;
26 |
27 | /**
28 | * 发送简单邮件
29 | *
30 | * @param mail
31 | */
32 | public boolean send(Mail mail) {
33 | String to = mail.getTo();// 目标邮箱
34 | String title = mail.getTitle();// 邮件标题
35 | String content = mail.getContent();// 邮件正文
36 |
37 | SimpleMailMessage message = new SimpleMailMessage();
38 | message.setFrom(from);
39 | message.setTo(to);
40 | message.setSubject(title);
41 | message.setText(content);
42 |
43 | try {
44 | mailSender.send(message);
45 | log.info("邮件发送成功");
46 | return true;
47 | } catch (MailException e) {
48 | log.error("邮件发送失败, to: {}, title: {}", to, title, e);
49 | return false;
50 | }
51 | }
52 |
53 | /**
54 | * 发送附件邮件
55 | *
56 | * @param mail 邮件
57 | * @param file 附件
58 | */
59 | public boolean sendAttachment(Mail mail, File file) {
60 | String to = mail.getTo();
61 | String title = mail.getTitle();
62 | String content = mail.getContent();
63 |
64 | MimeMessage message = mailSender.createMimeMessage();
65 | try {
66 | MimeMessageHelper helper = new MimeMessageHelper(message, true);
67 | helper.setFrom(from);
68 | helper.setTo(to);
69 | helper.setSubject(title);
70 | helper.setText(content);
71 | FileSystemResource resource = new FileSystemResource(file);
72 | String fileName = file.getName();
73 | helper.addAttachment(fileName, resource);
74 | mailSender.send(message);
75 | log.info("附件邮件发送成功");
76 | return true;
77 | } catch (Exception e) {
78 | log.error("附件邮件发送失败, to: {}, title: {}", to, title, e);
79 | return false;
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/config/OkHttpConfig.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.config;
2 |
3 | import okhttp3.ConnectionPool;
4 | import okhttp3.OkHttpClient;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | import javax.net.ssl.*;
10 | import java.security.*;
11 | import java.security.cert.CertificateException;
12 | import java.security.cert.X509Certificate;
13 | import java.util.concurrent.TimeUnit;
14 |
15 | @Configuration
16 | public class OkHttpConfig {
17 |
18 | @Value("${ok.http.connect-timeout}")
19 | private Integer connectTimeout;
20 |
21 | @Value("${ok.http.read-timeout}")
22 | private Integer readTimeout;
23 |
24 | @Value("${ok.http.write-timeout}")
25 | private Integer writeTimeout;
26 |
27 | @Value("${ok.http.max-idle-connections}")
28 | private Integer maxIdleConnections;
29 |
30 | @Value("${ok.http.keep-alive-duration}")
31 | private Long keepAliveDuration;
32 |
33 | @Bean
34 | public OkHttpClient okHttpClient() {
35 | return new OkHttpClient.Builder()
36 | .sslSocketFactory(sslSocketFactory(), x509TrustManager())
37 | // 是否开启缓存
38 | .retryOnConnectionFailure(false)
39 | .connectionPool(pool())
40 | .connectTimeout(connectTimeout, TimeUnit.SECONDS)
41 | .readTimeout(readTimeout, TimeUnit.SECONDS)
42 | .writeTimeout(writeTimeout,TimeUnit.SECONDS)
43 | .hostnameVerifier((hostname, session) -> true)
44 | .build();
45 | }
46 |
47 | @Bean
48 | public X509TrustManager x509TrustManager() {
49 | return new X509TrustManager() {
50 | @Override
51 | public void checkClientTrusted(X509Certificate[] chain, String authType)
52 | throws CertificateException {
53 | }
54 | @Override
55 | public void checkServerTrusted(X509Certificate[] chain, String authType)
56 | throws CertificateException {
57 | }
58 | @Override
59 | public X509Certificate[] getAcceptedIssuers() {
60 | return new X509Certificate[0];
61 | }
62 | };
63 | }
64 |
65 | @Bean
66 | public SSLSocketFactory sslSocketFactory() {
67 | try {
68 | // 信任任何链接
69 | SSLContext sslContext = SSLContext.getInstance("TLS");
70 | sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
71 | return sslContext.getSocketFactory();
72 | } catch (NoSuchAlgorithmException | KeyManagementException e) {
73 | e.printStackTrace();
74 | }
75 | return null;
76 | }
77 |
78 | @Bean
79 | public ConnectionPool pool() {
80 | return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS);
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/interceptor/AccessLimitInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.interceptor;
2 |
3 | import com.wangzaiplus.test.annotation.AccessLimit;
4 | import com.wangzaiplus.test.common.Constant;
5 | import com.wangzaiplus.test.common.ResponseCode;
6 | import com.wangzaiplus.test.exception.ServiceException;
7 | import com.wangzaiplus.test.util.IpUtil;
8 | import com.wangzaiplus.test.util.JedisUtil;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.web.method.HandlerMethod;
11 | import org.springframework.web.servlet.HandlerInterceptor;
12 | import org.springframework.web.servlet.ModelAndView;
13 |
14 | import javax.servlet.http.HttpServletRequest;
15 | import javax.servlet.http.HttpServletResponse;
16 | import java.lang.reflect.Method;
17 |
18 | /**
19 | * 接口防刷限流拦截器
20 | */
21 | public class AccessLimitInterceptor implements HandlerInterceptor {
22 |
23 | @Autowired
24 | private JedisUtil jedisUtil;
25 |
26 | @Override
27 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
28 | if (!(handler instanceof HandlerMethod)) {
29 | return true;
30 | }
31 |
32 | HandlerMethod handlerMethod = (HandlerMethod) handler;
33 | Method method = handlerMethod.getMethod();
34 |
35 | AccessLimit annotation = method.getAnnotation(AccessLimit.class);
36 | if (annotation != null) {
37 | check(annotation, request);
38 | }
39 |
40 | return true;
41 | }
42 |
43 | private void check(AccessLimit annotation, HttpServletRequest request) {
44 | int maxCount = annotation.maxCount();
45 | int seconds = annotation.seconds();
46 |
47 | StringBuilder sb = new StringBuilder();
48 | sb.append(Constant.Redis.ACCESS_LIMIT_PREFIX).append(IpUtil.getIpAddress(request)).append(request.getRequestURI());
49 | String key = sb.toString();
50 |
51 | Boolean exists = jedisUtil.exists(key);
52 | if (!exists) {
53 | jedisUtil.set(key, String.valueOf(1), seconds);
54 | } else {
55 | int count = Integer.valueOf(jedisUtil.get(key));
56 | if (count < maxCount) {
57 | Long ttl = jedisUtil.ttl(key);
58 | if (ttl <= 0) {
59 | jedisUtil.set(key, String.valueOf(1), seconds);
60 | } else {
61 | jedisUtil.set(key, String.valueOf(++count), ttl.intValue());
62 | }
63 | } else {
64 | throw new ServiceException(ResponseCode.ACCESS_LIMIT.getMsg());
65 | }
66 | }
67 | }
68 |
69 | @Override
70 | public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
71 | }
72 |
73 | @Override
74 | public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/BeanUtils.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import com.wangzaiplus.test.annotation.ColNum;
4 | import com.wangzaiplus.test.exception.ServiceException;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.apache.commons.collections4.CollectionUtils;
7 | import org.apache.commons.lang3.StringUtils;
8 |
9 | import java.beans.PropertyDescriptor;
10 | import java.lang.reflect.Field;
11 | import java.lang.reflect.Method;
12 | import java.math.BigDecimal;
13 | import java.util.List;
14 |
15 | @Slf4j
16 | public class BeanUtils {
17 |
18 | private static final String TYPE_STRING = "String";
19 | private static final String TYPE_DATE = "Date";
20 | private static final String TYPE_INT = "int";
21 | private static final String TYPE_INTEGER = "Integer";
22 | private static final String TYPE_LONG = "Long";
23 | private static final String TYPE_DOUBLE = "Double";
24 | private static final String TYPE_BOOLEAN = "Boolean";
25 | private static final String TYPE_BIG_DECIMAL = "BigDecimal";
26 |
27 | public static void convert(List list, Object o) throws Exception {
28 | if (CollectionUtils.isEmpty(list) || null == o) {
29 | throw new ServiceException("converter param error");
30 | }
31 |
32 | Class> clazz = o.getClass();
33 | Field[] fields = clazz.getDeclaredFields();
34 | for (Field field : fields) {
35 | ColNum colNum = field.getAnnotation(ColNum.class);
36 | if (null == colNum) {
37 | continue;
38 | }
39 |
40 | int num = colNum.colNum();
41 | if (num < 1 || num > list.size()) {
42 | throw new ServiceException("colNum error: " + num);
43 | }
44 |
45 | String value = list.get(num - 1);
46 | PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
47 | Method writeMethod = pd.getWriteMethod();
48 | if (null == writeMethod || StringUtils.isBlank(value)) {
49 | continue;
50 | }
51 |
52 | String fieldType = field.getType().getSimpleName();
53 | Object parsedValue = parseValue(fieldType, value);
54 | writeMethod.invoke(o, parsedValue);
55 | }
56 | }
57 |
58 | private static Object parseValue(String fieldType, String value) {
59 | if (TYPE_STRING.equals(fieldType)) {
60 | return value;
61 | } else if (TYPE_DATE.equals(fieldType)) {
62 | return JodaTimeUtil.strToDate(value);
63 | } else if (TYPE_INT.equals(fieldType) || TYPE_INTEGER.equals(value)) {
64 | return Integer.parseInt(value);
65 | } else if (TYPE_LONG.equalsIgnoreCase(fieldType)) {
66 | return Long.parseLong(value);
67 | } else if (TYPE_DOUBLE.equalsIgnoreCase(fieldType)) {
68 | return Double.parseDouble(value);
69 | } else if (TYPE_BOOLEAN.equalsIgnoreCase(fieldType)) {
70 | return Boolean.TRUE.toString().equalsIgnoreCase(fieldType);
71 | } else if (TYPE_BIG_DECIMAL.equalsIgnoreCase(fieldType)) {
72 | return new BigDecimal(value);
73 | } else {
74 | throw new ServiceException("fieldType error: "+ fieldType);
75 | }
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mq/BaseConsumerProxy.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.mq;
2 |
3 | import com.rabbitmq.client.Channel;
4 | import com.wangzaiplus.test.common.Constant;
5 | import com.wangzaiplus.test.pojo.MsgLog;
6 | import com.wangzaiplus.test.service.MsgLogService;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.amqp.core.Message;
9 | import org.springframework.amqp.core.MessageProperties;
10 |
11 | import java.lang.reflect.Proxy;
12 | import java.util.Map;
13 |
14 | @Slf4j
15 | public class BaseConsumerProxy {
16 |
17 | private Object target;
18 |
19 | private MsgLogService msgLogService;
20 |
21 | public BaseConsumerProxy(Object target, MsgLogService msgLogService) {
22 | this.target = target;
23 | this.msgLogService = msgLogService;
24 | }
25 |
26 | public Object getProxy() {
27 | ClassLoader classLoader = target.getClass().getClassLoader();
28 | Class[] interfaces = target.getClass().getInterfaces();
29 |
30 | Object proxy = Proxy.newProxyInstance(classLoader, interfaces, (proxy1, method, args) -> {
31 | Message message = (Message) args[0];
32 | Channel channel = (Channel) args[1];
33 |
34 | String correlationId = getCorrelationId(message);
35 |
36 | if (isConsumed(correlationId)) {// 消费幂等性, 防止消息被重复消费
37 | log.info("重复消费, correlationId: {}", correlationId);
38 | return null;
39 | }
40 |
41 | MessageProperties properties = message.getMessageProperties();
42 | long tag = properties.getDeliveryTag();
43 |
44 | try {
45 | Object result = method.invoke(target, args);// 真正消费的业务逻辑
46 | msgLogService.updateStatus(correlationId, Constant.MsgLogStatus.CONSUMED_SUCCESS);
47 | channel.basicAck(tag, false);// 消费确认
48 | return result;
49 | } catch (Exception e) {
50 | log.error("getProxy error", e);
51 | channel.basicNack(tag, false, true);
52 | return null;
53 | }
54 | });
55 |
56 | return proxy;
57 | }
58 |
59 | /**
60 | * 获取CorrelationId
61 | *
62 | * @param message
63 | * @return
64 | */
65 | private String getCorrelationId(Message message) {
66 | String correlationId = null;
67 |
68 | MessageProperties properties = message.getMessageProperties();
69 | Map headers = properties.getHeaders();
70 | for (Map.Entry entry : headers.entrySet()) {
71 | String key = (String) entry.getKey();
72 | String value = (String) entry.getValue();
73 | if (key.equals("spring_returned_message_correlation")) {
74 | correlationId = value;
75 | }
76 | }
77 |
78 | return correlationId;
79 | }
80 |
81 | /**
82 | * 消息是否已被消费
83 | *
84 | * @param correlationId
85 | * @return
86 | */
87 | private boolean isConsumed(String correlationId) {
88 | MsgLog msgLog = msgLogService.selectByMsgId(correlationId);
89 | if (null == msgLog || msgLog.getStatus().equals(Constant.MsgLogStatus.CONSUMED_SUCCESS)) {
90 | return true;
91 | }
92 |
93 | return false;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/RandomUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import java.util.Random;
4 | import java.util.UUID;
5 |
6 | public class RandomUtil {
7 |
8 | public static final String allChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
9 |
10 | public static final String letterChar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
11 |
12 | public static final String numberChar = "0123456789";
13 |
14 | public static String UUID32() {
15 | String str = UUID.randomUUID().toString();
16 | return str.replaceAll("-", "");
17 | }
18 |
19 | public static String UUID36() {
20 | return UUID.randomUUID().toString();
21 | }
22 |
23 | /**
24 | * 生成包含大、小写字母、数字的字符串
25 | *
26 | * @param length
27 | * @return 如: zsK8rCCi
28 | */
29 | public static String generateStr(int length) {
30 | StringBuffer sb = new StringBuffer();
31 | Random random = new Random();
32 | for (int i = 0; i < length; i++) {
33 | sb.append(allChar.charAt(random.nextInt(allChar.length())));
34 | }
35 | return sb.toString();
36 | }
37 |
38 | /**
39 | * 生成纯数字字符串
40 | *
41 | * @param length
42 | * @return 如: 77914
43 | */
44 | public static String generateDigitalStr(int length) {
45 | StringBuffer sb = new StringBuffer();
46 | Random random = new Random();
47 | for (int i = 0; i < length; i++) {
48 | sb.append(numberChar.charAt(random.nextInt(numberChar.length())));
49 | }
50 | return sb.toString();
51 | }
52 |
53 | /**
54 | * 生成只包含大小写字母的字符串
55 | *
56 | * @param length
57 | * @return 如: XetrWaYc
58 | */
59 | public static String generateLetterStr(int length) {
60 | StringBuffer sb = new StringBuffer();
61 | Random random = new Random();
62 | for (int i = 0; i < length; i++) {
63 | sb.append(letterChar.charAt(random.nextInt(letterChar.length())));
64 | }
65 | return sb.toString();
66 | }
67 |
68 | /**
69 | * 生成只包含小写字母的字符串
70 | *
71 | * @param length
72 | * @return 如: nzcaunmk
73 | */
74 | public static String generateLowerStr(int length) {
75 | return generateLetterStr(length).toLowerCase();
76 | }
77 |
78 | /**
79 | * 生成只包含大写字母的字符串
80 | *
81 | * @param length
82 | * @return 如: KZMQXSXW
83 | */
84 | public static String generateUpperStr(int length) {
85 | return generateLetterStr(length).toUpperCase();
86 | }
87 |
88 | /**
89 | * 生成纯0字符串
90 | *
91 | * @param length
92 | * @return 如: 00000000
93 | */
94 | public static String generateZeroStr(int length) {
95 | StringBuffer sb = new StringBuffer();
96 | for (int i = 0; i < length; i++) {
97 | sb.append('0');
98 | }
99 | return sb.toString();
100 | }
101 |
102 | /**
103 | * 根据数字生成字符串,长度不够前面补0
104 | *
105 | * @param num 数字
106 | * @param strLength 字符串长度
107 | * @return 如: 00000099
108 | */
109 | public static String generateStrWithZero(int num, int strLength) {
110 | StringBuffer sb = new StringBuffer();
111 | String strNum = String.valueOf(num);
112 | if (strLength - strNum.length() >= 0) {
113 | sb.append(generateZeroStr(strLength - strNum.length()));
114 | } else {
115 | throw new RuntimeException("将数字" + num + "转化为长度为" + strLength + "的字符串异常!");
116 | }
117 | sb.append(strNum);
118 | return sb.toString();
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/config/RabbitConfig.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.config;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import com.wangzaiplus.test.service.MsgLogService;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.amqp.core.Binding;
7 | import org.springframework.amqp.core.BindingBuilder;
8 | import org.springframework.amqp.core.DirectExchange;
9 | import org.springframework.amqp.core.Queue;
10 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
11 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
12 | import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.context.annotation.Bean;
15 | import org.springframework.context.annotation.Configuration;
16 |
17 | @Configuration
18 | @Slf4j
19 | public class RabbitConfig {
20 |
21 | @Autowired
22 | private CachingConnectionFactory connectionFactory;
23 |
24 | @Autowired
25 | private MsgLogService msgLogService;
26 |
27 | @Bean
28 | public RabbitTemplate rabbitTemplate() {
29 | RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
30 | rabbitTemplate.setMessageConverter(converter());
31 |
32 | // 消息是否成功发送到Exchange
33 | rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
34 | if (ack) {
35 | log.info("消息成功发送到Exchange");
36 | String msgId = correlationData.getId();
37 | msgLogService.updateStatus(msgId, Constant.MsgLogStatus.DELIVER_SUCCESS);
38 | } else {
39 | log.info("消息发送到Exchange失败, {}, cause: {}", correlationData, cause);
40 | }
41 | });
42 |
43 | // 触发setReturnCallback回调必须设置mandatory=true, 否则Exchange没有找到Queue就会丢弃掉消息, 而不会触发回调
44 | rabbitTemplate.setMandatory(true);
45 | // 消息是否从Exchange路由到Queue, 注意: 这是一个失败回调, 只有消息从Exchange路由到Queue失败才会回调这个方法
46 | rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
47 | log.info("消息从Exchange路由到Queue失败: exchange: {}, route: {}, replyCode: {}, replyText: {}, message: {}", exchange, routingKey, replyCode, replyText, message);
48 | });
49 |
50 | return rabbitTemplate;
51 | }
52 |
53 | @Bean
54 | public Jackson2JsonMessageConverter converter() {
55 | return new Jackson2JsonMessageConverter();
56 | }
57 |
58 | // 登录日志
59 | public static final String LOGIN_LOG_QUEUE_NAME = "login.log.queue";
60 | public static final String LOGIN_LOG_EXCHANGE_NAME = "login.log.exchange";
61 | public static final String LOGIN_LOG_ROUTING_KEY_NAME = "login.log.routing.key";
62 |
63 | @Bean
64 | public Queue logUserQueue() {
65 | return new Queue(LOGIN_LOG_QUEUE_NAME, true);
66 | }
67 |
68 | @Bean
69 | public DirectExchange logUserExchange() {
70 | return new DirectExchange(LOGIN_LOG_EXCHANGE_NAME, true, false);
71 | }
72 |
73 | @Bean
74 | public Binding logUserBinding() {
75 | return BindingBuilder.bind(logUserQueue()).to(logUserExchange()).with(LOGIN_LOG_ROUTING_KEY_NAME);
76 | }
77 |
78 | // 发送邮件
79 | public static final String MAIL_QUEUE_NAME = "mail.queue";
80 | public static final String MAIL_EXCHANGE_NAME = "mail.exchange";
81 | public static final String MAIL_ROUTING_KEY_NAME = "mail.routing.key";
82 |
83 | @Bean
84 | public Queue mailQueue() {
85 | return new Queue(MAIL_QUEUE_NAME, true);
86 | }
87 |
88 | @Bean
89 | public DirectExchange mailExchange() {
90 | return new DirectExchange(MAIL_EXCHANGE_NAME, true, false);
91 | }
92 |
93 | @Bean
94 | public Binding mailBinding() {
95 | return BindingBuilder.bind(mailQueue()).to(mailExchange()).with(MAIL_ROUTING_KEY_NAME);
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/UserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | id, username, password, password_salt, ip, mobile, mail, type, status, is_deleted, created_time, updated_time
21 |
22 |
23 |
28 |
29 |
35 |
36 |
37 | INSERT INTO t_user(username, password) VALUES (#{username}, #{password})
38 |
39 |
40 |
41 | UPDATE t_user SET
42 |
43 | username = #{username},
44 |
45 |
46 | password = #{password}
47 |
48 | WHERE id = #{id}
49 |
50 |
51 |
52 | DELETE FROM t_user WHERE id =#{id}
53 |
54 |
55 |
61 |
62 |
63 | insert into t_user(username, password)
64 | values
65 |
66 | (#{item.username}, #{item.password})
67 |
68 |
69 |
70 |
71 | update t_user
72 |
73 |
74 |
75 | when id = #{item.id} then #{item.username}
76 |
77 |
78 |
79 |
80 | when id = #{item.id} then #{item.password}
81 |
82 |
83 |
84 | where id in
85 |
86 | #{item.id}
87 |
88 |
89 |
90 |
96 |
97 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/service/impl/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.service.impl;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import com.wangzaiplus.test.common.ResponseCode;
5 | import com.wangzaiplus.test.common.ServerResponse;
6 | import com.wangzaiplus.test.config.RabbitConfig;
7 | import com.wangzaiplus.test.mapper.MsgLogMapper;
8 | import com.wangzaiplus.test.mapper.UserMapper;
9 | import com.wangzaiplus.test.mq.MessageHelper;
10 | import com.wangzaiplus.test.pojo.LoginLog;
11 | import com.wangzaiplus.test.pojo.MsgLog;
12 | import com.wangzaiplus.test.pojo.User;
13 | import com.wangzaiplus.test.service.UserService;
14 | import com.wangzaiplus.test.service.batch.mapperproxy.MapperProxy;
15 | import com.wangzaiplus.test.util.JedisUtil;
16 | import com.wangzaiplus.test.util.JodaTimeUtil;
17 | import com.wangzaiplus.test.util.RandomUtil;
18 | import lombok.extern.slf4j.Slf4j;
19 | import org.apache.commons.lang3.StringUtils;
20 | import org.springframework.amqp.rabbit.connection.CorrelationData;
21 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.stereotype.Service;
24 |
25 | import java.util.Date;
26 | import java.util.List;
27 |
28 | @Service
29 | @Slf4j
30 | public class UserServiceImpl implements UserService {
31 |
32 | @Autowired
33 | private UserMapper userMapper;
34 |
35 | @Autowired
36 | private RabbitTemplate rabbitTemplate;
37 |
38 | @Autowired
39 | private MsgLogMapper msgLogMapper;
40 |
41 | @Autowired
42 | private JedisUtil jedisUtil;
43 |
44 | @Override
45 | public List getAll() {
46 | return userMapper.selectAll();
47 | }
48 |
49 | @Override
50 | public User getOne(Integer id) {
51 | return userMapper.selectOne(id);
52 | }
53 |
54 | @Override
55 | public void add(User user) {
56 | userMapper.insert(user);
57 | }
58 |
59 | @Override
60 | public void update(User user) {
61 | userMapper.update(user);
62 | }
63 |
64 | @Override
65 | public void delete(Integer id) {
66 | userMapper.delete(id);
67 | }
68 |
69 | @Override
70 | public User getByUsernameAndPassword(String username, String password) {
71 | return userMapper.selectByUsernameAndPassword(username, password);
72 | }
73 |
74 | @Override
75 | public ServerResponse login(String username, String password) {
76 | if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
77 | return ServerResponse.error(ResponseCode.USERNAME_OR_PASSWORD_EMPTY.getMsg());
78 | }
79 |
80 | User user = userMapper.selectByUsernameAndPassword(username, password);
81 | if (null == user) {
82 | return ServerResponse.error(ResponseCode.USERNAME_OR_PASSWORD_WRONG.getMsg());
83 | }
84 |
85 | saveAndSendMsg(user);
86 |
87 | return ServerResponse.success();
88 | }
89 |
90 | /**
91 | * 保存并发送消息
92 | * @param user
93 | */
94 | private void saveAndSendMsg(User user) {
95 | String msgId = RandomUtil.UUID32();
96 |
97 | LoginLog loginLog = new LoginLog();
98 | loginLog.setUserId(user.getId());
99 | loginLog.setType(Constant.LogType.LOGIN);
100 | Date date = new Date();
101 | loginLog.setDescription(user.getUsername() + "在" + JodaTimeUtil.dateToStr(date) + "登录系统");
102 | loginLog.setCreateTime(date);
103 | loginLog.setUpdateTime(date);
104 | loginLog.setMsgId(msgId);
105 |
106 | CorrelationData correlationData = new CorrelationData(msgId);
107 | rabbitTemplate.convertAndSend(RabbitConfig.LOGIN_LOG_EXCHANGE_NAME, RabbitConfig.LOGIN_LOG_ROUTING_KEY_NAME, MessageHelper.objToMsg(loginLog), correlationData);
108 |
109 | MsgLog msgLog = new MsgLog(msgId, loginLog, RabbitConfig.LOGIN_LOG_EXCHANGE_NAME, RabbitConfig.LOGIN_LOG_ROUTING_KEY_NAME);
110 | msgLogMapper.insert(msgLog);
111 | }
112 |
113 | @Override
114 | public void batchInsert(List list) {
115 | new MapperProxy(userMapper).batchInsert(list);
116 | }
117 |
118 | @Override
119 | public void batchUpdate(List list) {
120 | new MapperProxy(userMapper).batchUpdate(list);
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 首页
6 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | 登录
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | 股票型
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
112 |
113 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/StrategyController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import com.wangzaiplus.test.common.Constant;
4 | import com.wangzaiplus.test.common.ServerResponse;
5 | import com.wangzaiplus.test.exception.ServiceException;
6 | import com.wangzaiplus.test.pojo.CalculateDto;
7 | import com.wangzaiplus.test.service.strategy.CalculateService;
8 | import com.wangzaiplus.test.service.strategy.CalculateServiceFactory;
9 | import com.wangzaiplus.test.service.strategy.CalculateStrategy;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.beans.factory.annotation.Qualifier;
12 | import org.springframework.web.bind.annotation.PostMapping;
13 | import org.springframework.web.bind.annotation.RequestBody;
14 | import org.springframework.web.bind.annotation.RequestMapping;
15 | import org.springframework.web.bind.annotation.RestController;
16 |
17 | @RestController
18 | @RequestMapping("/test")
19 | public class StrategyController {
20 |
21 | @Autowired
22 | @Qualifier("addCalculateServiceImpl")
23 | private CalculateService addCalculateServiceImpl;
24 |
25 | @Autowired
26 | @Qualifier("subtractCalculateServiceImpl")
27 | private CalculateService subtractCalculateServiceImpl;
28 |
29 | @Autowired
30 | @Qualifier("multiplyCalculateServiceImpl")
31 | private CalculateService multiplyCalculateServiceImpl;
32 |
33 | @Autowired
34 | @Qualifier("divideCalculateServiceImpl")
35 | private CalculateService divideCalculateServiceImpl;
36 |
37 | @Autowired
38 | private CalculateServiceFactory calculateServiceFactory;
39 |
40 | @PostMapping("strategy1")
41 | public ServerResponse strategy1(@RequestBody CalculateDto dto) {
42 | Integer type = dto.getType();
43 | CalculateService calculateService;
44 |
45 | if (Constant.CalculateTypeEnum.ADD.getType().equals(type)) {
46 | calculateService = addCalculateServiceImpl;
47 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
48 | calculateService = subtractCalculateServiceImpl;
49 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
50 | calculateService = multiplyCalculateServiceImpl;
51 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
52 | calculateService = divideCalculateServiceImpl;
53 | } else {
54 | throw new ServiceException("type error: " + type);
55 | }
56 |
57 | int result = calculateService.calculate(dto.getA(), dto.getB());
58 |
59 | return ServerResponse.success(result);
60 | }
61 |
62 | @PostMapping("strategy2")
63 | public ServerResponse strategy2(@RequestBody CalculateDto dto) {
64 | CalculateService calculateService = getCalculateService(dto.getType());
65 | int result = calculateService.calculate(dto.getA(), dto.getB());
66 | return ServerResponse.success(result);
67 | }
68 |
69 | private CalculateService getCalculateService(Integer type) {
70 | CalculateService calculateService;
71 |
72 | if (Constant.CalculateTypeEnum.ADD.getType().equals(type)) {
73 | calculateService = addCalculateServiceImpl;
74 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
75 | calculateService = subtractCalculateServiceImpl;
76 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
77 | calculateService = multiplyCalculateServiceImpl;
78 | } else if (Constant.CalculateTypeEnum.SUBTRACT.getType().equals(type)) {
79 | calculateService = divideCalculateServiceImpl;
80 | } else {
81 | throw new ServiceException("type error: " + type);
82 | }
83 |
84 | return calculateService;
85 | }
86 |
87 | @PostMapping("strategy3")
88 | public ServerResponse strategy3(@RequestBody CalculateDto dto) {
89 | CalculateService calculateService = calculateServiceFactory.getCalculateService(dto.getType());
90 | int result = calculateService.calculate(dto.getA(), dto.getB());
91 | return ServerResponse.success(result);
92 | }
93 |
94 | @PostMapping("strategy4")
95 | public ServerResponse strategy4(@RequestBody CalculateDto dto) {
96 | CalculateService calculateService = CalculateStrategy.getCalculateService(dto.getType());
97 | int result = calculateService.calculate(dto.getA(), dto.getB());
98 | return ServerResponse.success(result);
99 | }
100 |
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/JedisUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.stereotype.Component;
6 | import redis.clients.jedis.Jedis;
7 | import redis.clients.jedis.JedisPool;
8 |
9 | @Component
10 | @Slf4j
11 | public class JedisUtil {
12 |
13 | @Autowired(required = false)
14 | private JedisPool jedisPool;
15 |
16 | private Jedis getJedis() {
17 | return jedisPool.getResource();
18 | }
19 |
20 | /**
21 | * 设值
22 | *
23 | * @param key
24 | * @param value
25 | * @return
26 | */
27 | public String set(String key, String value) {
28 | Jedis jedis = null;
29 | try {
30 | jedis = getJedis();
31 | return jedis.set(key, value);
32 | } catch (Exception e) {
33 | log.error("set key: {} value: {} error", key, value, e);
34 | return null;
35 | } finally {
36 | close(jedis);
37 | }
38 | }
39 |
40 | /**
41 | * 设值
42 | *
43 | * @param key
44 | * @param value
45 | * @param expireTime 过期时间, 单位: s
46 | * @return
47 | */
48 | public String set(String key, String value, int expireTime) {
49 | Jedis jedis = null;
50 | try {
51 | jedis = getJedis();
52 | return jedis.setex(key, expireTime, value);
53 | } catch (Exception e) {
54 | log.error("set key:{} value:{} expireTime:{} error", key, value, expireTime, e);
55 | return null;
56 | } finally {
57 | close(jedis);
58 | }
59 | }
60 |
61 | /**
62 | * 设值
63 | *
64 | * @param key
65 | * @param value
66 | * @return
67 | */
68 | public Long setnx(String key, String value) {
69 | Jedis jedis = null;
70 | try {
71 | jedis = getJedis();
72 | return jedis.setnx(key, value);
73 | } catch (Exception e) {
74 | log.error("set key:{} value:{} error", key, value, e);
75 | return null;
76 | } finally {
77 | close(jedis);
78 | }
79 | }
80 |
81 | /**
82 | * 取值
83 | *
84 | * @param key
85 | * @return
86 | */
87 | public String get(String key) {
88 | Jedis jedis = null;
89 | try {
90 | jedis = getJedis();
91 | return jedis.get(key);
92 | } catch (Exception e) {
93 | log.error("get key:{} error", key, e);
94 | return null;
95 | } finally {
96 | close(jedis);
97 | }
98 | }
99 |
100 | /**
101 | * 删除key
102 | *
103 | * @param key
104 | * @return
105 | */
106 | public Long del(String key) {
107 | Jedis jedis = null;
108 | try {
109 | jedis = getJedis();
110 | return jedis.del(key.getBytes());
111 | } catch (Exception e) {
112 | log.error("del key:{} error", key, e);
113 | return null;
114 | } finally {
115 | close(jedis);
116 | }
117 | }
118 |
119 | /**
120 | * 判断key是否存在
121 | *
122 | * @param key
123 | * @return
124 | */
125 | public Boolean exists(String key) {
126 | Jedis jedis = null;
127 | try {
128 | jedis = getJedis();
129 | return jedis.exists(key.getBytes());
130 | } catch (Exception e) {
131 | log.error("exists key:{} error", key, e);
132 | return null;
133 | } finally {
134 | close(jedis);
135 | }
136 | }
137 |
138 | /**
139 | * 设值key过期时间
140 | *
141 | * @param key
142 | * @param expireTime 过期时间, 单位: s
143 | * @return
144 | */
145 | public Long expire(String key, int expireTime) {
146 | Jedis jedis = null;
147 | try {
148 | jedis = getJedis();
149 | return jedis.expire(key.getBytes(), expireTime);
150 | } catch (Exception e) {
151 | log.error("expire key:{} error", key, e);
152 | return null;
153 | } finally {
154 | close(jedis);
155 | }
156 | }
157 |
158 | /**
159 | * 获取剩余时间
160 | *
161 | * @param key
162 | * @return
163 | */
164 | public Long ttl(String key) {
165 | Jedis jedis = null;
166 | try {
167 | jedis = getJedis();
168 | return jedis.ttl(key);
169 | } catch (Exception e) {
170 | log.error("ttl key:{} error", key, e);
171 | return null;
172 | } finally {
173 | close(jedis);
174 | }
175 | }
176 |
177 | private void close(Jedis jedis) {
178 | if (null != jedis) {
179 | jedis.close();
180 | }
181 | }
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | https://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.io.File;
21 | import java.io.FileInputStream;
22 | import java.io.FileOutputStream;
23 | import java.io.IOException;
24 | import java.net.URL;
25 | import java.nio.channels.Channels;
26 | import java.nio.channels.ReadableByteChannel;
27 | import java.util.Properties;
28 |
29 | public class MavenWrapperDownloader {
30 |
31 | /**
32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
33 | */
34 | private static final String DEFAULT_DOWNLOAD_URL =
35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
36 |
37 | /**
38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
39 | * use instead of the default one.
40 | */
41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
42 | ".mvn/wrapper/maven-wrapper.properties";
43 |
44 | /**
45 | * Path where the maven-wrapper.jar will be saved to.
46 | */
47 | private static final String MAVEN_WRAPPER_JAR_PATH =
48 | ".mvn/wrapper/maven-wrapper.jar";
49 |
50 | /**
51 | * Name of the property which should be used to override the default download url for the wrapper.
52 | */
53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
54 |
55 | public static void main(String args[]) {
56 | System.out.println("- Downloader started");
57 | File baseDirectory = new File(args[0]);
58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
59 |
60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
61 | // wrapperUrl parameter.
62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
63 | String url = DEFAULT_DOWNLOAD_URL;
64 | if(mavenWrapperPropertyFile.exists()) {
65 | FileInputStream mavenWrapperPropertyFileInputStream = null;
66 | try {
67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
68 | Properties mavenWrapperProperties = new Properties();
69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
71 | } catch (IOException e) {
72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
73 | } finally {
74 | try {
75 | if(mavenWrapperPropertyFileInputStream != null) {
76 | mavenWrapperPropertyFileInputStream.close();
77 | }
78 | } catch (IOException e) {
79 | // Ignore ...
80 | }
81 | }
82 | }
83 | System.out.println("- Downloading from: : " + url);
84 |
85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
86 | if(!outputFile.getParentFile().exists()) {
87 | if(!outputFile.getParentFile().mkdirs()) {
88 | System.out.println(
89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
90 | }
91 | }
92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
93 | try {
94 | downloadFileFromURL(url, outputFile);
95 | System.out.println("Done");
96 | System.exit(0);
97 | } catch (Throwable e) {
98 | System.out.println("- Error downloading");
99 | e.printStackTrace();
100 | System.exit(1);
101 | }
102 | }
103 |
104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
105 | URL website = new URL(urlString);
106 | ReadableByteChannel rbc;
107 | rbc = Channels.newChannel(website.openStream());
108 | FileOutputStream fos = new FileOutputStream(destination);
109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
110 | fos.close();
111 | rbc.close();
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/OkHttpUtils.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import okhttp3.*;
5 | import org.apache.commons.lang3.exception.ExceptionUtils;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Component;
8 |
9 | import java.util.Map;
10 |
11 | @Slf4j
12 | @Component
13 | public class OkHttpUtils {
14 |
15 | private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
16 | private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8");
17 |
18 | @Autowired
19 | private OkHttpClient okHttpClient;
20 |
21 | /**
22 | * get 请求
23 | * @param url 请求url地址
24 | * @return string
25 | * */
26 | public String doGet(String url) {
27 | return doGet(url, null, null);
28 | }
29 |
30 | /**
31 | * get 请求
32 | * @param url 请求url地址
33 | * @param params 请求参数 map
34 | * @return string
35 | * */
36 | public String doGet(String url, Map params) {
37 | return doGet(url, params, null);
38 | }
39 |
40 | /**
41 | * get 请求
42 | * @param url 请求url地址
43 | * @param headers 请求头字段 {k1, v1 k2, v2, ...}
44 | * @return string
45 | * */
46 | public String doGet(String url, String[] headers) {
47 | return doGet(url, null, headers);
48 | }
49 |
50 | /**
51 | * get 请求
52 | * @param url 请求url地址
53 | * @param params 请求参数 map
54 | * @param headers 请求头字段 {k1, v1 k2, v2, ...}
55 | * @return string
56 | * */
57 | public String doGet(String url, Map params, String[] headers) {
58 | StringBuilder sb = new StringBuilder(url);
59 | if (params != null && params.keySet().size() > 0) {
60 | boolean firstFlag = true;
61 | for (String key : params.keySet()) {
62 | if (firstFlag) {
63 | sb.append("?").append(key).append("=").append(params.get(key));
64 | firstFlag = false;
65 | } else {
66 | sb.append("&").append(key).append("=").append(params.get(key));
67 | }
68 | }
69 | }
70 |
71 | Request.Builder builder = new Request.Builder();
72 | if (headers != null && headers.length > 0) {
73 | if (headers.length % 2 == 0) {
74 | for (int i = 0; i < headers.length; i = i + 2) {
75 | builder.addHeader(headers[i], headers[i + 1]);
76 | }
77 | } else {
78 | log.warn("headers's length[{}] is error.", headers.length);
79 | }
80 |
81 | }
82 |
83 | Request request = builder.url(sb.toString()).build();
84 | log.info("do get request and url[{}]", sb.toString());
85 | return execute(request);
86 | }
87 |
88 | /**
89 | * post 请求
90 | * @param url 请求url地址
91 | * @param params 请求参数 map
92 | * @return string
93 | */
94 | public String doPost(String url, Map params) {
95 | FormBody.Builder builder = new FormBody.Builder();
96 |
97 | if (params != null && params.keySet().size() > 0) {
98 | for (String key : params.keySet()) {
99 | builder.add(key, params.get(key));
100 | }
101 | }
102 | Request request = new Request.Builder().url(url).post(builder.build()).build();
103 | log.info("do post request and url[{}]", url);
104 |
105 | return execute(request);
106 | }
107 |
108 |
109 | /**
110 | * post 请求, 请求数据为 json 的字符串
111 | * @param url 请求url地址
112 | * @param json 请求数据, json 字符串
113 | * @return string
114 | */
115 | public String doPostJson(String url, String json) {
116 | log.info("do post request and url[{}]", url);
117 | return exectePost(url, json, JSON);
118 | }
119 |
120 | /**
121 | * post 请求, 请求数据为 xml 的字符串
122 | * @param url 请求url地址
123 | * @param xml 请求数据, xml 字符串
124 | * @return string
125 | */
126 | public String doPostXml(String url, String xml) {
127 | log.info("do post request and url[{}]", url);
128 | return exectePost(url, xml, XML);
129 | }
130 |
131 |
132 | private String exectePost(String url, String data, MediaType contentType) {
133 | RequestBody requestBody = RequestBody.create(contentType, data);
134 | Request request = new Request.Builder().url(url).post(requestBody).build();
135 |
136 | return execute(request);
137 | }
138 |
139 | private String execute(Request request) {
140 | Response response = null;
141 | try {
142 | response = okHttpClient.newCall(request).execute();
143 | if (response.isSuccessful()) {
144 | return response.body().string();
145 | }
146 | } catch (Exception e) {
147 | log.error(ExceptionUtils.getStackTrace(e));
148 | } finally {
149 | if (response != null) {
150 | response.close();
151 | }
152 | }
153 | return "";
154 | }
155 |
156 | }
157 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/controller/TestController.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.controller;
2 |
3 | import com.google.common.collect.Lists;
4 | import com.wangzaiplus.test.annotation.AccessLimit;
5 | import com.wangzaiplus.test.annotation.ApiIdempotent;
6 | import com.wangzaiplus.test.common.ServerResponse;
7 | import com.wangzaiplus.test.dto.UserDto;
8 | import com.wangzaiplus.test.mapper.MsgLogMapper;
9 | import com.wangzaiplus.test.mapper.UserMapper;
10 | import com.wangzaiplus.test.pojo.Mail;
11 | import com.wangzaiplus.test.pojo.User;
12 | import com.wangzaiplus.test.service.TestService;
13 | import com.wangzaiplus.test.service.batch.mapperproxy.MapperProxy;
14 | import com.wangzaiplus.test.util.MailUtil;
15 | import com.wangzaiplus.test.util.RandomUtil;
16 | import lombok.extern.slf4j.Slf4j;
17 | import org.springframework.beans.factory.annotation.Autowired;
18 | import org.springframework.scheduling.annotation.Async;
19 | import org.springframework.validation.Errors;
20 | import org.springframework.validation.annotation.Validated;
21 | import org.springframework.web.bind.annotation.PostMapping;
22 | import org.springframework.web.bind.annotation.RequestBody;
23 | import org.springframework.web.bind.annotation.RequestMapping;
24 | import org.springframework.web.bind.annotation.RestController;
25 |
26 | import java.util.List;
27 |
28 | @RestController
29 | @RequestMapping("/test")
30 | @Slf4j
31 | public class TestController {
32 |
33 | @Autowired
34 | private TestService testService;
35 |
36 | @Autowired
37 | private UserMapper userMapper;
38 |
39 | @Autowired
40 | private MsgLogMapper msgLogMapper;
41 |
42 | @Autowired
43 | private MailUtil mailUtil;
44 |
45 | @ApiIdempotent
46 | @PostMapping("testIdempotence")
47 | public ServerResponse testIdempotence() {
48 | return testService.testIdempotence();
49 | }
50 |
51 | @AccessLimit(maxCount = 5, seconds = 5)
52 | @PostMapping("accessLimit")
53 | public ServerResponse accessLimit() {
54 | return testService.accessLimit();
55 | }
56 |
57 | @PostMapping("send")
58 | public ServerResponse sendMail(@Validated Mail mail, Errors errors) {
59 | if (errors.hasErrors()) {
60 | String msg = errors.getFieldError().getDefaultMessage();
61 | return ServerResponse.error(msg);
62 | }
63 |
64 | return testService.send(mail);
65 | }
66 |
67 | @PostMapping("single")
68 | public ServerResponse single(int size) {
69 | List list = Lists.newArrayList();
70 |
71 | for (int i = 0; i < size; i++) {
72 | String str = RandomUtil.UUID32();
73 | User user = User.builder().username(str).password(str).build();
74 | list.add(user);
75 | }
76 |
77 | long startTime = System.nanoTime();
78 | log.info("batch insert costs: {} ms", (System.nanoTime() - startTime) / 1000000);
79 |
80 | return ServerResponse.success();
81 | }
82 |
83 | @PostMapping("batchInsert")
84 | public ServerResponse batchInsert(int size) {
85 | List list = Lists.newArrayList();
86 |
87 | for (int i = 0; i < size; i++) {
88 | String str = RandomUtil.UUID32();
89 | User user = User.builder().username(str).password(str).build();
90 | list.add(user);
91 | }
92 |
93 | new MapperProxy(userMapper).batchInsert(list);
94 |
95 | return ServerResponse.success();
96 | }
97 |
98 | @PostMapping("batchUpdate")
99 | public ServerResponse batchUpdate(String ids) {
100 | List list = Lists.newArrayList();
101 |
102 | String[] split = ids.split(",");
103 | for (String id : split) {
104 | User user = User.builder().id(Integer.valueOf(id)).username("batchUpdate_" + RandomUtil.UUID32()).password("123456").build();
105 | list.add(user);
106 | }
107 |
108 | new MapperProxy(userMapper).batchUpdate(list);
109 |
110 | return ServerResponse.success();
111 | }
112 |
113 | @PostMapping("sync")
114 | public ServerResponse sync() {
115 | List list = Lists.newArrayList();
116 | for (int i = 0; i < 300; i++) {
117 | String uuid32 = RandomUtil.UUID32();
118 | User user = User.builder().username(uuid32).password(uuid32).build();
119 | list.add(user);
120 | }
121 |
122 | userMapper.batchInsert(list);
123 |
124 | check(list);
125 |
126 | return ServerResponse.success();
127 | }
128 |
129 | @Async
130 | public void check(List list) {
131 | String username = list.get(list.size() - 1).getUsername();
132 | User user = userMapper.selectByUsername(username);
133 | log.info(user.getUsername());
134 | }
135 |
136 | @PostMapping("sendMail")
137 | public ServerResponse sendMail(@RequestBody Mail mail) {
138 | Mail build = Mail.builder().to(mail.getTo()).title(mail.getTitle()).content(mail.getContent()).build();
139 | boolean send = mailUtil.send(build);
140 | return ServerResponse.success(send);
141 | }
142 |
143 | public static ThreadLocal userDtoThreadLocal = new ThreadLocal<>();
144 |
145 | public static void main(String[] args) {
146 | userDtoThreadLocal.set(UserDto.builder().build());
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.1.5.RELEASE
9 |
10 |
11 | com.wangzaiplus
12 | test
13 | 0.0.1-SNAPSHOT
14 | test
15 | Demo project for Spring Boot
16 |
17 |
18 | 1.8
19 | 2.9.0
20 |
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-web
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-test
30 | test
31 |
32 |
33 |
34 | org.redisson
35 | redisson
36 | 3.6.5
37 |
38 |
39 |
40 | redis.clients
41 | jedis
42 | ${jedis.version}
43 |
44 |
45 |
46 | org.mybatis.spring.boot
47 | mybatis-spring-boot-starter
48 | 2.0.0
49 |
50 |
51 | com.github.pagehelper
52 | pagehelper-spring-boot-starter
53 | 1.3.0
54 |
55 |
56 |
57 | mysql
58 | mysql-connector-java
59 |
60 |
61 |
62 | org.projectlombok
63 | lombok
64 | 1.16.10
65 |
66 |
67 |
68 | org.apache.commons
69 | commons-lang3
70 | 3.4
71 |
72 |
73 |
74 | org.springframework.boot
75 | spring-boot-starter-aop
76 |
77 |
78 |
79 | com.google.guava
80 | guava
81 | 26.0-jre
82 |
83 |
84 |
85 | joda-time
86 | joda-time
87 | 2.10
88 |
89 |
90 |
91 | org.springframework.boot
92 | spring-boot-starter-amqp
93 |
94 |
95 |
96 | org.springframework.boot
97 | spring-boot-starter-mail
98 |
99 |
100 | org.apache.commons
101 | commons-collections4
102 | 4.1
103 |
104 |
105 | com.alibaba
106 | druid
107 | 1.1.20
108 |
109 |
110 | org.jdom
111 | jdom
112 | 2.0.2
113 |
114 |
115 | com.squareup.okhttp3
116 | okhttp
117 | 3.10.0
118 |
119 |
120 |
121 | org.codehaus.groovy
122 | groovy-all
123 | 3.0.0
124 | pom
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | org.springframework.boot
133 | spring-boot-maven-plugin
134 |
135 |
136 |
137 |
138 |
139 |
140 | src/main/java
141 |
142 | **/*.*
143 |
144 |
145 |
146 | src/main/resources
147 |
148 | **/*.*
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | spring-snapshots
157 | Spring Snapshots
158 | https://repo.spring.io/snapshot
159 |
160 | true
161 |
162 |
163 |
164 | spring-milestones
165 | Spring Milestones
166 | https://repo.spring.io/milestone
167 |
168 |
169 |
170 |
171 | spring-snapshots
172 | Spring Snapshots
173 | https://repo.spring.io/snapshot
174 |
175 | true
176 |
177 |
178 |
179 | spring-milestones
180 | Spring Milestones
181 | https://repo.spring.io/milestone
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/common/Constant.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.common;
2 |
3 | import com.wangzaiplus.test.dto.FundRankDto;
4 | import com.wangzaiplus.test.dto.FundTypeDto;
5 | import com.wangzaiplus.test.dto.FundYieldDto;
6 |
7 | import java.util.Arrays;
8 | import java.util.List;
9 | import java.util.Optional;
10 | import java.util.stream.Collectors;
11 |
12 | public class Constant {
13 |
14 | public static final int MAX_SIZE_PER_TIME = 1000;
15 | public static final int INDEX_ZERO = 0;
16 | public static final int INDEX_ONE = 1;
17 | public static final int INDEX_TWO = 2;
18 | public static final int INDEX_THREE = 3;
19 |
20 | public static final int NUMBER_ZERO = 0;
21 | public static final int NUMBER_ONE = 1;
22 |
23 | public static final String COLON = ":";
24 | public static final String COMMA = ",";
25 | public static final String DOUBLE_STRIGULA = "--";
26 | public static final String REPLACEMENT_TARGET = "-99999%";
27 |
28 | public static final String UNKNOWN_TYPE = "未知类型";
29 |
30 | public interface Redis {
31 | String OK = "OK";
32 | // 过期时间, 60s, 一分钟
33 | Integer EXPIRE_TIME_MINUTE = 60;
34 | // 过期时间, 一小时
35 | Integer EXPIRE_TIME_HOUR = 60 * 60;
36 | // 过期时间, 一天
37 | Integer EXPIRE_TIME_DAY = 60 * 60 * 24;
38 | String TOKEN_PREFIX = "token:";
39 | String MSG_CONSUMER_PREFIX = "consumer:";
40 | String ACCESS_LIMIT_PREFIX = "accessLimit:";
41 | String FUND_RANK = "fundRank";
42 | String FUND_LIST = "fundList";
43 | }
44 |
45 | public interface LogType {
46 | // 登录
47 | Integer LOGIN = 1;
48 | // 登出
49 | Integer LOGOUT = 2;
50 | }
51 |
52 | public interface MsgLogStatus {
53 | // 消息投递中
54 | Integer DELIVERING = 0;
55 | // 投递成功
56 | Integer DELIVER_SUCCESS = 1;
57 | // 投递失败
58 | Integer DELIVER_FAIL = 2;
59 | // 已消费
60 | Integer CONSUMED_SUCCESS = 3;
61 | }
62 |
63 | public enum CalculateTypeEnum {
64 | ADD(1, "加"),
65 | SUBTRACT(2, "减"),
66 | MULTIPLY(3, "乘"),
67 | DIVIDE(4, "除")
68 | ;
69 |
70 | Integer type;
71 | String desc;
72 |
73 | CalculateTypeEnum(Integer type, String desc) {
74 | this.type = type;
75 | this.desc = desc;
76 | }
77 |
78 | public Integer getType() {
79 | return type;
80 | }
81 |
82 | public String getDesc() {
83 | return desc;
84 | }
85 | }
86 |
87 | public enum FundType {
88 | STOCK_FUND(1, "股票型"),
89 | HYBRID_FUND(2, "混合型"),
90 | BOND_FUND(3, "债券型"),
91 | INDEX_FUND(4, "指数型"),
92 | QDII(5, "QDII")
93 | ;
94 |
95 | private Integer type;
96 | private String desc;
97 |
98 | FundType(Integer type, String desc) {
99 | this.type = type;
100 | this.desc = desc;
101 | }
102 |
103 | public Integer getType() {
104 | return type;
105 | }
106 |
107 | public String getDesc() {
108 | return desc;
109 | }
110 |
111 | public static boolean contains(Integer type) {
112 | FundType[] values = FundType.values();
113 | return Arrays.stream(values).filter(fundType -> fundType.getType() == type).findAny().isPresent();
114 | }
115 |
116 | public static List getTypeList() {
117 | FundType[] values = FundType.values();
118 | return Arrays.stream(values).map(fundType ->
119 | FundTypeDto.builder()
120 | .type(fundType.getType())
121 | .desc(fundType.getDesc())
122 | .build()
123 | ).collect(Collectors.toList());
124 | }
125 |
126 | public static String getDescByType(Integer type) {
127 | FundType[] values = FundType.values();
128 | Optional first = Arrays.stream(values).filter(fundType -> fundType.getType() == type).findFirst();
129 | boolean exists = first.isPresent();
130 | return exists ? first.get().getDesc() : UNKNOWN_TYPE;
131 | }
132 | }
133 |
134 | public enum FundYield {
135 | YIELD_OF_ONE_YEAR("yield_of_one_year", "近1年收益率"),
136 | YIELD_OF_TWO_YEAR("yield_of_two_year", "近2年收益率"),
137 | YIELD_OF_THREE_YEAR("yield_of_three_year", "近3年收益率"),
138 | YIELD_OF_FIVE_YEAR("yield_of_five_year", "近5年收益率")
139 | ;
140 |
141 | private String yield;
142 | private String desc;
143 |
144 | FundYield(String yield, String desc) {
145 | this.yield = yield;
146 | this.desc = desc;
147 | }
148 |
149 | public String getYield() {
150 | return yield;
151 | }
152 |
153 | public String getDesc() {
154 | return desc;
155 | }
156 |
157 | public static boolean contains(String yield) {
158 | FundYield[] values = FundYield.values();
159 | return Arrays.stream(values).filter(fundYield -> fundYield.getYield().equals(yield)).findAny().isPresent();
160 | }
161 |
162 | public static List getYieldList() {
163 | FundYield[] values = FundYield.values();
164 | return Arrays.stream(values).map(fundYield ->
165 | FundYieldDto.builder()
166 | .yield(fundYield.getYield())
167 | .desc(fundYield.getDesc())
168 | .build()
169 | ).collect(Collectors.toList());
170 | }
171 | }
172 |
173 | public enum FundRank {
174 | TOP_50(50, "前50"),
175 | TOP_100(100, "前100"),
176 | TOP_150(150, "前150"),
177 | TOP_200(200, "前200"),
178 | ;
179 |
180 | private Integer rank;
181 | private String desc;
182 |
183 | FundRank(Integer rank, String desc) {
184 | this.rank = rank;
185 | this.desc = desc;
186 | }
187 |
188 | public Integer getRank() {
189 | return rank;
190 | }
191 |
192 | public String getDesc() {
193 | return desc;
194 | }
195 |
196 | public static List getRankList() {
197 | FundRank[] values = FundRank.values();
198 | return Arrays.stream(values).map(rank ->
199 | FundRankDto.builder()
200 | .rank(rank.getRank())
201 | .desc(rank.getDesc())
202 | .build()
203 | ).collect(Collectors.toList());
204 | }
205 | }
206 |
207 | public enum FundSortType {
208 | ASC("asc"),
209 | DESC("desc"),
210 | ;
211 |
212 | private String type;
213 |
214 | FundSortType(String type) {
215 | this.type = type;
216 | }
217 |
218 | public String getType() {
219 | return type;
220 | }
221 | }
222 |
223 | }
224 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/JodaTimeUtil.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.apache.commons.lang3.StringUtils;
5 | import org.joda.time.DateTime;
6 | import org.joda.time.format.DateTimeFormat;
7 | import org.joda.time.format.DateTimeFormatter;
8 |
9 | import java.util.Date;
10 |
11 | @Slf4j
12 | public class JodaTimeUtil {
13 |
14 | private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
15 |
16 | /**
17 | * date类型 -> string类型
18 | *
19 | * @param date
20 | * @return
21 | */
22 | public static String dateToStr(Date date) {
23 | return dateToStr(date, STANDARD_FORMAT);
24 | }
25 |
26 | /**
27 | * date类型 -> string类型
28 | *
29 | * @param date
30 | * @param format 自定义日期格式
31 | * @return
32 | */
33 | public static String dateToStr(Date date, String format) {
34 | if (date == null) {
35 | return null;
36 | }
37 |
38 | format = StringUtils.isBlank(format) ? STANDARD_FORMAT : format;
39 | DateTime dateTime = new DateTime(date);
40 | return dateTime.toString(format);
41 | }
42 |
43 | /**
44 | * string类型 -> date类型
45 | *
46 | * @param timeStr
47 | * @return
48 | */
49 | public static Date strToDate(String timeStr) {
50 | return strToDate(timeStr, STANDARD_FORMAT);
51 | }
52 |
53 | /**
54 | * string类型 -> date类型
55 | *
56 | * @param timeStr
57 | * @param format 自定义日期格式
58 | * @return
59 | */
60 | public static Date strToDate(String timeStr, String format) {
61 | if (StringUtils.isBlank(timeStr)) {
62 | return null;
63 | }
64 |
65 | format = StringUtils.isBlank(format) ? STANDARD_FORMAT : format;
66 |
67 | DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(format);
68 | DateTime dateTime;
69 | try {
70 | dateTime = dateTimeFormatter.parseDateTime(timeStr);
71 | } catch (Exception e) {
72 | log.error("strToDate error: timeStr: {}", timeStr, e);
73 | return null;
74 | }
75 |
76 | return dateTime.toDate();
77 | }
78 |
79 | /**
80 | * 判断date日期是否过期(与当前时刻比较)
81 | *
82 | * @param date
83 | * @return
84 | */
85 | public static Boolean isTimeExpired(Date date) {
86 | String timeStr = dateToStr(date);
87 | return isBeforeNow(timeStr);
88 | }
89 |
90 | /**
91 | * 判断date日期是否过期(与当前时刻比较)
92 | *
93 | * @param timeStr
94 | * @return
95 | */
96 | public static Boolean isTimeExpired(String timeStr) {
97 | if (StringUtils.isBlank(timeStr)) {
98 | return true;
99 | }
100 |
101 | return isBeforeNow(timeStr);
102 | }
103 |
104 | /**
105 | * 判断timeStr是否在当前时刻之前
106 | *
107 | * @param timeStr
108 | * @return
109 | */
110 | private static Boolean isBeforeNow(String timeStr) {
111 | DateTimeFormatter format = DateTimeFormat.forPattern(STANDARD_FORMAT);
112 | DateTime dateTime;
113 | try {
114 | dateTime = DateTime.parse(timeStr, format);
115 | } catch (Exception e) {
116 | log.error("isBeforeNow error: timeStr: {}", timeStr, e);
117 | return null;
118 | }
119 | return dateTime.isBeforeNow();
120 | }
121 |
122 | /**
123 | * 日期加天数
124 | *
125 | * @param date
126 | * @param days
127 | * @return
128 | */
129 | public static Date plusDays(Date date, int days) {
130 | return plusOrMinusDays(date, days, 0);
131 | }
132 |
133 | /**
134 | * 日期减天数
135 | *
136 | * @param date
137 | * @param days
138 | * @return
139 | */
140 | public static Date minusDays(Date date, int days) {
141 | return plusOrMinusDays(date, days, 1);
142 | }
143 |
144 | /**
145 | * 加减天数
146 | *
147 | * @param date
148 | * @param days
149 | * @param type 0:加天数 1:减天数
150 | * @return
151 | */
152 | private static Date plusOrMinusDays(Date date, int days, Integer type) {
153 | if (null == date) {
154 | return null;
155 | }
156 |
157 | DateTime dateTime = new DateTime(date);
158 | if (type == 0) {
159 | dateTime = dateTime.plusDays(days);
160 | } else {
161 | dateTime = dateTime.minusDays(days);
162 | }
163 |
164 | return dateTime.toDate();
165 | }
166 |
167 | /**
168 | * 日期加分钟
169 | *
170 | * @param date
171 | * @param minutes
172 | * @return
173 | */
174 | public static Date plusMinutes(Date date, int minutes) {
175 | return plusOrMinusMinutes(date, minutes, 0);
176 | }
177 |
178 | /**
179 | * 日期减分钟
180 | *
181 | * @param date
182 | * @param minutes
183 | * @return
184 | */
185 | public static Date minusMinutes(Date date, int minutes) {
186 | return plusOrMinusMinutes(date, minutes, 1);
187 | }
188 |
189 | /**
190 | * 加减分钟
191 | *
192 | * @param date
193 | * @param minutes
194 | * @param type 0:加分钟 1:减分钟
195 | * @return
196 | */
197 | private static Date plusOrMinusMinutes(Date date, int minutes, Integer type) {
198 | if (null == date) {
199 | return null;
200 | }
201 |
202 | DateTime dateTime = new DateTime(date);
203 | if (type == 0) {
204 | dateTime = dateTime.plusMinutes(minutes);
205 | } else {
206 | dateTime = dateTime.minusMinutes(minutes);
207 | }
208 |
209 | return dateTime.toDate();
210 | }
211 |
212 | /**
213 | * 日期加月份
214 | *
215 | * @param date
216 | * @param months
217 | * @return
218 | */
219 | public static Date plusMonths(Date date, int months) {
220 | return plusOrMinusMonths(date, months, 0);
221 | }
222 |
223 | /**
224 | * 日期减月份
225 | *
226 | * @param date
227 | * @param months
228 | * @return
229 | */
230 | public static Date minusMonths(Date date, int months) {
231 | return plusOrMinusMonths(date, months, 1);
232 | }
233 |
234 | /**
235 | * 加减月份
236 | *
237 | * @param date
238 | * @param months
239 | * @param type 0:加月份 1:减月份
240 | * @return
241 | */
242 | private static Date plusOrMinusMonths(Date date, int months, Integer type) {
243 | if (null == date) {
244 | return null;
245 | }
246 |
247 | DateTime dateTime = new DateTime(date);
248 | if (type == 0) {
249 | dateTime = dateTime.plusMonths(months);
250 | } else {
251 | dateTime = dateTime.minusMonths(months);
252 | }
253 |
254 | return dateTime.toDate();
255 | }
256 |
257 | /**
258 | * 判断target是否在开始和结束时间之间
259 | *
260 | * @param target
261 | * @param startTime
262 | * @param endTime
263 | * @return
264 | */
265 | public static Boolean isBetweenStartAndEndTime(Date target, Date startTime, Date endTime) {
266 | if (null == target || null == startTime || null == endTime) {
267 | return false;
268 | }
269 |
270 | DateTime dateTime = new DateTime(target);
271 | return dateTime.isAfter(startTime.getTime()) && dateTime.isBefore(endTime.getTime());
272 | }
273 |
274 | }
275 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/mapper/FundMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | id
26 | ,code
27 | ,name
28 | ,net_value
29 | ,yield_of_one_year
30 | ,yield_of_two_year
31 | ,yield_of_three_year
32 | ,yield_of_five_year
33 | ,type
34 | ,established_time
35 | ,asset
36 | ,manager
37 | ,status
38 | ,is_deleted
39 | ,created_time
40 | ,updated_time
41 |
42 |
43 |
48 |
49 |
55 |
56 |
57 | INSERT INTO fund(
58 | code
59 | ,name
60 | ,net_value
61 | ,yield_of_one_year
62 | ,yield_of_two_year
63 | ,yield_of_three_year
64 | ,yield_of_five_year
65 | ,type
66 | ,established_time
67 | ,asset
68 | ,manager
69 | )
70 | VALUES (
71 | #{code}
72 | ,#{name}
73 | ,#{netValue}
74 | ,#{yieldOfOneYear}
75 | ,#{yieldOfTwoYear}
76 | ,#{yieldOfThreeYear}
77 | ,#{yieldOfFiveYear}
78 | ,#{type}
79 | ,#{establishedTime}
80 | ,#{asset}
81 | ,#{manager}
82 | )
83 |
84 |
85 |
86 | UPDATE fund SET
87 |
88 | code = #{code},
89 |
90 |
91 | name = #{name},
92 |
93 |
94 | net_value = #{netValue},
95 |
96 |
97 | yield_of_one_year = #{yieldOfOneYear},
98 |
99 |
100 | yield_of_two_year = #{yieldOfTwoYear},
101 |
102 |
103 | yield_of_three_year = #{yieldOfThreeYear},
104 |
105 |
106 | yield_of_five_year = #{yieldOfFiveYear},
107 |
108 |
109 | type = #{type},
110 |
111 |
112 | established_time = #{establishedTime},
113 |
114 |
115 | asset = #{asset},
116 |
117 |
118 | manager = #{manager},
119 |
120 |
121 | status = #{status},
122 |
123 |
124 | is_deleted = #{isDeleted},
125 |
126 | updated_time = now()
127 | WHERE id = #{id}
128 |
129 |
130 |
131 | DELETE FROM fund WHERE id =#{id}
132 |
133 |
134 |
135 | insert into user(username, password, password2, password3, password4, password5, password6,
136 | password7, password8, password9, password10)
137 | values
138 |
139 | (#{item.username}, #{item.password}, #{item.password2}, #{item.password3},
140 | #{item.password4}, #{item.password5}, #{item.password6}, #{item.password7},
141 | #{item.password8}, #{item.password9}, #{item.password10})
142 |
143 |
144 |
145 |
146 | update user
147 |
148 |
149 |
150 | when id = #{item.id} then #{item.username}
151 |
152 |
153 |
154 |
155 | when id = #{item.id} then #{item.password}
156 |
157 |
158 |
159 | where id in
160 |
161 | #{item.id}
162 |
163 |
164 |
165 |
171 |
172 |
181 |
182 |
190 |
191 |
202 |
203 |
212 |
213 |
--------------------------------------------------------------------------------
/src/main/java/com/wangzaiplus/test/util/FundUtils.java:
--------------------------------------------------------------------------------
1 | package com.wangzaiplus.test.util;
2 |
3 | import com.google.common.collect.Lists;
4 | import com.wangzaiplus.test.common.Constant;
5 | import com.wangzaiplus.test.dto.FundDto;
6 | import com.wangzaiplus.test.dto.FundJsonResponseDto;
7 | import com.wangzaiplus.test.exception.ServiceException;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.apache.commons.collections4.CollectionUtils;
10 | import org.apache.commons.lang3.StringUtils;
11 | import org.jdom2.Document;
12 | import org.jdom2.Element;
13 | import org.jdom2.input.SAXBuilder;
14 |
15 | import java.io.ByteArrayInputStream;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import java.util.stream.Collectors;
19 |
20 | @Slf4j
21 | public class FundUtils {
22 |
23 | private static final String BODY = "tbody";
24 | private static final String TR = "tr";
25 | private static final String TD = "td";
26 | private static final String COMMA = ",";
27 | private static final String QUESTION_MARK = "?";
28 | private static final String COLS_NUM = "3,4,6,8,9,10,11";
29 | private static final String PARAM_T = "t=";
30 | private static final String PARAM_PAGE = "&page=1&psize=50000";
31 |
32 | public static final String FUND_URL = "http://fund.eastmoney.com/api/Dtshph.ashx";
33 |
34 | public static List getFundDtoList(Integer type) {
35 | if (!Constant.FundType.contains(type)) {
36 | throw new ServiceException("type error: " + type);
37 | }
38 |
39 | List> lists = getFundData(type);
40 | if (CollectionUtils.isEmpty(lists)) {
41 | return null;
42 | }
43 |
44 | return lists.stream().map(list -> {
45 | FundDto dto = FundDto.builder().type(type).build();
46 | try {
47 | BeanUtils.convert(list, dto);
48 | } catch (Exception e) {
49 | log.error("BeanUtils.convert error: " + e.getMessage(), e);
50 | }
51 | return dto;
52 | }).collect(Collectors.toList());
53 | }
54 |
55 | public static List> getFundData(Integer type) {
56 | if (!Constant.FundType.contains(type)) {
57 | throw new ServiceException("type error: " + type);
58 | }
59 |
60 | OkHttpUtils httpUtils = SpringContextUtil.getBean(OkHttpUtils.class);
61 | try {
62 | String response = httpUtils.doGet(FUND_URL + QUESTION_MARK + PARAM_T + type + PARAM_PAGE);
63 | List> lists = parseTable(response);
64 | return extract(lists, COLS_NUM);
65 | } catch (Exception e) {
66 | log.error("request fund data error: " + e.getMessage(), e);
67 | return null;
68 | }
69 | }
70 |
71 | public static List> parse(String string) {
72 | String json = getJsonFromResponse(string);
73 | String data = getData(json);
74 | return extract(parseTable(data), COLS_NUM);
75 | }
76 |
77 | private static String getJsonFromResponse(String response) {
78 | if (StringUtils.isBlank(response)) {
79 | log.info("response is blank");
80 | return null;
81 | }
82 |
83 | List list = extractMessage(response);
84 | if (CollectionUtils.isEmpty(list)) {
85 | log.info("extractFromBracket empty");
86 | return null;
87 | }
88 |
89 | return list.get(Constant.INDEX_ZERO);
90 | }
91 |
92 | private static String getData(String json) {
93 | if (StringUtils.isBlank(json)) {
94 | return null;
95 | }
96 |
97 | FundJsonResponseDto dto = JsonUtil.strToObj(json, FundJsonResponseDto.class);
98 | if (null == dto) {
99 | return null;
100 | }
101 |
102 | return dto.getData();
103 | }
104 |
105 | /**
106 | * 提取中括号中内容,忽略中括号中的中括号
107 | * @param msg
108 | * @return
109 | */
110 | public static List extractMessage(String msg) {
111 | List list = new ArrayList<>();
112 | int start = 0;
113 | int startFlag = 0;
114 | int endFlag = 0;
115 | for (int i = 0; i < msg.length(); i++) {
116 | if (msg.charAt(i) == '(') {
117 | startFlag++;
118 | if (startFlag == endFlag + 1) {
119 | start = i;
120 | }
121 | } else if (msg.charAt(i) == ')') {
122 | endFlag++;
123 | if (endFlag == startFlag) {
124 | list.add(msg.substring(start + 1, i));
125 | }
126 | }
127 | }
128 | return list;
129 | }
130 |
131 | /**
132 | * 解析table中td元素
133 | * @param data
134 | * @return
135 | */
136 | public static List> parseTable(String data) {
137 | if (StringUtils.isBlank(data)) {
138 | return null;
139 | }
140 |
141 | ByteArrayInputStream is = new ByteArrayInputStream(data.getBytes());
142 | Document document;
143 | try {
144 | document = new SAXBuilder().build(is);
145 | } catch (Exception e) {
146 | log.error("build error, " + e.getMessage(), e);
147 | return null;
148 | }
149 |
150 | Element root = document.getRootElement();
151 | List bodyList = root.getChildren(BODY);
152 | if (CollectionUtils.isEmpty(bodyList)) {
153 | log.info("body empty");
154 | return null;
155 | }
156 |
157 | Element element = bodyList.get(Constant.INDEX_ZERO);
158 | List trList = element.getChildren(TR);
159 | if (CollectionUtils.isEmpty(trList)) {
160 | log.info("tr empty");
161 | return null;
162 | }
163 |
164 | List> parentList = Lists.newArrayList();
165 | for (Element tr : trList) {
166 | List tdList = tr.getChildren(TD);
167 | if (CollectionUtils.isEmpty(tdList)) {
168 | log.info("td empty");
169 | continue;
170 | }
171 |
172 | List childrenList = Lists.newArrayList();
173 | for (Element td : tdList) {
174 | childrenList.add(td.getValue());
175 | }
176 |
177 | parentList.add(childrenList);
178 | }
179 |
180 | return parentList;
181 | }
182 |
183 | /**
184 | * 提取指定列
185 | * @param lists
186 | * @param colsNum
187 | * @return
188 | */
189 | private static List> extract(List> lists, String colsNum) {
190 | if (CollectionUtils.isEmpty(lists)) {
191 | return null;
192 | }
193 |
194 | for (List list : lists) {
195 | if (!checkCols(colsNum, list.size())) {
196 | return null;
197 | }
198 | }
199 |
200 | String[] split = colsNum.split(COMMA);
201 | List> parentList = Lists.newArrayList();
202 | for (List list : lists) {
203 | List childrenList = Lists.newArrayList();
204 | for (String s : split) {
205 | Integer colNum = Integer.valueOf(s.trim());
206 | Integer colIndex = colNum - Constant.NUMBER_ONE;
207 | childrenList.add(list.get(colIndex));
208 | }
209 | parentList.add(childrenList);
210 | }
211 |
212 | return parentList;
213 | }
214 |
215 | /**
216 | * 校验列序号是否合法
217 | * @param colsNum 如:1,2,5,8
218 | * @param size
219 | * @return
220 | */
221 | private static boolean checkCols(String colsNum, int size) {
222 | if (StringUtils.isBlank(colsNum)) {
223 | return false;
224 | }
225 |
226 | String[] split = colsNum.split(COMMA);
227 | for (String col : split) {
228 | Integer colNum;
229 | try {
230 | colNum = Integer.valueOf(col.trim());
231 | } catch (Exception e) {
232 | log.error("Integer.valueOf error, " + e.getMessage(), e);
233 | return false;
234 | }
235 |
236 | if (colNum < Constant.NUMBER_ONE) {
237 | log.error("colNum can't be less than 1");
238 | return false;
239 | }
240 |
241 | if (colNum > size) {
242 | log.error("colNum: {} can't be greater than colSize: {}", colNum, size);
243 | return false;
244 | }
245 | }
246 |
247 | return true;
248 | }
249 |
250 | }
251 |
--------------------------------------------------------------------------------