springboot注解Aspect实现方案

网友投稿 234 2022-09-04


springboot注解Aspect实现方案

目录目标实现POM一些实体类CheckedParamProcessDbModel测试用的入参对象一些工具类Base64UtilSpringBootBeanUtilProcessBeanUtilCheckedTransmitableUtilPrivateTransmitableUtil一些BeanPostProcessTestCheckPostProcessAspect注解切面类 CheckedAop线程池配置持久化service审批用的service测试用的service审批用的controller测试用的controller开启异步功能测试

目标

本文提供一种自定义注解,来实现业务审批操作的DEMO,不包含审批流程的配置功能。具体方案是自定义一个Aspect注解,拦截sevice方法,将拦截的信息持久化,待审批;审批时获取持久化数据,执行目标方法。

实现

POM

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.5.8

com.proc

process-test

1.0.0-SNAPSHOT

process-test

Demo project for Spring Boot

1.8

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-starter-aop

org.springframework.boot

spring-boot-configuration-processor

true

com.alibaba

transmittable-thread-local

2.12.2

org.springframework.boot

spring-boot-maven-plugin

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.5.8

com.proc

process-test

1.0.0-SNAPSHOT

process-test

Demo project for Spring Boot

1.8

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-starter-aop

org.springframework.boot

spring-boot-configuration-processor

true

com.alibaba

transmittable-thread-local

2.12.2

org.springframework.boot

spring-boot-maven-plugin

一些实体类

CheckedParam

用于包装页面传进来的参数

package com.proc.model;

import java.util.List;

public class CheckedParam {

//业务标记,由页面传入,用于审批时页面根据tagPagejs解析data,渲染到页面,审批管理员可看到审批的内容

private String tagPageJs;

//页面传入的原始数据

private List data;

public String getTagPageJs() {

return tagPageJs;

}

public void setTagPageJs(String tagPageJs) {

this.tagPageJs = tagPageJs;

}

public List getData() {

return data;

}

public void setData(List data) {

this.data = data;

}

}

ProcessDbModel

拦截的信息包装类,用于持久化数据

package com.proc.model;

public class ProcessDbModel {

//bean的目标类全限定名

private String targetClassName;

//拦截到的service方法名

private String methodName;

//页面传入的tagPageJs或Checked注解的tag

private String tag;

private String description;

//拦截到的service入参类型,包含泛型信息

private String paramTypes;

//拦截到的service入参值

private String paramArgs;

//拦截到的service入参值或页面传入的原始数据

private String data;

public String getTargetClassName() {

return targetClassName;

}

public void setTargetClassName(String targetClassName) {

this.targetClassName = targetClassName;

}

public String getMethodName() {

return methodName;

}

public void setMethodName(String methodName) {

this.methodName = methodName;

}

public String getTag() {

return tag;

}

public String getDescription() {

return description;

}

public void setDescription(String description) {

this.description = description;

}

public void setTag(String tag) {

this.tag = tag;

}

public String getParamTypes() {

return paramTypes;

}

public void setParamTypes(String paramTypes) {

this.paramTypes = paramTypes;

}

public String getParamArgs() {

return paramArgs;

}

public void setParamArgs(String paramArgs) {

this.paramArgs = paramArgs;

}

public String getData() {

return data;

}

public void setData(String data) {

this.data = data;

}

@Override

public String toString() {

return "ProcessDbModel [targetClassName=" + targetClassName + ", methodName=" + methodName + ", tag=" + tag

+ ", description=" + description + ", paramTypes=" + paramTypes + ", paramArgs=" + paramArgs + ", data="

+ data + "]";

}

}

测试用的入参对象

package com.proc.model;

import java.math.BigDecimal;

public class Score {

private BigDecimal langue;

private BigDecimal math;

private BigDecimal english;

public BigDecimal getLangue() {

return langue;

}

public void setLangue(BigDecimal langue) {

this.langue = langue;

}

public BigDecimal getMath() {

return math;

}

public void setMath(BigDecimal math) {

this.math = math;

}

public BigDecimal getEnglish() {

return english;

}

public void setEnglish(BigDecimal english) {

this.english = english;

}

@Override

public String toString() {

return "Score [langue=" + langue + ", math=" + math + ", english=" + english + "]";

}

}

