添加代码示例springboot-async

This commit is contained in:
yidao620 2018-02-28 11:17:40 +08:00
parent 33f127db44
commit 5fddfb2bed
14 changed files with 474 additions and 1 deletions

View File

@ -54,7 +54,7 @@ app-manage-api | [同时实现了需要认证授权访问的RESTful
## 运行
每个子项目都可以单独运行都是打包成jar包后通过使用内置jetty容器执行有3种方式运行。
每个子项目都可以单独运行都是打包成jar包后通过使用内置jetty容器执行有3种方式运行。:point_right:
1. 在IDEA里面直接运行Application.java的main函数。
2. 另一种方式是执行`mvn clean package`命令后传到linux服务器上面通过命令`java -jar xxx.jar`方式运行

14
springboot-async/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# 此为注释– 将被Git 忽略
# /结尾表示是目录,忽略目录和目录下的所有件
# /开头表示根目录,否则是.gitignore的相对目录
# !开头表示反选
.idea/
target/
*.iml
*.ipr
*.iws
*.log
.svn/
.project
rebel.xml
.rebel-remote.xml.*

20
springboot-async/LICENSE Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2018 Xiong Neng
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,13 @@
## 异步线程池
演示在SpringBoot中如何使用异步线程池
## 测试用例
`com.xncoding.pos.ApplicationTests.java`
## 许可证
Copyright (c) 2018 Xiong Neng
基于 MIT 协议发布: <http://www.opensource.org/licenses/MIT>

87
springboot-async/pom.xml Normal file
View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xncoding</groupId>
<artifactId>springboot-async</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-async</name>
<description>异步线程池</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<!--<proc>none</proc>-->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>

72
springboot-async/run.sh Normal file
View File

@ -0,0 +1,72 @@
#!/bin/bash
# 项目自动更新脚本
# 先clone相应的分支下来
# git clone ssh://git@120.24.173.142:7999/xxx.git
# 远程调试启动:
# nohup java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &
function start {
profile="$1"
echo "启动环境profile=${profile}"
jarfile=$(ls target/*.jar)
if [[ "$?" == "0" ]]; then
stop $profile $jarfile
fi
branch=$(git branch |awk '{print $2}')
git pull origin ${branch}
echo "更新完代码开始重新打包"
mvn clean && mvn clean && mvn package -DskipTests=true
if [[ "$?" != "0" ]]; then
echo "编译出错,退出!"
exit 1
fi
echo "nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &"
nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &
echo "启动应用中,请查看日志文件..."
}
function stop {
profile="$1"
jarfile="$2"
ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep > /dev/null
if [[ "$?" == "0" ]]; then
echo "该应用还在跑,我先停了它"
pid=$(ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep |awk '{print $2}')
if [[ "$pid" != "" ]]; then
kill -9 $pid
fi
echo "停止应用成功..."
fi
}
if [[ "$1" == "start" ]]; then
if [[ "$#" < 2 ]]; then
echo "请输入正确参数:./epay.sh start {profile}"
exit 1
fi
profile="$2"
if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then
echo "参数错误请输入正确的profile参数使用方法"
echo "./epay.sh start {profile} ==> 启动应用,{profile}取值dev|test|show|production"
exit 1
fi
start "${profile}"
elif [[ "$1" == "stop" ]]; then
if [[ "$#" < 2 ]]; then
echo "请输入正确参数:./epay.sh stop {profile}"
exit 1
fi
profile="$2"
if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then
echo "参数错误请输入正确的profile参数使用方法"
echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值dev|test|show|production"
exit 1
fi
jarfile=$(ls target/*.jar)
stop $profile $jarfile
else
echo "参数错误,使用方法:{}参数是必填的,[]参数可选"
echo "./epay.sh start {profile} ==> 启动应用,{profile}取值dev|test|show|production"
echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值dev|test|show|production"
exit 1
fi

View File

@ -0,0 +1,12 @@
package com.xncoding.pos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,37 @@
package com.xncoding.pos.async;
/**
* 异步方法异常
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/25
*/
public class AsyncException extends RuntimeException {
public AsyncException() {
super();
}
public AsyncException(String msg) {
super(msg);
}
public AsyncException(int code, String msg) {
super(msg);
this.code = code;
}
/**
* 错误代码
*/
private int code;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

View File

@ -0,0 +1,30 @@
package com.xncoding.pos.async;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* AsyncExceptionHandler
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/25
*/
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(AsyncExceptionHandler.class);
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
log.error("Async method has uncaught exception, params:{}" + Arrays.toString(params));
if (ex instanceof AsyncException) {
AsyncException asyncException = (AsyncException) ex;
log.error("asyncException:" + asyncException.getMessage());
}
log.error("Exception :", ex);
}
}

View File

@ -0,0 +1,46 @@
package com.xncoding.pos.async;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
/**
* AsyncDemo
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/25
*/
@Component
public class AsyncTask {
private static final Logger logger = LoggerFactory.getLogger(AsyncTask.class);
@Async
public void dealNoReturnTask() {
logger.info("返回值为void的异步调用开始" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info("返回值为void的异步调用结束" + Thread.currentThread().getName());
}
@Async
public Future<String> dealHaveReturnTask(int i) {
logger.info("asyncInvokeReturnFuture, parementer=" + i);
Future<String> future;
try {
Thread.sleep(1000 * i);
future = new AsyncResult<String>("success:" + i);
} catch (InterruptedException e) {
future = new AsyncResult<String>("error");
}
return future;
}
}

View File

@ -0,0 +1,41 @@
package com.xncoding.pos.config;
import com.xncoding.pos.async.AsyncExceptionHandler;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* AsyncConfig
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/25
*/
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(100);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60 * 10);
executor.setThreadNamePrefix("AsyncThread-");
executor.initialize(); //如果不初始化导致找到不到执行器
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}

View File

@ -0,0 +1,39 @@
##########################################################
################## 所有profile共有的配置 #################
##########################################################
################### spring配置 ###################
spring:
profiles:
active: dev
---
#####################################################################
######################## 开发环境profile ##########################
#####################################################################
spring:
profiles: dev
logging:
level:
ROOT: INFO
com:
xncoding: DEBUG
file: E:/logs/app.log
---
#####################################################################
######################## 测试环境profile ##########################
#####################################################################
spring:
profiles: test
logging:
level:
ROOT: INFO
com:
xncoding: DEBUG
file: /var/logs/app.log

View File

@ -0,0 +1,23 @@
_____ _______ _____ _____
/\ \ /::\ \ /\ \ /\ \
/::\____\ /::::\ \ /::\____\ /::\ \
/:::/ / /::::::\ \ /:::/ / /::::\ \
/:::/ / /::::::::\ \ /:::/ / /::::::\ \
/:::/ / /:::/~~\:::\ \ /:::/ / /:::/\:::\ \
/:::/ / /:::/ \:::\ \ /:::/____/ /:::/__\:::\ \
/:::/ / /:::/ / \:::\ \ |::| | /::::\ \:::\ \
/:::/ / /:::/____/ \:::\____\ |::| | _____ /::::::\ \:::\ \
/:::/ / |:::| | |:::| | |::| | /\ \ /:::/\:::\ \:::\ \
/:::/____/ |:::|____| |:::| | |::| | /::\____\/:::/__\:::\ \:::\____\
\:::\ \ \:::\ \ /:::/ / |::| | /:::/ /\:::\ \:::\ \::/ /
\:::\ \ \:::\ \ /:::/ / |::| | /:::/ / \:::\ \:::\ \/____/
\:::\ \ \:::\ /:::/ / |::|____|/:::/ / \:::\ \:::\ \
\:::\ \ \:::\__/:::/ / |:::::::::::/ / \:::\ \:::\____\
\:::\ \ \::::::::/ / \::::::::::/____/ \:::\ \::/ /
\:::\ \ \::::::/ / ~~~~~~~~~~ \:::\ \/____/
\:::\ \ \::::/ / \:::\ \
\:::\____\ \::/____/ \:::\____\
\::/ / ~~ \::/ /
\/____/ \/____/

View File

@ -0,0 +1,39 @@
package com.xncoding.pos;
import com.xncoding.pos.async.AsyncTask;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
/**
* 测试异步任务
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
private static final Logger log = LoggerFactory.getLogger(ApplicationTests.class);
@Autowired
private AsyncTask asyncTask;
@Test
public void testAsync() throws InterruptedException, ExecutionException {
asyncTask.dealNoReturnTask();
Future<String> f = asyncTask.dealHaveReturnTask(5);
log.info("主线程执行finished");
log.info(f.get());
assertThat(f.get(), is("success:" + 5));
}
}