├── .gitignore
├── LICENSE
├── README.en.md
├── README.md
├── apijson
├── README.md
├── apijson.conf
├── apijson.rest
├── apijson.sql
├── bills.sql
├── checkcode.rest
├── district.sql
├── doc2fill.docx
├── pdnovel.rest
├── service.rest
└── tables.sql
├── http_load.sh
├── knife4j
├── group.json
└── swagger.json
├── my.pwd
├── pom.xml
├── postman.json
├── src
├── main
│ ├── java
│ │ ├── apijson
│ │ │ ├── JSON.java
│ │ │ ├── framework
│ │ │ │ ├── APIJSONApplication.java
│ │ │ │ └── APIJSONSQLExecutor.java
│ │ │ └── orm
│ │ │ │ └── AbstractParser.java
│ │ ├── ch
│ │ │ └── qos
│ │ │ │ └── logback
│ │ │ │ ├── classic
│ │ │ │ └── redis
│ │ │ │ │ └── RedisAppender.java
│ │ │ │ └── core
│ │ │ │ └── util
│ │ │ │ └── ExecutorServiceUtil.java
│ │ ├── com
│ │ │ ├── alibaba
│ │ │ │ └── druid
│ │ │ │ │ └── util
│ │ │ │ │ └── Base64.java
│ │ │ ├── mysql
│ │ │ │ └── jdbc
│ │ │ │ │ ├── AbandonedConnectionCleanupThread$1.class
│ │ │ │ │ ├── AbandonedConnectionCleanupThread$ConnectionFinalizerPhantomReference.class
│ │ │ │ │ ├── AbandonedConnectionCleanupThread.class
│ │ │ │ │ └── AbandonedConnectionCleanupThread.java
│ │ │ ├── networknt
│ │ │ │ ├── client
│ │ │ │ │ └── Http2Client.java
│ │ │ │ ├── config
│ │ │ │ │ ├── AesCrypto.java
│ │ │ │ │ └── RefreshScope.java
│ │ │ │ └── server
│ │ │ │ │ ├── Servers.java
│ │ │ │ │ └── UrlConfigLoader.java
│ │ │ └── xlongwei
│ │ │ │ └── light4j
│ │ │ │ ├── Servers.java
│ │ │ │ ├── apijson
│ │ │ │ ├── DemoApplication.java
│ │ │ │ ├── DemoController.java
│ │ │ │ ├── DemoFunctionParser.java
│ │ │ │ ├── DemoObjectParser.java
│ │ │ │ ├── DemoParser.java
│ │ │ │ ├── DemoSQLConfig.java
│ │ │ │ ├── DemoSQLExecutor.java
│ │ │ │ ├── DemoVerifier.java
│ │ │ │ └── model
│ │ │ │ │ ├── Privacy.java
│ │ │ │ │ ├── User.java
│ │ │ │ │ └── Verify.java
│ │ │ │ ├── beetl
│ │ │ │ ├── dao
│ │ │ │ │ └── UserDao.java
│ │ │ │ └── model
│ │ │ │ │ ├── District.java
│ │ │ │ │ ├── Ecdict.java
│ │ │ │ │ └── User.java
│ │ │ │ ├── handler
│ │ │ │ ├── DemoHandler.java
│ │ │ │ ├── ServiceHandler.java
│ │ │ │ ├── UploadHandler.java
│ │ │ │ ├── WeixinHandler.java
│ │ │ │ ├── demo
│ │ │ │ │ ├── IndexHandler.java
│ │ │ │ │ └── LogHandler.java
│ │ │ │ ├── service
│ │ │ │ │ ├── AnsjHandler.java
│ │ │ │ │ ├── ApijsonHandler.java
│ │ │ │ │ ├── BankCardHandler.java
│ │ │ │ │ ├── Base64ImageHandler.java
│ │ │ │ │ ├── CheckcodeHandler.java
│ │ │ │ │ ├── DatetimeHandler.java
│ │ │ │ │ ├── DelayHandler.java
│ │ │ │ │ ├── DesHandler.java
│ │ │ │ │ ├── DictHandler.java
│ │ │ │ │ ├── DistrictHandler.java
│ │ │ │ │ ├── DocHandler.java
│ │ │ │ │ ├── DruidHandler.java
│ │ │ │ │ ├── ExamHandler.java
│ │ │ │ │ ├── ExcelHandler.java
│ │ │ │ │ ├── HtmlHandler.java
│ │ │ │ │ ├── IdcardHandler.java
│ │ │ │ │ ├── IpHandler.java
│ │ │ │ │ ├── LayuiHandler.java
│ │ │ │ │ ├── MobileHandler.java
│ │ │ │ │ ├── MoneyHandler.java
│ │ │ │ │ ├── PdfHandler.java
│ │ │ │ │ ├── PdnovelHandler.java
│ │ │ │ │ ├── PinyinHandler.java
│ │ │ │ │ ├── PlateHandler.java
│ │ │ │ │ ├── PropertyHandler.java
│ │ │ │ │ ├── QrcodeHandler.java
│ │ │ │ │ ├── RsaHandler.java
│ │ │ │ │ ├── SequenceHandler.java
│ │ │ │ │ ├── TrainHandler.java
│ │ │ │ │ ├── UploadHandler.java
│ │ │ │ │ ├── ValidateHandler.java
│ │ │ │ │ └── WeixinHandler.java
│ │ │ │ └── weixin
│ │ │ │ │ ├── CalcHandler.java
│ │ │ │ │ ├── ClickHandler.java
│ │ │ │ │ ├── CounterHandler.java
│ │ │ │ │ ├── DictHandler.java
│ │ │ │ │ ├── FangdaiHandler.java
│ │ │ │ │ ├── ImageHandler.java
│ │ │ │ │ ├── KeyHandler.java
│ │ │ │ │ ├── LocationHandler.java
│ │ │ │ │ ├── NongliHandler.java
│ │ │ │ │ ├── PinyinHandler.java
│ │ │ │ │ ├── PlateHandler.java
│ │ │ │ │ ├── PoetryHandler.java
│ │ │ │ │ ├── PostHandler.java
│ │ │ │ │ ├── SubscribeHandler.java
│ │ │ │ │ ├── TrainHandler.java
│ │ │ │ │ ├── VoiceHandler.java
│ │ │ │ │ └── YoudaoHandler.java
│ │ │ │ ├── openapi
│ │ │ │ ├── OpenapiHandler.java
│ │ │ │ ├── extend
│ │ │ │ │ ├── DummyMiddlewareHandler.java
│ │ │ │ │ ├── MyCorrelationHandler.java
│ │ │ │ │ ├── MyJwtShiroHandler.java
│ │ │ │ │ └── MyRedisSessionRepository.java
│ │ │ │ └── handler
│ │ │ │ │ ├── DatetimeHandler.java
│ │ │ │ │ ├── ServiceHandler.java
│ │ │ │ │ └── UploadHandler.java
│ │ │ │ ├── provider
│ │ │ │ ├── WebSocketAbstractCallback.java
│ │ │ │ ├── WebSocketChatCallback.java
│ │ │ │ ├── WebSocketHandlerProvider.java
│ │ │ │ └── WebSocketServiceCallback.java
│ │ │ │ └── util
│ │ │ │ ├── AdtUtil.java
│ │ │ │ ├── BankUtil.java
│ │ │ │ ├── CardBin.java
│ │ │ │ ├── ConfigUtil.java
│ │ │ │ ├── DateUtil.java
│ │ │ │ ├── DesUtil.java
│ │ │ │ ├── DictUtil.java
│ │ │ │ ├── DocxUtil.java
│ │ │ │ ├── DruidUtil.java
│ │ │ │ ├── EcdictUtil.java
│ │ │ │ ├── ExcelUtil.java
│ │ │ │ ├── ExecUtil.java
│ │ │ │ ├── ExpUtil.java
│ │ │ │ ├── ExpireTimeMap.java
│ │ │ │ ├── FenciUtil.java
│ │ │ │ ├── FileUtil.java
│ │ │ │ ├── HandlerUtil.java
│ │ │ │ ├── HolidayUtil.java
│ │ │ │ ├── HtmlUtil.java
│ │ │ │ ├── Http2Util.java
│ │ │ │ ├── HttpSessionNetworknt.java
│ │ │ │ ├── HttpSessionUndertow.java
│ │ │ │ ├── HttpSessionWrapper.java
│ │ │ │ ├── HttpUtil.java
│ │ │ │ ├── IdCardUtil.java
│ │ │ │ ├── IdWorker.java
│ │ │ │ ├── ImageUtil.java
│ │ │ │ ├── JsonUtil.java
│ │ │ │ ├── MailUtil.java
│ │ │ │ ├── MySqlUtil.java
│ │ │ │ ├── NumberUtil.java
│ │ │ │ ├── PathEndpointSource.java
│ │ │ │ ├── PdfUtil.java
│ │ │ │ ├── PdnovelUtil.java
│ │ │ │ ├── PinyinUtil.java
│ │ │ │ ├── PlateUtil.java
│ │ │ │ ├── PostUtil.java
│ │ │ │ ├── QnObject.java
│ │ │ │ ├── RedisCache.java
│ │ │ │ ├── RedisConfig.java
│ │ │ │ ├── RedisPubsub.java
│ │ │ │ ├── RedisUtil.java
│ │ │ │ ├── RelationUtil.java
│ │ │ │ ├── RsaUtil.java
│ │ │ │ ├── SealUtil.java
│ │ │ │ ├── ShiroUtil.java
│ │ │ │ ├── SqlInsert.java
│ │ │ │ ├── StringUtil.java
│ │ │ │ ├── TaskUtil.java
│ │ │ │ ├── ThrowingFunction.java
│ │ │ │ ├── TokenCounter.java
│ │ │ │ ├── TrainUtil.java
│ │ │ │ ├── UploadUtil.java
│ │ │ │ ├── WeixinUtil.java
│ │ │ │ ├── WordUtil.java
│ │ │ │ ├── XmlObject.java
│ │ │ │ ├── ZhDate.java
│ │ │ │ └── ZxingUtil.java
│ │ ├── net
│ │ │ └── sourceforge
│ │ │ │ └── pinyin4j
│ │ │ │ ├── PinyinHelper2.java
│ │ │ │ └── multipinyin
│ │ │ │ └── Trie.java
│ │ └── unitauto
│ │ │ └── MethodUtil.java
│ └── resources
│ │ ├── META-INF
│ │ └── services
│ │ │ └── java.sql.Driver
│ │ ├── beetl
│ │ ├── demo
│ │ │ ├── index.html
│ │ │ └── index
│ │ │ │ ├── mysql.html
│ │ │ │ └── script.html
│ │ └── sql
│ │ │ └── user.md
│ │ ├── btsql-ext.properties
│ │ ├── config
│ │ ├── client.truststore
│ │ ├── config.yml
│ │ ├── consul.yml
│ │ ├── correlation.yml
│ │ ├── datetime.yml
│ │ ├── handler.yml
│ │ ├── jwt.yml
│ │ ├── light4j.yml
│ │ ├── openapi.yaml
│ │ ├── secret.yml
│ │ ├── security.yml
│ │ ├── server.crt
│ │ ├── server.keystore
│ │ ├── server.yml
│ │ ├── service.yml
│ │ ├── startup.yml
│ │ └── values.yml
│ │ ├── houbb
│ │ ├── char.txt
│ │ ├── phrase.txt
│ │ └── ts.txt
│ │ ├── log4jdbc.properties
│ │ ├── logback.xml
│ │ ├── logserver.xml
│ │ ├── public
│ │ ├── chat.html
│ │ └── exam.html
│ │ ├── shiro.ini
│ │ └── singleNodeConfig.json
└── test
│ └── java
│ └── com
│ └── xlongwei
│ └── light4j
│ ├── AesCryptoTest.java
│ ├── BankUtilTest.java
│ ├── ConsulTest.java
│ ├── CrawlTest.java
│ ├── DistrictUtilTest.java
│ ├── EcdictTest.java
│ ├── HolidayUtilTest.java
│ ├── MySqlUtilTest.java
│ ├── PinyinTest.java
│ ├── QnObjectTest.java
│ ├── RedisTest.java
│ └── ZhDateTest.java
├── start.bat
└── start.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | bower_components/
3 | node_modules/
4 | dist/
5 | .history
6 | .idea/
7 | .settings
8 | *.iml
9 | *.log
10 | *.tmp
11 | *.zip
12 | dependency-reduced-pom.xml
13 |
14 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
15 | hs_err_pid*
16 |
17 | .metadata
18 | bin/
19 | tmp/
20 | logs
21 | *.tmp
22 | *.bak
23 | *.swp
24 | *~.nib
25 | local.properties
26 | .settings
27 | .vscode
28 | .loadpath
29 | .recommenders
30 | .classpath
31 | .project
32 | .class
33 |
34 | # External tool builders
35 | .externalToolBuilders/
36 |
37 | # Locally stored "Eclipse launch configurations"
38 | *.launch
39 |
40 | # PyDev specific (Python IDE for Eclipse)
41 | *.pydevproject
42 |
43 | # CDT-specific (C/C++ Development Tooling)
44 | .cproject
45 |
46 | # CDT- autotools
47 | .autotools
48 |
49 | # Java annotation processor (APT)
50 | .factorypath
51 |
52 | # PDT-specific (PHP Development Tools)
53 | .buildpath
54 |
55 | # sbteclipse plugin
56 | .target
57 |
58 | # Tern plugin
59 | .tern-project
60 |
61 | # TeXlipse plugin
62 | .texlipse
63 |
64 | # STS (Spring Tool Suite)
65 | .springBeans
66 |
67 | # Code Recommenders
68 | .recommenders/
69 |
70 | # Annotation Processing
71 | .apt_generated/
72 |
73 | # Scala IDE specific (Scala & Java development for Eclipse)
74 | .cache-main
75 | .scala_dependencies
76 | .worksheet
77 |
--------------------------------------------------------------------------------
/README.en.md:
--------------------------------------------------------------------------------
1 | # light4j
2 |
3 | #### Description
4 | a microservice project using light-4j
5 |
6 | #### Software Architecture
7 | Software architecture description
8 |
9 | #### Installation
10 |
11 | 1. redis-server
12 | 2. sh start.sh install
13 | 3. mvn compile
14 | 4. mvn exec:exec
15 |
16 | profile "debug" is activated by default.
17 |
18 | #### Instructions
19 |
20 | 1. rewrite configs in config/light4j.yml
21 |
22 | -Dupload.save=/soft/uploads -Dlight4j.directory=/soft/softwares/library/
23 |
24 | 2. append logs to logserver or logfile
25 |
26 | -Dlogserver -Dlogfile=path/log
27 |
28 | ### Debug
29 |
30 | 1. com.networknt.server.Server
31 |
32 | you can config vm arguments -Dupload.save=/soft/uploads -Dlight4j.directory=/soft/softwares/library/
33 |
34 | 2. using postman(chrome plugin) to import postman.json
35 |
36 | #### Deploy
37 |
38 | 1. mvn compile jar:jar
39 |
40 | 2. mvn dependency:copy-dependencies -DoutputDirectory=target/deploy
41 |
42 | 3. copy target/light4j-3.0.1.jar target/deploy
43 |
44 | you need only upload "deploy" directory once, after that you just need to update light4j-3.0.1.jar.
45 |
46 | 4. java -Dlight4j.directory=H:/works/itecheast/Servers/library/ -Dupload.save=H:/works/itecheast/Servers/uploads/ -jar target/deploy/light4j-3.0.1.jar
47 |
48 | redis-server is required. "mvn package -P release -Dmaven.javadoc.skip=true" will package one-jar "target/light4j-3.0.1.jar" that can be deployed also.
49 |
50 | #### Features
51 |
52 | 1. lombok
53 |
54 | org.projectlombok:lombok:1.16.18+
55 |
56 | 2. logback if/else
57 |
58 | org.codehaus.janino:janino:2.6.1
59 |
60 | ### Test
61 |
62 | By default, all endpoints are protected by OAuth jwt token verifier. It can be turned off with config change through for development.
63 |
64 |
65 | In order to access the server, there is a long lived token below issued by my
66 | oauth2 server [light-oauth2](https://github.com/networknt/light-oauth2)
67 |
68 | ```
69 | Bearer eyJraWQiOiIxMDAiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJ1cm46Y29tOm5ldHdvcmtudDpvYXV0aDI6djEiLCJhdWQiOiJ1cm46Y29tLm5ldHdvcmtudCIsImV4cCI6MTg4MjUwNjM1NiwianRpIjoiQTlaUHVjM3RsS1BoWmM0RnpzTlJjQSIsImlhdCI6MTU2NzE0NjM1NiwibmJmIjoxNTY3MTQ2MjM2LCJ2ZXJzaW9uIjoiMS4wIiwidXNlcl9pZCI6ImFkbWluIn0.Jb89PTAOY7zDQBUpLS-5L9iDz28__fBUhXgmXqjXByiu6HG1sSemHHs-C0n-ZFUH4Tn3yfVbcHndSjNtVQ__gZMmpKi4PCg7NTiSo7TZZmVYI9uinQEdnDlFT2YA97AL6jBCGJW2Ol6q-odSajpCdoMfOh9KM2yXKQPqr95P5v4Du7L-MNL8dW7evfa0gBpGA2FF4Sr4txerS_SXJg3ED4_px_WbbkqZYpzo6_MupNK9nfJVG7ycP50r21-HMrSnBR7pUN1JvF8mxpfmcQi8j0W4TiYFZV2PKV2AGqsJ9d4IuPu--3YHNpevG3Pv78982o6qK22o_4h4Z8VFzr_NUQ
70 | ```
71 |
72 | Postman is the best tool to test REST APIs
73 |
74 | Add "Authorization" header with value as above token and a dummy message will return from the generated stub.
75 |
76 |
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # light4j
2 |
3 | #### 项目简介
4 | 使用light-4j构建的微服务接口应用
5 |
6 | #### 本地测试
7 | 1. 获取依赖:sh start.sh install,项目构建:sh start.sh package
8 | 2. 启动缓存:redis-server,运行项目:start.bat
9 | 3. 测试访问:[chat](http://localhost:8080/ws/chat.html),[datetime](http://localhost:8080/service/datetime.json)
10 | 4. VSCode+Mysql:"vmArgs": "-Dapijson.enabled=true", "env": {"db.hostPort": "host:port"}
11 |
12 | #### 线上部署
13 | 1. 获取依赖:sh start.sh install,项目打包:sh start.sh deploy
14 | 2. 提取脚本:jar xvf light4j.jar start.sh,修改配置:vi start.sh
15 | 3. 启动缓存:redis-server,运行服务:sh start.sh start
16 |
17 | #### 配置说明
18 | vi start.sh
19 |
20 | 1. -Dredis.configDb、-Dredis.cacheDbs,配置redis地址
21 | 2. -Dlight4j.directory,相关资源可在[library](http://t.xlongwei.com/softwares/library/)获取
22 | 3. -Dlogserver,在/etc/hosts配置logserver地址:127.0.0.1 logserver
23 | 4. -DcontextName=light4j,修改应用的日志上下文
24 | 5. -Djava.compiler=none,禁用JIT可节约内存,默认启用JIT可提高性能
25 | 6. https、registry可自行研究,sh start.sh keystore转换密钥为相关文件
26 |
27 | #### 其他说明
28 |
29 | 1. WeixinHandler支持响应微信公众号消息,关注xlongwei试试[help](https://api.xlongwei.com/service/weixin/chat.json?text=help)
30 | 2. LayuiHandler和openapi支持前后端分离,参考[admin](http://layui.xlongwei.com/admin/)
31 | 3. WebSocketHandlerProvider支持web socket消息,参考[chat](https://api.xlongwei.com:8443/ws/chat.html)
32 |
--------------------------------------------------------------------------------
/apijson/apijson.conf:
--------------------------------------------------------------------------------
1 | server {
2 | # http://apijson.cn/api/ APIAuto不支持/service/apijson,因此用独立子域名apijson提供服务
3 | server_name apijson.xlongwei.com;
4 | location / {
5 | if ( $request_method = OPTIONS ) {
6 | add_header Access-Control-Allow-Origin $http_origin;
7 | add_header Access-Control-Allow-Credentials 'true';
8 | add_header Access-Control-Allow-Methods 'GET, PUT, POST, DELETE, HEAD, OPTIONS';
9 | add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
10 | return 204;
11 | }
12 | proxy_pass http://localhost:8080/service/apijson/;
13 | }
14 | location /method/ {
15 | if ( $request_method = OPTIONS ) {
16 | add_header Access-Control-Allow-Origin $http_origin;
17 | add_header Access-Control-Allow-Credentials 'true';
18 | add_header Access-Control-Allow-Methods 'GET, PUT, POST, DELETE, HEAD, OPTIONS';
19 | add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
20 | return 204;
21 | }
22 | # /method/list => /service/apijson/method_list
23 | proxy_pass http://localhost:8080/service/apijson/method_;
24 | }
25 | location /unit/ {
26 | alias E:/GITHUB/APIJSON/UnitAuto/UnitAuto-Admin/;
27 | autoindex on;
28 | }
29 | }
--------------------------------------------------------------------------------
/apijson/bills.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `bills` (
2 | `_id` char(24) NOT NULL,
3 | `apiCode` smallint(6) DEFAULT NULL,
4 | `apiName` varchar(11) DEFAULT NULL,
5 | `slaveId` char(24) DEFAULT NULL,
6 | `slaveName` varchar(14) DEFAULT NULL,
7 | `payTime` datetime DEFAULT NULL,
8 | `realPayMoney` smallint(6) DEFAULT NULL,
9 | PRIMARY KEY (`_id`)
10 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='bills';
11 | SELECT apiCode
12 | ,apiName
13 | ,COUNT(*) AS num
14 | ,SUM(realPayMoney)/1000.0 AS sum
15 | FROM bills
16 | GROUP BY apiCode ORDER BY num desc;
--------------------------------------------------------------------------------
/apijson/checkcode.rest:
--------------------------------------------------------------------------------
1 | @host=http://localhost:8080
2 | @checkcode={{host}}/service/checkcode
3 | ### type=-2字母数字
4 | {{checkcode}}/code?secure=false
5 | ### type=-1随机取0汉字 1算术 2拆字
6 | {{checkcode}}/code?secure=false&type=-1
7 | ### type=-3三方easy-captcha style支持spec gif chinese arithmetic chinesegif
8 | {{checkcode}}/code?secure=false&type=-3&style=random
9 | ### image 获取验证码图片 type支持-3|-4|空
10 | {{checkcode}}/image?checkcode=1234&type=&ajax=true
11 | ### image 直接拿图片,需提供sid
12 | {{checkcode}}/image?sid=12345678901234&type=
13 | ### type=-4三方hutool style=circle gif shear line
14 | {{checkcode}}/code?secure=false&type=-4&style=random
15 | ### type=-5三方tianai style=ROTATE CONCAT WORD_IMAGE_CLICK
16 | {{checkcode}}/code?secure=false&type=-5&style=RANDOM
17 | ### check行为验证码
18 | {{checkcode}}/check?checkcode=0.3169491&sid=1560884810192494594
--------------------------------------------------------------------------------
/apijson/doc2fill.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xlongwei/light4j/16d0030e8aae1ed9f7b7687c3a05f43cbb88a5a6/apijson/doc2fill.docx
--------------------------------------------------------------------------------
/apijson/pdnovel.rest:
--------------------------------------------------------------------------------
1 |
2 | @host=http://localhost:8080
3 | @service={{host}}/service
4 | ### grant all privileges on bbs.* to apijson;
5 | @pdnovel={{service}}/pdnovel
6 | ### 书
7 | {{pdnovel}}/books
8 | ### 卷
9 | {{pdnovel}}/volumes?novelid=1
10 | ### 章
11 | {{pdnovel}}/chapters?novelid=1&volumeid=1
12 | ### 延迟队列
13 | @delay={{service}}/delay
14 | {{delay}}?delay=3&unit=SECONDS&url=https://api.xlongwei.com/service/datetime
15 | ### X-Traceability-Id: 用于跟踪日志
16 | {{service}}/?handler=datetime&path=isworkday
17 | X-Traceability-Id: {{$guid}}
18 | ### X-Handler-Path指定handler/path,与/service/handler/path的概念一致
19 | {{service}}/
20 | X-Handler-Path: datetime/isworkday
--------------------------------------------------------------------------------
/http_load.sh:
--------------------------------------------------------------------------------
1 | hostPort=localhost:8080
2 | clients=3
3 | seconds=5
4 |
5 | echo "http://$hostPort/ws/ok" > /tmp/urls.txt
6 | http_load -parallel $clients -seconds $seconds /tmp/urls.txt
7 |
--------------------------------------------------------------------------------
/knife4j/group.json:
--------------------------------------------------------------------------------
1 | [ {
2 | "name" : "swagger",
3 | "url" : "/json/swagger.json",
4 | "swaggerVersion" : "2.0"
5 | } ]
6 |
--------------------------------------------------------------------------------
/my.pwd:
--------------------------------------------------------------------------------
1 | #daemon=true
2 | #profile="-P mysql5"
3 | #includeCallerData=false
4 | token=xlongwei
5 | ipsConfig=service.controller.ips.config
--------------------------------------------------------------------------------
/src/main/java/ch/qos/logback/core/util/ExecutorServiceUtil.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Logback: the reliable, generic, fast and flexible logging framework.
3 | * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4 | *
5 | * This program and the accompanying materials are dual-licensed under
6 | * either the terms of the Eclipse Public License v1.0 as published by
7 | * the Eclipse Foundation
8 | *
9 | * or (per the licensee's choosing)
10 | *
11 | * under the terms of the GNU Lesser General Public License version 2.1
12 | * as published by the Free Software Foundation.
13 | */
14 | package ch.qos.logback.core.util;
15 |
16 | import java.util.List;
17 | import java.util.concurrent.Callable;
18 | import java.util.concurrent.ExecutorService;
19 | import java.util.concurrent.Executors;
20 | import java.util.concurrent.Future;
21 | import java.util.concurrent.ScheduledExecutorService;
22 | import java.util.concurrent.ScheduledThreadPoolExecutor;
23 | import java.util.concurrent.ThreadFactory;
24 | import java.util.concurrent.atomic.AtomicInteger;
25 |
26 | /**
27 | * Static utility methods for manipulating an {@link ExecutorService}.
28 | *
29 | * @author Carl Harris
30 | * @author Mikhail Mazursky
31 | */
32 | public class ExecutorServiceUtil {
33 |
34 | private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {
35 |
36 | private final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
37 | private final AtomicInteger threadNumber = new AtomicInteger(1);
38 |
39 | public Thread newThread(Runnable r) {
40 | Thread thread = defaultFactory.newThread(r);
41 | if (!thread.isDaemon()) {
42 | thread.setDaemon(true);
43 | }
44 | thread.setName("logback-" + threadNumber.getAndIncrement());
45 | return thread;
46 | }
47 | };
48 |
49 | public static final LogbackScheduler scheduler = new LogbackScheduler(1, THREAD_FACTORY);
50 |
51 | public static ScheduledExecutorService newScheduledExecutorService() {
52 | return scheduler;
53 | }
54 |
55 | /**
56 | * Creates an executor service suitable for use by logback components.
57 | * @return executor service
58 | */
59 | public static ExecutorService newExecutorService() {
60 | return scheduler.getExecutorService();
61 | }
62 |
63 | /**
64 | * Shuts down an executor service.
65 | *
66 | * @param executorService the executor service to shut down
67 | */
68 | public static void shutdown(ExecutorService executorService) {
69 | executorService.shutdownNow();
70 | }
71 |
72 | /**
73 | * ScheduledThreadPoolExecutor不会按需创建新的线程,logback调用submit、execute时可能会长期占用线程,导致缺少线程执行scheduleWithFixedDelay等定时任务,
74 | * 因此LogbackScheduler创建额外的线程池来执行此类耗时任务
75 | */
76 | public static class LogbackScheduler extends ScheduledThreadPoolExecutor {
77 | ExecutorService es = null;
78 | public LogbackScheduler(int corePoolSize, ThreadFactory threadFactory) {
79 | super(corePoolSize, threadFactory);
80 | es = Executors.newCachedThreadPool(threadFactory);
81 | }
82 | public ExecutorService getExecutorService() {
83 | return es;
84 | }
85 | @Override
86 | public void execute(Runnable command) {
87 | es.execute(command);
88 | }
89 | @Override
90 | public Future> submit(Runnable task) {
91 | return es.submit(task);
92 | }
93 | @Override
94 | public Future submit(Runnable task, T result) {
95 | return es.submit(task, result);
96 | }
97 | @Override
98 | public Future submit(Callable task) {
99 | return es.submit(task);
100 | }
101 | @Override
102 | public void shutdown() {
103 | super.shutdown();
104 | es.shutdown();
105 | }
106 | @Override
107 | public List shutdownNow() {
108 | es.shutdownNow();
109 | return super.shutdownNow();
110 | }
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/com/mysql/jdbc/AbandonedConnectionCleanupThread$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xlongwei/light4j/16d0030e8aae1ed9f7b7687c3a05f43cbb88a5a6/src/main/java/com/mysql/jdbc/AbandonedConnectionCleanupThread$1.class
--------------------------------------------------------------------------------
/src/main/java/com/mysql/jdbc/AbandonedConnectionCleanupThread$ConnectionFinalizerPhantomReference.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xlongwei/light4j/16d0030e8aae1ed9f7b7687c3a05f43cbb88a5a6/src/main/java/com/mysql/jdbc/AbandonedConnectionCleanupThread$ConnectionFinalizerPhantomReference.class
--------------------------------------------------------------------------------
/src/main/java/com/mysql/jdbc/AbandonedConnectionCleanupThread.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xlongwei/light4j/16d0030e8aae1ed9f7b7687c3a05f43cbb88a5a6/src/main/java/com/mysql/jdbc/AbandonedConnectionCleanupThread.class
--------------------------------------------------------------------------------
/src/main/java/com/networknt/config/RefreshScope.java:
--------------------------------------------------------------------------------
1 | package com.networknt.config;
2 |
3 | import java.lang.reflect.Method;
4 | import java.util.Map;
5 |
6 | import net.sf.cglib.proxy.Enhancer;
7 | import net.sf.cglib.proxy.MethodInterceptor;
8 | import net.sf.cglib.proxy.MethodProxy;
9 |
10 | /**
11 | * 相比Config.getJsonObjectConfig、getJsonMapConfig增加一层代理,获取配置时直接从缓存取值,以便刷新配置后可以实时更新相应配置
12 | * @author xlongwei
13 | *
14 | */
15 | @SuppressWarnings("unchecked")
16 | public class RefreshScope {
17 |
18 | public static T getJsonObjectConfig(String configName, Class clazz) {
19 | return (T)create(new JsonObjectConfigCallback(configName, clazz, ""));
20 | }
21 |
22 | public static T getJsonObjectConfig(String configName, Class clazz, String path) {
23 | return (T)create(new JsonObjectConfigCallback(configName, clazz, path));
24 | }
25 |
26 | public static Map getJsonMapConfig(String configName) {
27 | return (Map)create(new JsonMapConfigCallback(configName, Map.class, ""));
28 | }
29 |
30 | public static Map getJsonMapConfig(String configName, String path) {
31 | return (Map)create(new JsonMapConfigCallback(configName, Map.class, path));
32 | }
33 |
34 | static Object create(ConfigCallback cc) {
35 | final Enhancer enhancer = new Enhancer();
36 | enhancer.setSuperclass(cc.clazz);
37 | enhancer.setCallback(cc);
38 | return enhancer.create();
39 | }
40 |
41 | static abstract class ConfigCallback implements MethodInterceptor {
42 | String configName, path;
43 | Class> clazz;
44 | abstract Object getConfig();
45 | ConfigCallback(String configName, Class> clazz, String path){
46 | this.configName = configName;
47 | this.clazz = clazz;
48 | this.path = path;
49 | }
50 | @Override
51 | public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
52 | Object config = getConfig();
53 | return proxy.invoke(config, args);
54 | }
55 | }
56 |
57 | static class JsonObjectConfigCallback extends ConfigCallback {
58 | public JsonObjectConfigCallback(String configName, Class> clazz, String path) {
59 | super(configName, clazz, path);
60 | }
61 | @Override
62 | Object getConfig() {
63 | return Config.getInstance().getJsonObjectConfig(configName, clazz, path);
64 | }
65 | }
66 |
67 | static class JsonMapConfigCallback extends ConfigCallback {
68 | public JsonMapConfigCallback(String configName, Class> clazz, String path) {
69 | super(configName, clazz, path);
70 | }
71 | @Override
72 | Object getConfig() {
73 | return Config.getInstance().getJsonMapConfig(configName, path);
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/Servers.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j;
2 |
3 | import com.networknt.server.Server;
4 | import com.networknt.server.ServerConfig;
5 |
6 | /**
7 | * listen both http and https
8 | * @author xlongwei
9 | *
10 | */
11 | public class Servers {
12 |
13 | public static void main(String[] args) {
14 | ServerConfig serverConfig = Server.getServerConfig();
15 | boolean enableHttps = serverConfig.isEnableHttps();
16 | boolean enableRegistry = serverConfig.isEnableRegistry();
17 | if(enableHttps==false && enableRegistry) {
18 | //http启动时禁用enableRegistry
19 | serverConfig.setEnableRegistry(false);
20 | }
21 | Server.main(args);
22 | if(enableHttps==false) {
23 | serverConfig.setEnableHttps(true);
24 | serverConfig.setEnableRegistry(enableRegistry);
25 | Server.main(args);
26 | }
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/apijson/DemoObjectParser.java:
--------------------------------------------------------------------------------
1 | /*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.*/
14 |
15 | package com.xlongwei.light4j.apijson;
16 |
17 | import java.util.List;
18 |
19 | import javax.servlet.http.HttpSession;
20 |
21 | import com.alibaba.fastjson.JSONObject;
22 |
23 | import apijson.NotNull;
24 | import apijson.RequestMethod;
25 | import apijson.framework.APIJSONObjectParser;
26 | import apijson.orm.AbstractParser;
27 | import apijson.orm.Join;
28 | import apijson.orm.SQLConfig;
29 |
30 |
31 | /**简化Parser,getObject和getArray(getArrayConfig)都能用
32 | * @author Lemon
33 | */
34 | public class DemoObjectParser extends APIJSONObjectParser {
35 |
36 | public DemoObjectParser(HttpSession session, @NotNull JSONObject request, String parentPath, SQLConfig arrayConfig
37 | , boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception {
38 | super(session, request, parentPath, arrayConfig, isSubquery, isTable, isArrayMainTable);
39 | }
40 |
41 | @Override
42 | public DemoObjectParser setMethod(RequestMethod method) {
43 | super.setMethod(method);
44 | return this;
45 | }
46 |
47 | @Override
48 | public DemoObjectParser setParser(AbstractParser> parser) {
49 | super.setParser(parser);
50 | return this;
51 | }
52 |
53 |
54 | @Override
55 | public SQLConfig newSQLConfig(RequestMethod method, String table, String alias, JSONObject request, List joinList, boolean isProcedure) throws Exception {
56 | return DemoSQLConfig.newSQLConfig(method, table, alias, request, joinList, isProcedure);
57 | }
58 |
59 | @Override
60 | public JSONObject parseResponse(SQLConfig config, boolean isProcedure) throws Exception {
61 | try{
62 | return super.parseResponse(config, isProcedure);
63 | }finally {
64 | if(parser.getSQLExecutor() != null) {
65 | parser.getSQLExecutor().close();
66 | }
67 | }
68 | }
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/apijson/DemoParser.java:
--------------------------------------------------------------------------------
1 | /*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.*/
14 |
15 | package com.xlongwei.light4j.apijson;
16 |
17 | import com.alibaba.fastjson.JSONObject;
18 |
19 | import apijson.RequestMethod;
20 | import apijson.framework.APIJSONObjectParser;
21 | import apijson.framework.APIJSONParser;
22 | import apijson.orm.SQLConfig;
23 | import apijson.orm.SQLCreator;
24 | import apijson.orm.SQLExecutor;
25 |
26 |
27 | /**请求解析器
28 | * @author Lemon
29 | */
30 | public class DemoParser extends APIJSONParser {
31 |
32 | public DemoParser() {
33 | super();
34 | }
35 | public DemoParser(RequestMethod method) {
36 | super(method);
37 | }
38 | public DemoParser(RequestMethod method, boolean needVerify) {
39 | super(method, needVerify);
40 | }
41 |
42 | /**
43 | * bug修复:父类parseResponse总是调createSQLExecutor,而getStructure是正确的,问题为修改时借了两个数据库连接,最后只还了一个,原因为sqlExecutor被覆盖,没有调用到close方法
44 | * @return 每个parser只有一个sqlExecutor,并且每次都有close
45 | */
46 | @Override
47 | public SQLExecutor createSQLExecutor() {
48 | if(sqlExecutor == null) {
49 | sqlExecutor = super.createSQLExecutor();
50 | }
51 | return sqlExecutor;
52 | }
53 | @Override
54 | public JSONObject parseCorrectRequest(RequestMethod method, String tag, int version, String name,
55 | JSONObject request, int maxUpdateCount, SQLCreator creator) throws Exception {
56 | try{
57 | return super.parseCorrectRequest(method, tag, version, name, request, maxUpdateCount, creator);
58 | }finally {
59 | if(sqlExecutor != null) {
60 | sqlExecutor.close();
61 | }
62 | }
63 | }
64 |
65 | //可重写来设置最大查询数量
66 | @Override
67 | public int getMaxQueryCount() {
68 | return 1000;
69 | }
70 | @Override
71 | public int getMaxQueryPage() {
72 | return 10000;
73 | }
74 |
75 | @Override
76 | public APIJSONObjectParser createObjectParser(JSONObject request, String parentPath, SQLConfig arrayConfig
77 | , boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception {
78 | return new DemoObjectParser(getSession(), request, parentPath, arrayConfig
79 | , isSubquery, isTable, isArrayMainTable).setMethod(getMethod()).setParser(this);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/apijson/DemoSQLExecutor.java:
--------------------------------------------------------------------------------
1 | /*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.*/
14 |
15 | package com.xlongwei.light4j.apijson;
16 |
17 | import apijson.framework.APIJSONSQLExecutor;
18 |
19 |
20 | /**executor for query(read) or update(write) MySQL database
21 | * @author Lemon
22 | */
23 | public class DemoSQLExecutor extends APIJSONSQLExecutor {
24 | public static final String TAG = "DemoSQLExecutor";
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/apijson/DemoVerifier.java:
--------------------------------------------------------------------------------
1 | /*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.*/
14 |
15 | package com.xlongwei.light4j.apijson;
16 |
17 |
18 | import apijson.framework.APIJSONVerifier;
19 |
20 |
21 | /**权限验证器
22 | * @author Lemon
23 | */
24 | public class DemoVerifier extends APIJSONVerifier {
25 | public static final String TAG = "DemoVerifier";
26 |
27 | // 重写方法来自定义字段名等
28 | // @Override
29 | // public String getVisitorIdKey(SQLConfig config) {
30 | // return super.getVisitorIdKey(config); // return "userid"; // return "uid" 等自定义的字段名
31 | // }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/apijson/model/Privacy.java:
--------------------------------------------------------------------------------
1 | /*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.*/
14 |
15 | package com.xlongwei.light4j.apijson.model;
16 |
17 | import static apijson.RequestRole.ADMIN;
18 | import static apijson.RequestRole.OWNER;
19 | import static apijson.RequestRole.UNKNOWN;
20 |
21 | import com.alibaba.fastjson.annotation.JSONField;
22 |
23 | import apijson.MethodAccess;
24 | import apijson.framework.BaseModel;
25 |
26 | /**
27 | * 漏洞:如果GETS允许CONTACT,则CONTACT能看到自己的余额,tag可以不是Privacy-circle。
28 | * 所以需要在Request表中增加role字段。或者干脆这里GETS只允许OWNER, ADMIN,需要用其它角色查时走独立接口。
29 | */
30 | /**用户隐私信息
31 | * @author Lemon
32 | */
33 | @MethodAccess(
34 | GET = {},
35 | GETS = {OWNER, ADMIN},
36 | POST = {UNKNOWN, ADMIN},
37 | DELETE = {ADMIN}
38 | )
39 | public class Privacy extends BaseModel {
40 | private static final long serialVersionUID = 1L;
41 |
42 | public static final int PASSWORD_TYPE_LOGIN = 0;
43 | public static final int PASSWORD_TYPE_PAY = 1;
44 |
45 | private String phone; //手机
46 | private String password; //登录密码,隐藏字段
47 | private String payPassword; //支付密码,隐藏字段
48 | private Double balance; //余额
49 |
50 | public Privacy() {
51 | super();
52 | }
53 |
54 | public Privacy(long id) {
55 | this();
56 | setId(id);
57 | }
58 |
59 | public Privacy(String phone, String password) {
60 | this();
61 | setPhone(phone);
62 | setPassword(password);
63 | }
64 |
65 |
66 |
67 | public String getPhone() {
68 | return phone;
69 | }
70 | public Privacy setPhone(String phone) {
71 | this.phone = phone;
72 | return this;
73 | }
74 |
75 | /**fastjson-1.2.71会解析为__password,因此使用注解指定名称*/
76 | @JSONField(name="_password")
77 | public String get__password() {
78 | return password;
79 | }
80 | public Privacy setPassword(String password) {
81 | this.password = password;
82 | return this;
83 | }
84 |
85 | /**fastjson-1.2.71会解析为__password,因此使用注解指定名称*/
86 | @JSONField(name="_payPassword")
87 | public String get__payPassword() {
88 | return payPassword;
89 | }
90 | public Privacy setPayPassword(String payPassword) {
91 | this.payPassword = payPassword;
92 | return this;
93 | }
94 |
95 | public Double getBalance() {
96 | return balance;
97 | }
98 | public Privacy setBalance(Double balance) {
99 | this.balance = balance;
100 | return this;
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/apijson/model/User.java:
--------------------------------------------------------------------------------
1 | /*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.*/
14 |
15 | package com.xlongwei.light4j.apijson.model;
16 |
17 | import static apijson.RequestRole.ADMIN;
18 | import static apijson.RequestRole.UNKNOWN;
19 |
20 | import java.util.List;
21 |
22 | import apijson.MethodAccess;
23 | import apijson.framework.BaseModel;
24 | import apijson.orm.Visitor;
25 |
26 | /**用户开放信息
27 | * @author Lemon
28 | */
29 | @MethodAccess(
30 | POST = {UNKNOWN, ADMIN},
31 | DELETE = {ADMIN}
32 | )
33 | public class User extends BaseModel implements Visitor {
34 | private static final long serialVersionUID = 1L;
35 |
36 | public static final int SEX_MAIL = 0;
37 | public static final int SEX_FEMALE = 1;
38 | public static final int SEX_UNKNOWN = 2;
39 |
40 |
41 | private Integer sex; //性别
42 | private String head; //头像url
43 | private String name; //姓名
44 | private String tag; //标签
45 | private List pictureList; //照片列表
46 | private List contactIdList; //朋友列表
47 |
48 | /**默认构造方法,JSON等解析时必须要有
49 | */
50 | public User() {
51 | super();
52 | }
53 | public User(long id) {
54 | this();
55 | setId(id);
56 | }
57 |
58 | public Integer getSex() {
59 | return sex;
60 | }
61 | public User setSex(Integer sex) {
62 | this.sex = sex;
63 | return this;
64 | }
65 | public String getHead() {
66 | return head;
67 | }
68 | public User setHead(String head) {
69 | this.head = head;
70 | return this;
71 | }
72 | public String getName() {
73 | return name;
74 | }
75 | public User setName(String name) {
76 | this.name = name;
77 | return this;
78 | }
79 | public List getPictureList() {
80 | return pictureList;
81 | }
82 | public User setPictureList(List pictureList) {
83 | this.pictureList = pictureList;
84 | return this;
85 | }
86 |
87 | public String getTag() {
88 | return tag;
89 | }
90 | public User setTag(String tag) {
91 | this.tag = tag;
92 | return this;
93 | }
94 | @Override
95 | public List getContactIdList() {
96 | return contactIdList;
97 | }
98 | public User setContactIdList(List contactIdList) {
99 | this.contactIdList = contactIdList;
100 | return this;
101 | }
102 |
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/apijson/model/Verify.java:
--------------------------------------------------------------------------------
1 | /*Copyright ©2016 TommyLemon(https://github.com/TommyLemon/APIJSON)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.*/
14 |
15 | package com.xlongwei.light4j.apijson.model;
16 |
17 | import static apijson.RequestRole.ADMIN;
18 | import static apijson.RequestRole.CIRCLE;
19 | import static apijson.RequestRole.CONTACT;
20 | import static apijson.RequestRole.LOGIN;
21 | import static apijson.RequestRole.OWNER;
22 | import static apijson.RequestRole.UNKNOWN;
23 |
24 | import apijson.MethodAccess;
25 | import apijson.framework.BaseModel;
26 |
27 | /**验证码
28 | * @author Lemon
29 | */
30 | @MethodAccess(
31 | GET = {},
32 | HEAD = {},
33 | GETS = {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN},
34 | HEADS = {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN},
35 | POST = {UNKNOWN, LOGIN, CONTACT, CIRCLE, OWNER, ADMIN},
36 | PUT = {ADMIN},
37 | DELETE = {ADMIN}
38 | )
39 | public class Verify extends BaseModel {
40 | private static final long serialVersionUID = 1L;
41 |
42 | public static final int TYPE_LOGIN = 0; //登录
43 | public static final int TYPE_REGISTER = 1; //注册
44 | public static final int TYPE_PASSWORD = 2; //登录密码
45 | public static final int TYPE_PAY_PASSWORD = 3; //支付密码
46 | public static final int TYPE_RELOAD = 4; //重载配置
47 |
48 | private String phone; //手机
49 | private String verify; //验证码
50 | private Integer type; //验证类型
51 |
52 | public Verify() {
53 | super();
54 | }
55 | /**type和phone为联合主键,必传
56 | * @param type
57 | * @param phone
58 | */
59 | public Verify(int type, String phone) {
60 | this();
61 | setType(type);
62 | setPhone(phone);
63 | }
64 |
65 |
66 | public String getVerify() {
67 | return verify;
68 | }
69 | public Verify setVerify(String verify) {
70 | this.verify = verify;
71 | return this;
72 | }
73 |
74 | public String getPhone() {
75 | return phone;
76 | }
77 | public Verify setPhone(String phone) {
78 | this.phone = phone;
79 | return this;
80 | }
81 |
82 | public Integer getType() {
83 | return type;
84 | }
85 | public Verify setType(Integer type) {
86 | this.type = type;
87 | return this;
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/beetl/dao/UserDao.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.beetl.dao;
2 |
3 | import java.util.List;
4 |
5 | import org.beetl.sql.mapper.BaseMapper;
6 |
7 | import com.xlongwei.light4j.beetl.model.User;
8 |
9 | public interface UserDao extends BaseMapper {
10 | /** sample */
11 | List sample(User user);
12 | }
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/beetl/model/District.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.beetl.model;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class District {
7 | private String province;
8 | private String provinceName;
9 | private String city;
10 | private String cityName;
11 | private String county;
12 | private String countyName;
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/beetl/model/Ecdict.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.beetl.model;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class Ecdict {
7 | private String word;
8 | private String phonetic;
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/beetl/model/User.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.beetl.model;
2 |
3 | import java.util.Date;
4 |
5 | import lombok.Data;
6 |
7 | @Data
8 | public class User {
9 | private Integer id;
10 | private Integer age;
11 | private String name;
12 | private Date createDate;
13 |
14 | }
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/handler/DemoHandler.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.handler;
2 |
3 | import java.util.Deque;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 | import java.util.Set;
7 |
8 | import com.networknt.handler.LightHttpHandler;
9 | import com.networknt.utility.StringUtils;
10 | import com.xlongwei.light4j.handler.ServiceHandler.AbstractHandler;
11 | import com.xlongwei.light4j.util.HandlerUtil;
12 | import com.xlongwei.light4j.util.PathEndpointSource;
13 | import com.xlongwei.light4j.util.StringUtil;
14 |
15 | import cn.hutool.core.util.ClassUtil;
16 | import cn.hutool.core.util.ReflectUtil;
17 | import cn.hutool.extra.template.Template;
18 | import cn.hutool.extra.template.TemplateConfig;
19 | import cn.hutool.extra.template.TemplateConfig.ResourceMode;
20 | import cn.hutool.extra.template.TemplateEngine;
21 | import cn.hutool.extra.template.TemplateUtil;
22 | import io.undertow.server.HttpServerExchange;
23 | import io.undertow.util.Headers;
24 | import lombok.extern.slf4j.Slf4j;
25 |
26 | /**
27 | * demo handler
28 | * @author xlongwei
29 | *
30 | */
31 | @Slf4j
32 | public class DemoHandler implements LightHttpHandler {
33 | public static final TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("beetl/demo", ResourceMode.CLASSPATH));
34 | private Map handlers = new HashMap<>();
35 |
36 | public DemoHandler() {
37 | String pkg = getClass().getPackage().getName()+".demo";
38 | Set> list = ClassUtil.scanPackageBySuper(pkg, AbstractHandler.class);
39 | for(Class> clazz : list) {
40 | AbstractHandler handler = (AbstractHandler)ReflectUtil.newInstanceIfPossible(clazz);
41 | String name = handler.name();
42 | handlers.put(name, handler);
43 | log.info("demo {} => {}", name, handler.getClass().getName());
44 | }
45 | }
46 |
47 | @Override
48 | public void handleRequest(HttpServerExchange exchange) throws Exception {
49 | Map> queryParameters = exchange.getQueryParameters();
50 | String service = queryParameters.remove("*").getFirst();
51 | log.info("{} {}", exchange.getRequestMethod(), exchange.getRequestURI());
52 | int dot = service.indexOf('.');
53 | String[] split = StringUtils.split(dot>0 ? service.substring(0, dot) : service, "/");
54 | String name = split.length>0 ? split[0] : "index", path = split.length>1 ? split[1] : "";
55 | AbstractHandler handler = handlers.get(name);
56 | if(handler != null) {
57 | exchange.putAttachment(AbstractHandler.PATH, path);
58 | HandlerUtil.parseBody(exchange);
59 | handler.handleRequest(exchange);
60 | String accept = exchange.getRequestHeaders().getFirst(Headers.ACCEPT);
61 | if (accept == null || !accept.contains("html")) {
62 | HandlerUtil.sendResp(exchange);
63 | return;
64 | }
65 | }
66 | Template template = engine.getTemplate((StringUtil.isBlank(path) ? name : name+"/"+path)+".html");
67 | String html = template.render((Map, ?>)exchange.getAttachment(HandlerUtil.RESP));
68 | if(StringUtils.isBlank(html)) {
69 | HandlerUtil.sendResp(exchange);
70 | }else {
71 | exchange.removeAttachment(HandlerUtil.RESP);
72 | exchange.setStatusCode(200);
73 | exchange.getResponseHeaders().add(Headers.CONTENT_TYPE, "text/html");
74 | exchange.getResponseSender().send(html);
75 | }
76 | }
77 |
78 | public static class DemoEndpointSource extends PathEndpointSource {
79 | public DemoEndpointSource() {
80 | super("/demo/*");
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/handler/UploadHandler.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.handler;
2 |
3 | import java.io.File;
4 | import java.util.Deque;
5 | import java.util.Map;
6 |
7 | import com.networknt.handler.LightHttpHandler;
8 | import com.xlongwei.light4j.util.HandlerUtil;
9 | import com.xlongwei.light4j.util.NumberUtil;
10 | import com.xlongwei.light4j.util.StringUtil;
11 | import com.xlongwei.light4j.util.UploadUtil;
12 |
13 | import io.undertow.server.HttpServerExchange;
14 | import io.undertow.server.handlers.form.FormData.FormValue;
15 | import lombok.extern.slf4j.Slf4j;
16 |
17 | /**
18 | * 上传服务
19 | * @author xlongwei
20 | *
21 | */
22 | @Slf4j
23 | public class UploadHandler implements LightHttpHandler {
24 |
25 | @Override
26 | public void handleRequest(HttpServerExchange exchange) throws Exception {
27 | Map> queryParameters = exchange.getQueryParameters();
28 | String service = queryParameters.remove("*").getFirst();
29 | log.info("{} {}", exchange.getRequestMethod(), exchange.getRequestURI());
30 | int dot = service.indexOf('.');
31 | String name = dot==-1 ? service : service.substring(0, dot);
32 | HandlerUtil.parseBody(exchange);
33 | if(name.length()==0 || UploadUtil.TEMP.equals(name) || UploadUtil.DIRECT.equals(name)) {
34 | //上传文件
35 | upload(exchange, name);
36 | }else if(UploadUtil.CONFIRM.equals(name) || UploadUtil.TRASH.equals(name)) {
37 | //移动文件
38 | move(exchange, name);
39 | }
40 | HandlerUtil.sendResp(exchange);
41 | }
42 |
43 | private void upload(HttpServerExchange exchange, String name) {
44 | FormValue file = HandlerUtil.getFile(exchange, "file");
45 | if(file!=null && file.isFileItem()) {
46 | String type = StringUtil.firstNotBlank(HandlerUtil.getParam(exchange, "type"), "image");
47 | //temp方式重命名 direct方式默认不重命名,保存目录也不同
48 | boolean temp = UploadUtil.DIRECT.equals(name) ? false : true;
49 | boolean rename = temp ? true : NumberUtil.parseBoolean(HandlerUtil.getParam(exchange, "rename"), Boolean.FALSE);
50 | String fileName = file.getFileName();
51 | String path = rename ? UploadUtil.path(type, fileName) : type+"/"+fileName;
52 | File target = new File(temp ? UploadUtil.SAVE_TEMP : UploadUtil.SAVE, path);
53 | try {
54 | boolean save = UploadUtil.save(file.getFileItem().getInputStream(), target);
55 | log.info("direct upload save={}, file={}, size={}K, path={}", save, fileName, target.length()/1024, path);
56 | if(save) {
57 | String string = UploadUtil.string((temp ? UploadUtil.URL_TEMP : UploadUtil.URL) + "," + path);
58 | exchange.putAttachment(HandlerUtil.RESP, string);
59 | }
60 | }catch(Exception e) {
61 | log.warn("fail to {} upload file, ex:{}", name, e.getMessage());
62 | }
63 | }
64 | }
65 |
66 | private void move(HttpServerExchange exchange, String name) {
67 | String path = HandlerUtil.getParam(exchange, "path");
68 | boolean move = UploadUtil.move(path, name);
69 | exchange.putAttachment(HandlerUtil.RESP, move ? "1" : "0");
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/handler/WeixinHandler.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.handler;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | import com.networknt.handler.LightHttpHandler;
8 | import com.xlongwei.light4j.util.HandlerUtil;
9 | import com.xlongwei.light4j.util.StringUtil;
10 | import com.xlongwei.light4j.util.WeixinUtil;
11 | import com.xlongwei.light4j.util.WeixinUtil.AbstractMessage;
12 | import com.xlongwei.light4j.util.WeixinUtil.AbstractMessageHandler;
13 |
14 | import cn.hutool.core.util.ClassUtil;
15 | import cn.hutool.core.util.ReflectUtil;
16 | import io.undertow.server.HttpServerExchange;
17 | import lombok.extern.slf4j.Slf4j;
18 |
19 | /**
20 | * weixin handler
21 | * @author xlongwei
22 | *
23 | */
24 | @Slf4j
25 | @SuppressWarnings({"rawtypes"})
26 | public class WeixinHandler implements LightHttpHandler {
27 |
28 | public WeixinHandler() {
29 | String pkg = getClass().getPackage().getName()+".weixin";
30 | List> list = new ArrayList<>(ClassUtil.scanPackageBySuper(pkg, AbstractMessageHandler.class));
31 | Collections.sort(list, (a,b)->{ return a.getName().compareTo(b.getName()); });
32 | for(Class> clazz : list) {
33 | AbstractMessageHandler handler = (AbstractMessageHandler)ReflectUtil.newInstanceIfPossible(clazz);
34 | WeixinUtil.register(handler);
35 | }
36 | }
37 |
38 | @Override
39 | public void handleRequest(HttpServerExchange exchange) throws Exception {
40 | HandlerUtil.parseBody(exchange);
41 | String echostr = HandlerUtil.getParam(exchange, "echostr");
42 | String timestamp = HandlerUtil.getParam(exchange, "timestamp");
43 | String nonce = HandlerUtil.getParam(exchange, "nonce");
44 | if(!StringUtil.isBlank(echostr)) {
45 | String signature = HandlerUtil.getParam(exchange, "signature");
46 | String token = HandlerUtil.getParam(exchange, "token");
47 | String response = WeixinUtil.checkSignature(signature, timestamp, nonce, token) ? echostr : "";
48 | exchange.getResponseSender().send(response);
49 | log.info("echostr: {}, timestamp: {}, nonce: {}, signature: {}, token: {}", echostr, timestamp, nonce, signature, token);
50 | }else {
51 | String xml = HandlerUtil.getBodyString(exchange);
52 | boolean aes = "aes".equals(HandlerUtil.getParam(exchange, "encrypt_type"));
53 | log.info("timestamp: {}, nonce: {}, aes: {}", timestamp, nonce, aes);
54 | if(aes) {
55 | String msgSignature = HandlerUtil.getParam(exchange, "msg_signature");
56 | String decrypt = WeixinUtil.decrypt(WeixinUtil.appid, msgSignature, timestamp, nonce, xml);
57 | log.info("msg_signature: {}, decrypt: {}", msgSignature, decrypt);
58 | xml = decrypt;
59 | }
60 | AbstractMessage msg = StringUtil.isBlank(xml) ? null : AbstractMessage.fromXML(xml);
61 | msg = msg == null ? null : WeixinUtil.dispatch(msg);
62 | xml = msg !=null ? msg.toXML() : "";
63 | log.info("response: {}", xml);
64 | if(aes && !StringUtil.isBlank(xml)) {
65 | String encrypt = WeixinUtil.encrypt(WeixinUtil.appid, xml, timestamp, nonce);
66 | log.info("encrypt: {}", encrypt);
67 | xml = encrypt;
68 | }
69 | exchange.getResponseSender().send(xml);
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/handler/demo/IndexHandler.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.handler.demo;
2 |
3 | import java.util.Collections;
4 | import java.util.Map;
5 |
6 | import javax.script.ScriptContext;
7 | import javax.script.SimpleScriptContext;
8 |
9 | import org.beetl.sql.core.SQLReady;
10 | import org.beetl.sql.core.SqlId;
11 |
12 | import com.networknt.config.Config;
13 | import com.networknt.server.Servers;
14 | import com.xlongwei.light4j.beetl.dao.UserDao;
15 | import com.xlongwei.light4j.beetl.model.User;
16 | import com.xlongwei.light4j.handler.ServiceHandler.AbstractHandler;
17 | import com.xlongwei.light4j.handler.service.IpHandler;
18 | import com.xlongwei.light4j.util.HandlerUtil;
19 | import com.xlongwei.light4j.util.JsonUtil;
20 | import com.xlongwei.light4j.util.MySqlUtil;
21 | import com.xlongwei.light4j.util.RedisConfig;
22 | import com.xlongwei.light4j.util.StringUtil;
23 | import com.xlongwei.light4j.util.TaskUtil;
24 |
25 | import cn.hutool.script.ScriptUtil;
26 | import io.undertow.server.HttpServerExchange;
27 | import lombok.extern.slf4j.Slf4j;
28 |
29 | /**
30 | * beetl index demo
31 | * @author xlongwei
32 | *
33 | */
34 | @Slf4j
35 | public class IndexHandler extends AbstractHandler {
36 |
37 | public void index(HttpServerExchange exchange) throws Exception {
38 | String ip = HandlerUtil.getIp(exchange);
39 | String region = IpHandler.searchToMap(ip).get("region");
40 | HandlerUtil.setResp(exchange, StringUtil.params("ip", ip, "region", region));
41 | }
42 |
43 | public void mysql(HttpServerExchange exchange) throws Exception {
44 | String type = StringUtil.firstNotBlank(HandlerUtil.getParam(exchange, "type"), "tables");
45 | Object obj = null;
46 | switch(type) {
47 | case "all": obj = MySqlUtil.SQLMANAGER.all(User.class); break;
48 | case "sql": obj = MySqlUtil.SQLMANAGER.select(SqlId.of("user.sample"), User.class); break;
49 | case "dao": obj = MySqlUtil.SQLMANAGER.getMapper(UserDao.class).all(); break;
50 | default: obj = MySqlUtil.SQLMANAGER.getMetaDataManager().allTable(); break;
51 | }
52 | HandlerUtil.setResp(exchange, Collections.singletonMap("allTable", obj));
53 | }
54 |
55 | public void refresh(HttpServerExchange exchange) throws Exception {
56 | Map startup = Config.getInstance().getJsonMapConfig(Servers.STARTUP_CONFIG_NAME);
57 | Servers.loadConfigs();
58 | HandlerUtil.setResp(exchange, startup);
59 | }
60 |
61 | public void script(HttpServerExchange exchange) throws Exception {
62 | String script = HandlerUtil.getParam(exchange, "script");
63 | if(!StringUtil.isBlank(script)) {
64 | ScriptContext context = new SimpleScriptContext();
65 | context.setAttribute("log", log, ScriptContext.ENGINE_SCOPE);
66 | context.setAttribute("util", new Util(), ScriptContext.ENGINE_SCOPE);
67 | TaskUtil.submit(()->{
68 | ScriptUtil.eval(script, context);
69 | });
70 | }
71 | HandlerUtil.setResp(exchange, exchange.getAttachment(HandlerUtil.BODY));
72 | }
73 |
74 | public static class Util {
75 | public Map hgetall(String key) {
76 | return StringUtil.isBlank(key) ? Collections.emptyMap() : RedisConfig.hgetAll(RedisConfig.CACHE, key);
77 | }
78 | public String get(String json, String path) {
79 | return StringUtil.isBlank(json) || StringUtil.isBlank(path) ? "" : JsonUtil.get(json, path);
80 | }
81 | /** 仅支持insert ignore | into,replace ,不能有分号 */
82 | public void insert(String sql, Object ... args) {
83 | if(!StringUtil.isBlank(sql) && !sql.contains(";") && (sql.startsWith("insert ") || sql.startsWith("replace ")) ) {
84 | MySqlUtil.SQLMANAGER.executeUpdate(new SQLReady(sql, args));
85 | }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/com/xlongwei/light4j/handler/demo/LogHandler.java:
--------------------------------------------------------------------------------
1 | package com.xlongwei.light4j.handler.demo;
2 |
3 | import java.util.Arrays;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 | import java.util.Objects;
8 | import java.util.stream.Collectors;
9 |
10 | import org.slf4j.LoggerFactory;
11 |
12 | import com.networknt.utility.StringUtils;
13 | import com.xlongwei.light4j.handler.ServiceHandler.AbstractHandler;
14 | import com.xlongwei.light4j.util.HandlerUtil;
15 |
16 | import ch.qos.logback.classic.Level;
17 | import ch.qos.logback.classic.LoggerContext;
18 | import cn.hutool.core.map.MapUtil;
19 | import io.undertow.server.HttpServerExchange;
20 | import lombok.extern.slf4j.Slf4j;
21 |
22 | /**
23 | * log handler
24 | * @author xlongwei
25 | */
26 | @Slf4j
27 | public class LogHandler extends AbstractHandler {
28 | public static final String token = System.getProperty("token");
29 |
30 | public void log(HttpServerExchange exchange) throws Exception {
31 | LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
32 | String loggerName = HandlerUtil.getParam(exchange, "logger");
33 | List loggers = null;
34 | if (StringUtils.isNotBlank(loggerName)) {
35 | ch.qos.logback.classic.Logger logger = lc.getLogger(loggerName);
36 | if (logger != null) {
37 | loggers = Arrays.asList(logger);
38 | String levelName = HandlerUtil.getParam(exchange, "level");
39 | if (StringUtils.isNotBlank(levelName)
40 | && (StringUtils.isBlank(token) || token.equals(HandlerUtil.getParam(exchange, "token")))) {
41 | Level level = Level.toLevel(levelName, null);
42 | log.warn("change logger:{} level from:{} to:{}", logger.getName(), logger.getLevel(), level);
43 | logger.setLevel(level);
44 | }
45 | }
46 | }
47 | if (loggers == null) {
48 | loggers = lc.getLoggerList();
49 | }
50 | log.info("check logger level, loggers:{}", loggers.size());
51 | List