package com.proc.model;

import java.util.List;

public class Person {

private String name;

private String age;

private String sex;

private String testName;

private String salary;

private String work;

private List grades;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAge() {

return age;

}

public void setAge(String age) {

this.age = age;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public String getSalary() {

return salary;

}

public void setSalary(String salary) {

this.salary = salary;

}

public String getTestName() {

return testName;

}

public void setTestName(String testName) {

this.testName = testName;

}

public String getWork() {

return work;

}

public void setWork(String work) {

this.work = work;

}

public List getGrades() {

return grades;

}

public void setGrades(List grades) {

this.grades = grades;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + ", sex=" + sex + ", testName=" + testName + ", salary="

+ salary + ", work=" + work + ", grades=" + grades + "]";

}

}

一些工具类

JacksonCanonicalUtil

package com.proc.util;

import com.fasterxml.jackson.core.type.TypeReference;

import com.fasterxml.jackson.databind.JavaType;

import com.fasterxml.jackson.databind.json.JsonMapper;

public class JacksonCanonicalUtil {

private static final JsonMapper MAPPER = new JsonMapper();

private JacksonCanonicalUtil () {}

public static String toCanonical (Class clazz) {

return MAPPER.getTypeFactory().constructType(clazz).toCanonical();

}

public static String toCanonical (TypeReference tr) {

return MAPPER.getTypeFactory().constructType(tr).toCanonical();

}

//反序列化时从持久数据中获取JavaType

public static JavaType constructFromCanonical (String canonical) {

return MAPPER.getTypeFactory().constructFromCanonical(canonical);

}

}

StringZipUtil

用于压缩和解压字符串,减少持久数据占用空间

package com.proc.util;

import java.io.ByteArrayOutputStream;

import java.io.OutputStream;

import java.nio.charset.StandardCharsets;

import java.util.Base64;

import java.util.zip.DeflaterOutputStream;

import java.util.zip.InflaterOutputStream;

public class StringZipUtil {

private StringZipUtil () {}

public static String zipBase64(String text) {

try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {

try (OutputStream os = new DeflaterOutputStream(out)) {

os.write(text.getBytes(StandardCharsets.UTF_8));

}

return Base64.getEncoder().encodeToString(out.toByteArray());

} catch (Exception e) {

throw new RuntimeException("压缩字符串出错", e);

}

}

public static String unzipBase64(String text) {

try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {

try (OutputStream os = new InflaterOutputStream(out)) {

os.write(Base64.getDecoder().decode(text));

}

return new String(out.toByteArray(), StandardCharsets.UTF_8);

} catch (Exception e) {

throw new RuntimeException("解压字符串出错", e);

}

}

}

Base64Util

一些参数值转为Base64后持久化

package com.proc.util;

import java.nio.charset.StandardCharsets;

import java.util.ArrayList;

import java.util.Base64;

import java.util.List;

import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.json.JsonMapper;

public class Base64Util {

private Base64Util () {}

private static final JsonMapper MAPPER = new JsonMapper();

public static String[] toStrings (Object[] objs) {

List list = new ArrayList<>();

try {

for (Object obj : objs) {

list.add(MAPPER.writeValueAsString(obj));

}

} catch (Exception e) {

throw new RuntimeException("序列化对象出错", e);

}

return list.toArray(new String[0]);

}

public static String encode (String[] strs) {

List list = new ArrayList<>();

for (String str : strs) {

list.add(Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8)));

}

String join = list.stream().collect(Collectors.joining("|"));

return join;

}

public static String[] decode (String text) {

String[] strs = text.split("\\|", -1);

List list = new ArrayList<>();

for (String base64 : strs) {

list.add(new String(Base64.getDecoder().decode(base64), StandardCharsets.UTF_8));

}

return list.toArray(new String[0]);

}

public static String encodeZip (Object[] objs) {

return encodeZip(toStrings(objs));

}

public static String encodeZip (String[] strs) {

List list = new ArrayList<>();

for (String str : strs) {

list.add(StringZipUtil.zipBase64(str));

}

String join = list.stream().collect(Collectors.joining("|"));

return StringZipUtil.zipBase64(join);

}

public static String[] decodeZip (String text) {

String str = StringZipUtil.unzipBase64(text);

String[] strs = str.split("\\|", -1);

List list = new ArrayList<>();

for (String base64 : strs) {

list.add(StringZipUtil.unzipBase64(base64));

}

return list.toArray(new String[0]);

}

}

SpringBootBeanUtil

package com.proc.util;

import java.util.Map;

import org.springframework.beans.BeansException;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.stereotype.Component;

@Component

public class SpringBootBeanUtil implements ApplicationContextAware {

private static ApplicationContext applicationContext;

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

SpringBootBeanUtil.applicationContext = applicationContext;

}

public static ApplicationContext getApplicationContext() {

return applicationContext;

}

public static Object getBean(String name) {

return applicationContext.getBean(name);

}

public static T getBean(Class clazz) {

return (T) applicationContext.getBean(clazz);

}

public static T getBean(String name, Class clazz) {

return applicationContext.getBean(name, clazz);

}

public static Map getBeansOfType(Class clazz) {

return applicationContext.getBeansOfType(clazz);

}

}

ProcessBeanUtil

用于执行目标方法

package com.proc.util;

import java.lang.reflect.Method;

import org.springframework.util.ReflectionUtils;

public class ProcessBeanUtil {

private ProcessBeanUtil () {}

public static Object excuteBeanMethod (String targetClassName, String methodName, Class>[] parameterTypes, Object[] args) {

Class> targetClass;

try {

targetClass = Class.forName(targetClassName);

} catch (ClassNotFoundException e) {

throw new RuntimeException("未找到类", e);

}

return excuteBeanMethod(targetClass, methodName, parameterTypes, args);

}

public static Object excuteBeanMethod (Class> targetClass, String methodName, Class>[] parameterTypes, Object[] args) {

Object bean = SpringBootBeanUtil.getBean(targetClass);

Method method = ReflectionUtils.findMethod(targetClass, methodName, parameterTypes);

return ReflectionUtils.invokeMethod(method, bean, args);

}

}

CheckedTransmitableUtil

用于传递业务参数

package com.proc.util;

import com.alibaba.ttl.TransmittableThreadLocal;

import com.proc.model.CheckedParam;

public class CheckedTransmitableUtil {

private static final TransmittableThreadLocal threadLocal = new TransmittableThreadLocal<>();

private CheckedTransmitableUtil () {}

public static void set (CheckedParam checkedParam) {

threadLocal.set(checkedParam);

}

public static CheckedParam getAndRemove () {

CheckedParam checkedParam = threadLocal.get();

threadLocal.remove();

return checkedParam;

}

}

PrivateTransmitableUtil

为Aspect判断是否拦截提供依据

package com.proc.util;

import com.alibaba.ttl.TransmittableThreadLocal;

public class PrivateTransmitableUtil {

private static final String CHECKED = "__CHECKED__";

private static final TransmittableThreadLocal threadLocal = new TransmittableThreadLocal<>();

private PrivateTransmitableUtil () {}

public static void set () {

threadLocal.set(CHECKED);

}

//是否执行的审批程序

public static boolean isCheck () {

String checked = threadLocal.get();

threadLocal.remove();

return CHECKED.equals(checked);

}

}

一些Bean

PostProcess

用于拦截方法后做的个性处理

package com.proc.bean;

public interface PostProcess {

//返回说明内容,审批时在页面显示

String description(String tag, Class>[] parameterTypes, Object[] args);

//返回代替的返回值

T retObject(String tag, Class>[] parameterTypes, Object[] args);

}

TestCheckPostProcess

测试用

package com.proc.bean;

import org.springframework.stereotype.Component;

@Component

public class TestCheckPostProcess implements PostProcess {

@Override

public String description(String tag, Class>[] parameterTypes, Object[] args) {

return tag + "测试testCheck";

}

@Override

public String retObject(String tag, Class>[] parameterTypes, Object[] args) {

return tag + "返回拦截响应";

}

}

Aspect注解

package com.proc.config;

import static java.lang.annotation.ElementType.METHOD;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;

import java.lang.annotation.Target;

import com.proc.bean.PostProcess;

@Retention(RUNTIME)

@Target(METHOD)

public @interface Checked {

String tag() default "";

/**

* @see com.proc.util.JacksonCanonicalUtil

* @return

*/

String[] paramCanonical();

Class extends PostProcess>> postProcess();

}

切面类 CheckedAop

package com.proc.config;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Pointcut;

import org.aspectj.lang.reflect.MethodSignature;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import com.proc.bean.PostProcess;

import com.proc.model.CheckedParam;

import com.proc.model.ProcessDbModel;

import com.proc.service.ProcessDbService;

import com.proc.util.Base64Util;

import com.proc.util.CheckedTransmitableUtil;

import com.proc.util.PrivateTransmitableUtil;

import com.proc.util.SpringBootBeanUtil;

@Component

@Aspect

public class CheckedAop {

@Autowired

private ProcessDbService processDbService;

//拦截Checked注释的方法

@Pointcut("@annotation(com.proc.config.Checked)")

public void check() {

}

@Around(value = "com.proc.config.CheckedAop.check() && @annotation(checked)")

public Object around(ProceedingJoinPoint joinPoint, Checked checked) throws Throwable {

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

Class>[] parameterTypes = signature.getParameterTypes();

String methodName = signature.getMethod().getName();

Object[] args = joinPoint.getArgs();

if (PrivateTransmitableUtil.isCheck()) {

//审批后,执行业务代码

Object returnVal = joinPoint.proceed();

return returnVal;

} else {

//不是审批操作,拦截

Class extends PostProcess>> postProcess = checked.postProcess();

PostProcess> bean = SpringBootBeanUtil.getBean(postProcess);

//组装持久化数据

ProcessDbModel dbModel = new ProcessDbModel();

dbModel.setTargetClassName(joinPoint.getTarget().getClass().getName());

dbModel.setMethodName(methodName);

String tag = checked.tag();

CheckedParam checkedParam = CheckedTransmitableUtil.getAndRemove();

if (checkedParam == null || checkedParam.getTagPageJs() == null || checkedParam.getTagPageJs().isEmpty()) {

//不是页面调用的业务,使用注解的tag,data保存为service的参数,这时需要页面专门解析渲染

String[] argStrs = Base64Util.toStrings(args);

dbModel.setParamArgs(Base64Util.encodeZip(argStrs));

dbModel.setData(Base64Util.encode(argStrs));

} else {

tag = checkedParam.getTagPageJs();

dbModel.setParamArgs(Base64Util.encodeZip(args));

dbModel.setData(Base64Util.encode(checkedParam.getData().toArray(new String[0])));

}

dbModel.setTag(tag);

dbModel.setParamTypes(Base64Util.encodeZip(checked.paramCanonical()));

dbModel.setDescription(bean.description(tag, parameterTypes, args));

//持久化数据

processDbService.save(dbModel);

return bean.retObject(tag, parameterTypes, args);

}

}

}

线程池配置

测试用

package com.proc.config;

import java.util.concurrent.Executor;

import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.alibaba.ttl.threadpool.TtlExecutors;

@Configuration

public class TaskExecutePoolConfig {

@Bean

public Executor processExecutor() {

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

//核心线程池大小

executor.setCorePoolSize(10);

//最大线程数

executor.setMaxPoolSize(10);

//队列容量

executor.setQueueCapacity(500);

//活跃时间

executor.setKeepAliveSeconds(60);

//线程名字前缀

executor.setThreadNamePrefix("ProcessExecutor-");

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());

// 等待所有任务结束后再关闭线程池

executor.setWaitForTasksToCompleteOnShutdown(true);

executor.initialize();

//用transmittable-thread-local包装,才可以正确给线程池中的线程传递数据

return TtlExecutors.getTtlExecutor(executor);

}

}

持久化service

为测试方便,未真正实现持久化

package com.proc.service;

import com.proc.model.ProcessDbModel;

public interface ProcessDbService {

void save (ProcessDbModel model);

ProcessDbModel get ();

}

package com.proc.service.impl;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import com.proc.model.ProcessDbModel;

import com.proc.service.ProcessDbService;

@Component

public class ProcessDbServiceImpl implements ProcessDbService {

private static final Logger log = LoggerFactory.getLogger(ProcessDbService.class);

private volatile ProcessDbModel model;

@Override

public void save(ProcessDbModel model) {

this.model = model;

log.info(model.toString());

}

@Override

public ProcessDbModel get() {

return this.model;

}

}

审批用的service

package com.proc.service;

import com.proc.model.ProcessDbModel;

public interface ProcessCheckService {

void process (ProcessDbModel model);

}

package com.proc.service.impl;

import java.util.ArrayList;

import java.util.List;

import java.util.Objects;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.JavaType;

import com.fasterxml.jackson.databind.json.JsonMapper;

import com.proc.model.ProcessDbModel;

import com.proc.service.ProcessCheckService;

import com.proc.util.Base64Util;

import com.proc.util.JacksonCanonicalUtil;

import com.proc.util.PrivateTransmitableUtil;

import com.proc.util.ProcessBeanUtil;

@Service

public class ProcessCheckServiceImpl implements ProcessCheckService {

private static final Logger log = LoggerFactory.getLogger(ProcessCheckServiceImpl.class);

private static final JsonMapper MAPPER = new JsonMapper();

@Override

public void process(ProcessDbModel model) {

PrivateTransmitableUtil.set();

String[] paramArgs = Base64Util.decodeZip(model.getParamArgs());

String[] paramTypes = Base64Util.decodeZip(model.getParamTypes());

List> parameterTypes = new ArrayList<>();

List args = new ArrayList<>();

try {

for (int i = 0; i < paramTypes.length; i++) {

JavaType javaType = JacksonCanonicalUtil.constructFromCanonical(paramTypes[i]);

parameterTypes.add(javaType.getRawClass());

args.add(MAPPER.readValue(paramArgs[i], javaType));

}

} catch (JsonProcessingException e) {

throw new RuntimeException("反序列化对象出错", e);

}

Object ret = ProcessBeanUtil.excuteBeanMethod(

model.getTargetClassName(),

model.getMethodName(),

parameterTypes.toArray(new Class>[0]),

args.toArray(new Object[0])

);

log.info(Objects.toString(ret));

}

}

测试用的service

package com.proc.service;

import com.proc.model.Person;

import com.proc.model.Score;

public interface TestService {

String testCheck(Person person, String team);

String testCheck2(Person person, String team);

String testCheckAsync(Person personeFHevn, String team);

}

package com.proc.service.impl;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.scheduling.annotation.Async;

import org.springframework.stereotype.Service;

import com.proc.bean.TestCheckPostProcess;

import com.proc.config.Checked;

import com.proc.model.Person;

import com.proc.model.Score;

import com.proc.service.TestService;

@Service

public class TestServiceImpl implements TestService {

private static final Logger log = LoggerFactory.getLogger(TestServiceImpl.class);

//paramCanonical对应testCheck的参数类型

@Checked(

paramCanonical = {"com.proc.model.Person", "java.lang.String"},

postProcess = TestCheckPostProcess.class)

@Override

public String testCheck(Person person, String team) {

log.info(team + ">>>>" + person);

return "target方法";

}

@Checked(

tag = "A1",

paramCanonical = {"com.proc.model.Person", "java.lang.String"},

postProcess = TestCheckPostProcess.class)

@Override

public String testCheck2(Person person, String team) {

log.info(team + ">>2>>" + person);

return "target2方法";

}

@Async("processExecutor")

@Checked(

paramCanonical = {"com.proc.model.Person", "java.lang.String"},

postProcess = TestCheckPostProcess.class)

@Override

public String testCheckAsync(Person person, String team) {

log.info(team + ">>>>" + person);

return "target方法";

}

}

审批用的controller

package com.proc.ctrl;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

import com.proc.model.ProcessDbModel;

import com.proc.service.ProcessCheckService;

import com.proc.service.ProcessDbService;

@RestController

public class ProcessCheckController {

private static final Logger log = LoggerFactory.getLogger(ProcessCheckController.class);

@Autowired

private ProcessDbService processDbService;

@Autowired

private ProcessCheckService processCheckService;

@GetMapping(value = "process")

public String process() {

ProcessDbModel processDbModel = processDbService.get();

log.info(processDbModel.toString());

processCheckService.process(processDbModel);

return "审批成功";

}

}

测试用的controller

package com.proc.ctrl;

import java.math.BigDecimal;

import java.util.ArrayList;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

import com.proc.model.CheckedParam;

import com.proc.model.Person;

import com.proc.model.Score;

import com.proc.service.TestService;

import com.proc.util.CheckedTransmitableUtil;

@RestController

public class TestController {

@Autowired

private TestService testService;

//模拟页面调用

@GetMapping(value = "index")

public String testCheck() {

CheckedParam checkedParam = new CheckedParam();

checkedParam.setTagPageJs("01");

List data = new ArrayList<>();

data.add("前端传进来的数据1");

data.add("前端传进来的数据2");

checkedParam.setData(data);

CheckedTransmitableUtil.set(checkedParam);

Person person = new Person<>();

person.setName("一个人");

person.setAge("18");

person.setSex("1");

person.setSalary("20000.00");

person.setTestName("测试人");

person.setWork("工作");

Score score1 = new Score();

score1.setEnglish(new BigDecimal("12.4"));

score1.setLangue(new BigDecimal("764"));

score1.setMath(new BigDecimal("87.4"));

Score score2 = new Score();

score2.setEnglish(new BigDecimal("12.4"));

score2.setLangue(new BigDecimal("764"));

score2.setMath(new BigDecimal("87.4"));

List list = new ArrayList<>();

list.add(score1);

list.add(score2);

person.setGrades(list);

testService.testCheck(person, "team>>>>>>>>");

return "12345";

}

//模拟其他渠道调用

@GetMapping(value = "index2")

public String testCheck2() {

Person person = new Person<>();

person.setName("一个人");

person.setAge("18");

person.setSex("1");

person.setSalary("20000.00");

person.setTestName("测试人");

person.setWork("工作");

Score score1 = new Score();

score1.setEnglish(new BigDecimal("12.4"));

score1.setLangue(new BigDecimal("764"));

score1.setMath(new BigDecimal("87.4"));

Score score2 = new Score();

score2.setEnglish(new BigDecimal("12.4"));

score2.setLangue(new BigDecimal("764"));

score2.setMath(new BigDecimal("87.4"));

List list = new ArrayList<>();

list.add(score1);

list.add(score2);

person.setGrades(list);

testService.testCheck2(person, "team>>>2>>>>>");

return "12345";

}

//模拟调用异步方法

@GetMapping(value = "index3")

public String testCheckAsync() {

CheckedParam checkedParam = new CheckedParam();

checkedParam.setTagPageJs("01");

List data = new ArrayList<>();

data.add("前端传进来的数据1");

data.add("前端传进来的数据2");

checkedParam.setData(data);

CheckedTransmitableUtil.set(checkedParam);

Person person = new Person<>();

person.setName("一个人");

person.setAge("18");

person.setSex("1");

person.setSalary("20000.00");

person.setTestName("测试人");

person.setWork("工作");

Score score1 = new Score();

score1.setEnglish(new BigDecimal("12.4"));

score1.setLangue(new BigDecimal("764"));

score1.setMath(new BigDecimal("87.4"));

Score score2 = new Score();

score2.setEnglish(new BigDecimal("12.4"));

score2.setLangue(new BigDecimal("764"));

score2.setMath(new BigDecimal("87.4"));

List list = new ArrayList<>();

list.add(score1);

list.add(score2);

person.setGrades(list);

testService.testCheckAsync(person, "team>>>3>>>>>");

return "12345";

}

}

开启异步功能

package com.proc;

import org.springframework.boot.SpringApplication;

import org.springframeFHevnework.boot.autoconfigure.SpringBootApplication;

import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication

@EnableAsync

public class ProcessTestApplication {

public static void main(String[] args) {

SpringApplication.run(ProcessTestApplication.class, args);

}

}

测试

http://localhost:8080/indexhttp://localhost:8080/index2http://localhost:8080/index3浏览器访问上面其中一个路径一次,再访问http://localhost:8080/process一次即可


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:centos 安装uwsgi报错:pip3 install uwsgi(centos7)
下一篇:Python学习笔记(一):CentOS 7.9安装配置pyenv、pip、ipython和jupyter(python之)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~