init
This commit is contained in:
		
							
								
								
									
										35
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | src/main/resources/application.yml | ||||||
|  |  | ||||||
|  | HELP.md | ||||||
|  | target/ | ||||||
|  | !.mvn/wrapper/maven-wrapper.jar | ||||||
|  | !**/src/main/**/target/ | ||||||
|  | !**/src/test/**/target/ | ||||||
|  |  | ||||||
|  | ### STS ### | ||||||
|  | .apt_generated | ||||||
|  | .classpath | ||||||
|  | .factorypath | ||||||
|  | .project | ||||||
|  | .settings | ||||||
|  | .springBeans | ||||||
|  | .sts4-cache | ||||||
|  |  | ||||||
|  | ### IntelliJ IDEA ### | ||||||
|  | .idea | ||||||
|  | *.iws | ||||||
|  | *.iml | ||||||
|  | *.ipr | ||||||
|  |  | ||||||
|  | ### NetBeans ### | ||||||
|  | /nbproject/private/ | ||||||
|  | /nbbuild/ | ||||||
|  | /dist/ | ||||||
|  | /nbdist/ | ||||||
|  | /.nb-gradle/ | ||||||
|  | build/ | ||||||
|  | !**/src/main/**/build/ | ||||||
|  | !**/src/test/**/build/ | ||||||
|  |  | ||||||
|  | ### VS Code ### | ||||||
|  | .vscode/ | ||||||
							
								
								
									
										135
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | |||||||
|  | <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
|  |     <modelVersion>4.0.0</modelVersion> | ||||||
|  |     <parent> | ||||||
|  |         <groupId>org.springframework.boot</groupId> | ||||||
|  |         <artifactId>spring-boot-starter-parent</artifactId> | ||||||
|  |         <version>2.5.2</version> | ||||||
|  |         <relativePath/> <!-- lookup parent from repository --> | ||||||
|  |     </parent> | ||||||
|  |     <groupId>com.weilab</groupId> | ||||||
|  |     <artifactId>biology</artifactId> | ||||||
|  |     <version>0.0.1-SNAPSHOT</version> | ||||||
|  |     <name>biology</name> | ||||||
|  |     <description>Demo project for Spring Boot</description> | ||||||
|  |  | ||||||
|  |     <properties> | ||||||
|  |         <java.version>1.8</java.version> | ||||||
|  |         <maven.compiler.source>1.8</maven.compiler.source> | ||||||
|  |         <maven.compiler.target>1.8</maven.compiler.target> | ||||||
|  |         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||||
|  |         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||||||
|  |     </properties> | ||||||
|  |  | ||||||
|  |     <dependencies> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-web</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-devtools</artifactId> | ||||||
|  |             <scope>runtime</scope> | ||||||
|  |             <optional>true</optional> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>mysql</groupId> | ||||||
|  |             <artifactId>mysql-connector-java</artifactId> | ||||||
|  |             <scope>runtime</scope> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.projectlombok</groupId> | ||||||
|  |             <artifactId>lombok</artifactId> | ||||||
|  |             <optional>true</optional> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-test</artifactId> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-mail</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>com.alibaba</groupId> | ||||||
|  |             <artifactId>fastjson</artifactId> | ||||||
|  |             <version>1.2.76</version> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>com.baomidou</groupId> | ||||||
|  |             <artifactId>mybatis-plus-boot-starter</artifactId> | ||||||
|  |             <version>3.4.1</version> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.python</groupId> | ||||||
|  |             <artifactId>jython-standalone</artifactId> | ||||||
|  |             <version>2.7.2</version> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>javax.validation</groupId> | ||||||
|  |             <artifactId>validation-api</artifactId> | ||||||
|  |             <version>2.0.1.Final</version> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>cn.hutool</groupId> | ||||||
|  |             <artifactId>hutool-all</artifactId> | ||||||
|  |             <version>5.7.19</version> | ||||||
|  |         </dependency> | ||||||
|  |     </dependencies> | ||||||
|  |  | ||||||
|  |     <build> | ||||||
|  |         <finalName>biology</finalName> | ||||||
|  |         <plugins> | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>org.springframework.boot</groupId> | ||||||
|  |                 <artifactId>spring-boot-maven-plugin</artifactId> | ||||||
|  |                 <configuration> | ||||||
|  |                     <excludes> | ||||||
|  |                         <exclude> | ||||||
|  |                             <groupId>org.projectlombok</groupId> | ||||||
|  |                             <artifactId>lombok</artifactId> | ||||||
|  |                         </exclude> | ||||||
|  |                     </excludes> | ||||||
|  |                 </configuration> | ||||||
|  |             </plugin> | ||||||
|  |         </plugins> | ||||||
|  |     </build> | ||||||
|  |  | ||||||
|  |     <repositories> | ||||||
|  |         <repository> | ||||||
|  |             <id>public</id> | ||||||
|  |             <name>aliyun nexus</name> | ||||||
|  |             <url>https://maven.aliyun.com/nexus/content/groups/public/</url> | ||||||
|  |             <releases> | ||||||
|  |                 <enabled>true</enabled> | ||||||
|  |             </releases> | ||||||
|  |         </repository> | ||||||
|  |     </repositories> | ||||||
|  |  | ||||||
|  |     <pluginRepositories> | ||||||
|  |         <pluginRepository> | ||||||
|  |             <id>public</id> | ||||||
|  |             <name>aliyun nexus</name> | ||||||
|  |             <url>https://maven.aliyun.com/nexus/content/groups/public/</url> | ||||||
|  |             <releases> | ||||||
|  |                 <enabled>true</enabled> | ||||||
|  |             </releases> | ||||||
|  |             <snapshots> | ||||||
|  |                 <enabled>false</enabled> | ||||||
|  |             </snapshots> | ||||||
|  |         </pluginRepository> | ||||||
|  |     </pluginRepositories> | ||||||
|  |  | ||||||
|  | </project> | ||||||
							
								
								
									
										13
									
								
								src/main/java/com/weilab/biology/BiologyApplication.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/main/java/com/weilab/biology/BiologyApplication.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | package com.weilab.biology; | ||||||
|  |  | ||||||
|  | import org.springframework.boot.SpringApplication; | ||||||
|  | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||||
|  |  | ||||||
|  | @SpringBootApplication | ||||||
|  | public class BiologyApplication { | ||||||
|  |  | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         SpringApplication.run(BiologyApplication.class, args); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								src/main/java/com/weilab/biology/config/FilterConfig.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/main/java/com/weilab/biology/config/FilterConfig.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | package com.weilab.biology.config; | ||||||
|  |  | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.web.filter.DelegatingFilterProxy; | ||||||
|  |  | ||||||
|  | import javax.servlet.DispatcherType; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2020-12-27 10:54 | ||||||
|  |  * Description : | ||||||
|  |  */ | ||||||
|  | @Configuration | ||||||
|  | public class FilterConfig { | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private TokenFilter tokenFilter; | ||||||
|  |  | ||||||
|  |     @SuppressWarnings({"rawtypes", "unchecked"}) | ||||||
|  |     @Bean | ||||||
|  |     public FilterRegistrationBean tokenFilterRegistration() { | ||||||
|  |         FilterRegistrationBean registration = new FilterRegistrationBean(); | ||||||
|  |         registration.setFilter(tokenFilter); | ||||||
|  |         registration.addUrlPatterns("/*"); | ||||||
|  |         registration.setName("tokenFilter"); | ||||||
|  |         registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); | ||||||
|  |         return registration; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								src/main/java/com/weilab/biology/config/TokenFilter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/main/java/com/weilab/biology/config/TokenFilter.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | package com.weilab.biology.config; | ||||||
|  |  | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
|  | import javax.servlet.*; | ||||||
|  | import javax.servlet.http.HttpServletRequest; | ||||||
|  | import javax.servlet.http.HttpServletResponse; | ||||||
|  | import java.io.IOException; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @Component | ||||||
|  | public class TokenFilter implements Filter { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { | ||||||
|  |         HttpServletRequest request = (HttpServletRequest) servletRequest; | ||||||
|  |         HttpServletResponse response = (HttpServletResponse) servletResponse; | ||||||
|  |         response.setCharacterEncoding("UTF-8"); | ||||||
|  |         response.setHeader("Access-Control-Allow-Origin", "*"); | ||||||
|  |         response.setHeader("Access-Control-Allow-Credentials", "true"); | ||||||
|  |         response.setHeader("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS"); | ||||||
|  |         response.setHeader("Access-Control-Allow-Headers", "*"); | ||||||
|  |         response.setHeader("Access-Control-Expose-Headers", "*"); | ||||||
|  |         response.setHeader("Access-Control-Max-Age", "36000"); | ||||||
|  |  | ||||||
|  |         if ("OPTIONS".equals(request.getMethod())) { | ||||||
|  |             response.setStatus(200); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         filterChain.doFilter(servletRequest, servletResponse); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										124
									
								
								src/main/java/com/weilab/biology/controller/JobController.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								src/main/java/com/weilab/biology/controller/JobController.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | |||||||
|  | package com.weilab.biology.controller; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.io.FileUtil; | ||||||
|  | import cn.hutool.core.util.IdUtil; | ||||||
|  | import com.alibaba.fastjson.JSON; | ||||||
|  | import com.alibaba.fastjson.JSONObject; | ||||||
|  | import com.baomidou.mybatisplus.core.toolkit.StringUtils; | ||||||
|  | import com.weilab.biology.core.data.enums.JobStatusEnum; | ||||||
|  | import com.weilab.biology.core.data.vo.result.CommonError; | ||||||
|  | import com.weilab.biology.core.data.vo.result.Result; | ||||||
|  | import com.weilab.biology.core.data.vo.result.error.JobError; | ||||||
|  | import com.weilab.biology.core.validation.EnumValidation; | ||||||
|  | import com.weilab.biology.service.JobService; | ||||||
|  | import com.weilab.biology.util.FileUtils; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.beans.factory.annotation.Value; | ||||||
|  | import org.springframework.web.bind.annotation.*; | ||||||
|  | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
|  | import java.io.BufferedInputStream; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @RestController | ||||||
|  | @RequestMapping("job") | ||||||
|  | public class JobController { | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private JobService jobService; | ||||||
|  |  | ||||||
|  |     @Value("${biology.request-path}") | ||||||
|  |     private String requestPath; | ||||||
|  |  | ||||||
|  |     @PostMapping("/submit") | ||||||
|  |     public Result submit(@RequestParam(required = false) String dataStr, | ||||||
|  |                          @RequestParam(required = false) MultipartFile dataFile, | ||||||
|  |                          @RequestParam String param, | ||||||
|  |                          @RequestParam String mail, | ||||||
|  |                          @RequestParam(defaultValue = "0") Integer type, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file1, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file2, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file3, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file4, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file5, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file6, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file7, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file8, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file9, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file10, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file11, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file12, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file13, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file14, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file15, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file16, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file17, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file18, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file19, | ||||||
|  |                          @RequestParam(required = false) MultipartFile file20) { | ||||||
|  |         if (dataFile == null && StringUtils.isBlank(dataStr)) | ||||||
|  |             return Result.getResult(JobError.PARAM_CAN_NOT_BE_EMPTY); | ||||||
|  |  | ||||||
|  |         JSONObject obj = null; | ||||||
|  |         try { | ||||||
|  |             obj = JSON.parseObject(param); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             return Result.getResult(CommonError.PARAM_WRONG); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         BufferedInputStream dataStream = null; | ||||||
|  |         if (dataFile != null) { | ||||||
|  |             dataStream = FileUtil.getInputStream(FileUtils.multipartToFile(dataFile)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             List<MultipartFile> files = Arrays.asList(file1, file2, file3, file4, file5, | ||||||
|  |                     file6, file7, file8, file9, file10, file11, file12, file13, file14, file15, | ||||||
|  |                     file16, file17, file18, file19, file20); | ||||||
|  |             for (MultipartFile file : files) { | ||||||
|  |                 if (file != null) { | ||||||
|  |                     String filePath = requestPath + FileUtil.FILE_SEPARATOR + "file" + FileUtil.FILE_SEPARATOR + IdUtil.fastUUID() + "." + FileUtil.extName(file.getOriginalFilename()); | ||||||
|  |                     FileUtil.writeFromStream(file.getInputStream(), filePath); | ||||||
|  |                     obj.put(file.getName(), filePath); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } catch (IOException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             return Result.getResult(JobError.FILE_READ_FAIL); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return jobService.submit(dataStr, dataStream, obj, mail, type); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @PostMapping("/status/update") | ||||||
|  |     public Result updateJobStatus(@RequestParam Integer jobId, | ||||||
|  |                                   @EnumValidation(clazz = JobStatusEnum.class, message = "没有此状态") | ||||||
|  |                                   @RequestParam Integer status, | ||||||
|  |                                   @RequestParam(required = false) String result) { | ||||||
|  |         if (status.equals(JobStatusEnum.WAIT.getKey())) | ||||||
|  |             return Result.getResult(CommonError.PARAM_WRONG); | ||||||
|  |         if (status.equals(JobStatusEnum.SUCCESS.getKey())) { | ||||||
|  |             if (StringUtils.isBlank(result)) | ||||||
|  |                 return Result.getResult(CommonError.PARAM_WRONG); | ||||||
|  |             try { | ||||||
|  |                 JSON.parseObject(result); | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 return Result.getResult(CommonError.PARAM_WRONG); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return jobService.updateJobStatus(jobId, JobStatusEnum.getEnumByKey(status), result); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @GetMapping("/info/{jobId}") | ||||||
|  |     public Result getJobInfo(@PathVariable Integer jobId) { | ||||||
|  |         return jobService.getJobInfo(jobId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @GetMapping("/list") | ||||||
|  |     public Result getJobList(@RequestParam(required = false) Integer type) { | ||||||
|  |         return jobService.getJobList(type); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										78
									
								
								src/main/java/com/weilab/biology/core/data/dto/JobDto.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/main/java/com/weilab/biology/core/data/dto/JobDto.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | package com.weilab.biology.core.data.dto; | ||||||
|  |  | ||||||
|  | import com.alibaba.fastjson.JSON; | ||||||
|  | import com.alibaba.fastjson.JSONObject; | ||||||
|  | import com.baomidou.mybatisplus.annotation.IdType; | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableField; | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableId; | ||||||
|  | import com.fasterxml.jackson.annotation.JsonFormat; | ||||||
|  | import com.weilab.biology.core.data.enums.JobStatusEnum; | ||||||
|  | import com.weilab.biology.core.data.po.Job; | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @AllArgsConstructor | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class JobDto { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * jobId | ||||||
|  |      */ | ||||||
|  |     private Integer jobId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 任务状态 | ||||||
|  |      */ | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求参数 | ||||||
|  |      */ | ||||||
|  |     private JSONObject param; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 运行结果 | ||||||
|  |      */ | ||||||
|  |     private JSONObject result; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求时间 | ||||||
|  |      */ | ||||||
|  |     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | ||||||
|  |     private LocalDateTime requestTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建时间 | ||||||
|  |      */ | ||||||
|  |     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | ||||||
|  |     private LocalDateTime createTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 完成时间 | ||||||
|  |      */ | ||||||
|  |     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | ||||||
|  |     private LocalDateTime completeTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求类型 | ||||||
|  |      */ | ||||||
|  |     private Integer type; | ||||||
|  |  | ||||||
|  |     public static JobDto parseJob(Job job) { | ||||||
|  |         return new JobDto( | ||||||
|  |                 job.getJobId(), | ||||||
|  |                 JobStatusEnum.getRemark(job.getStatus()), | ||||||
|  |                 JSON.parseObject(job.getParam()), | ||||||
|  |                 job.getResult() == null ? null : JSON.parseObject(job.getResult()), | ||||||
|  |                 job.getRequestTime(), | ||||||
|  |                 job.getCreateTime(), | ||||||
|  |                 job.getCompleteTime(), | ||||||
|  |                 job.getType() | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,64 @@ | |||||||
|  | package com.weilab.biology.core.data.dto; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonFormat; | ||||||
|  | import com.weilab.biology.core.data.enums.JobStatusEnum; | ||||||
|  | import com.weilab.biology.core.data.po.Job; | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-09-22 | ||||||
|  |  * Description : | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @AllArgsConstructor | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class JobLessDto { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * jobId | ||||||
|  |      */ | ||||||
|  |     private Integer jobId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 任务状态 | ||||||
|  |      */ | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求时间 | ||||||
|  |      */ | ||||||
|  |     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | ||||||
|  |     private LocalDateTime requestTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建时间 | ||||||
|  |      */ | ||||||
|  |     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | ||||||
|  |     private LocalDateTime createTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 完成时间 | ||||||
|  |      */ | ||||||
|  |     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") | ||||||
|  |     private LocalDateTime completeTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求类型 | ||||||
|  |      */ | ||||||
|  |     private Integer type; | ||||||
|  |  | ||||||
|  |     public static JobLessDto parseJob(Job job) { | ||||||
|  |         return new JobLessDto( | ||||||
|  |                 job.getJobId(), | ||||||
|  |                 JobStatusEnum.getRemark(job.getStatus()), | ||||||
|  |                 job.getRequestTime(), | ||||||
|  |                 job.getCreateTime(), | ||||||
|  |                 job.getCompleteTime(), | ||||||
|  |                 job.getType() | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,42 @@ | |||||||
|  | package com.weilab.biology.core.data.enums; | ||||||
|  |  | ||||||
|  | import lombok.Getter; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 校区的枚举类 | ||||||
|  |  */ | ||||||
|  | @Getter | ||||||
|  | public enum JobStatusEnum { | ||||||
|  |     WAIT(0, "waiting"), | ||||||
|  |     REQED(3, "requested"), | ||||||
|  |     RUNNING(1, "running"), | ||||||
|  |     SUCCESS(2, "success"), | ||||||
|  |     FAIL(-1, "failed"), | ||||||
|  |     TIMEOUT(-2, "timeout"), | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  |     private final Integer key; | ||||||
|  |     private final String remark; | ||||||
|  |  | ||||||
|  |     private JobStatusEnum(Integer key, String remark) { | ||||||
|  |         this.key = key; | ||||||
|  |         this.remark = remark; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static String getRemark(Integer key) { | ||||||
|  |         for (JobStatusEnum enums : JobStatusEnum.values()) { | ||||||
|  |             if (enums.key.equals(key)) | ||||||
|  |                 return enums.getRemark(); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static JobStatusEnum getEnumByKey(Integer key) { | ||||||
|  |         for (JobStatusEnum enums : JobStatusEnum.values()) { | ||||||
|  |             if (enums.key.equals(key)) | ||||||
|  |                 return enums; | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										97
									
								
								src/main/java/com/weilab/biology/core/data/po/Job.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/main/java/com/weilab/biology/core/data/po/Job.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | package com.weilab.biology.core.data.po; | ||||||
|  |  | ||||||
|  | import com.baomidou.mybatisplus.annotation.IdType; | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableField; | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableId; | ||||||
|  | import com.baomidou.mybatisplus.annotation.TableName; | ||||||
|  |  | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.time.LocalDate; | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.util.Date; | ||||||
|  |  | ||||||
|  | import jnr.ffi.annotations.In; | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-09-19 | ||||||
|  |  * Description : | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @AllArgsConstructor | ||||||
|  | @NoArgsConstructor | ||||||
|  | @TableName(value = "job") | ||||||
|  | public class Job implements Serializable { | ||||||
|  |     /** | ||||||
|  |      * jobId | ||||||
|  |      */ | ||||||
|  |     @TableId(value = "job_id", type = IdType.AUTO) | ||||||
|  |     private Integer jobId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 基因序列数据 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "`data`") | ||||||
|  |     private String data; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求参数 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "param") | ||||||
|  |     private String param; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 联系邮箱 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "mail") | ||||||
|  |     private String mail; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 运行结果 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "result") | ||||||
|  |     private String result; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 任务状态。0为待运行,1为正在运行,2为运行成功,-1为运行失败 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "`status`") | ||||||
|  |     private Integer status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求时间 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "request_time") | ||||||
|  |     private LocalDateTime requestTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建时间 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "create_time") | ||||||
|  |     private LocalDateTime createTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 完成时间 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "complete_time") | ||||||
|  |     private LocalDateTime completeTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求类型 | ||||||
|  |      */ | ||||||
|  |     @TableField(value = "type") | ||||||
|  |     private Integer type; | ||||||
|  |  | ||||||
|  |     public Job(String data, String param, String mail, Integer status, LocalDateTime requestTime, Integer type) { | ||||||
|  |         this.data = data; | ||||||
|  |         this.param = param; | ||||||
|  |         this.mail = mail; | ||||||
|  |         this.status = status; | ||||||
|  |         this.requestTime = requestTime; | ||||||
|  |         this.type = type; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  | } | ||||||
| @@ -0,0 +1,43 @@ | |||||||
|  | package com.weilab.biology.core.data.vo.result; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-01-30 | ||||||
|  |  * Description : 通用异常返回 | ||||||
|  |  */ | ||||||
|  | public enum CommonError implements ResultError { | ||||||
|  |     PARAM_WRONG(40000, "参数范围或格式错误"), | ||||||
|  |     NETWORK_WRONG(40001, "网络错误"), | ||||||
|  |     REQUEST_NOT_ALLOW(40002, "当前条件或时间不允许〒▽〒"), | ||||||
|  |     REQUEST_FREQUENTLY(40003, "请求繁忙,请稍后再试"), | ||||||
|  |     CONTENT_NOT_FOUND(40004, "你要找的东西好像走丢啦X﹏X"), | ||||||
|  |     METHOD_NOT_ALLOW(40005, "方法不允许"), | ||||||
|  |     THIS_IS_LAST_PAGE(40006, "这是最后一页,再怎么找也没有啦"), | ||||||
|  |     THIS_IS_FIRST_PAGE(40007, "没有上一页啦"), | ||||||
|  |     PIC_FORMAT_ERROR(40008, "图片格式只能为jpg, jpeg, png, gif, bmp, webp"), | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  |     private int code; | ||||||
|  |  | ||||||
|  |     private String message; | ||||||
|  |  | ||||||
|  |     private CommonError(int code, String message) { | ||||||
|  |         this.code = code; | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public int getCode() { | ||||||
|  |         return code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setCode(int code) { | ||||||
|  |         this.code = code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String getMessage() { | ||||||
|  |         return message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setMessage(String message) { | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,96 @@ | |||||||
|  | package com.weilab.biology.core.data.vo.result; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * web层统一返回类型 | ||||||
|  |  */ | ||||||
|  | public class Result { | ||||||
|  |     private int code = 0; | ||||||
|  |  | ||||||
|  |     private String message; | ||||||
|  |  | ||||||
|  |     private Object data; | ||||||
|  |  | ||||||
|  |     public Result() { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Result(int code, String message, Object data) { | ||||||
|  |         this.code = code; | ||||||
|  |         this.message = message; | ||||||
|  |         this.data = data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Result(ResultError resultError) { | ||||||
|  |         this.code = resultError.getCode(); | ||||||
|  |         this.message = resultError.getMessage(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result getResult(int code, String message) { | ||||||
|  |         return getResult(code, message, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result getResult(int code, String message, Object data) { | ||||||
|  |         return new Result(code, message, data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result success() { | ||||||
|  |         return success(null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result success(Object data) { | ||||||
|  |         return success("success", data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result success(String message, Object data) { | ||||||
|  |         return new Result(0, message, data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result fail() { | ||||||
|  |         return fail(null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result fail(Object data) { | ||||||
|  |         return fail("请求失败", data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result fail(String message, Object data) { | ||||||
|  |         return new Result(-1, message, data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Result getResult(ResultError resultError) { | ||||||
|  |         return getResult(resultError.getCode(), resultError.getMessage()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     public int getCode() { | ||||||
|  |         return code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setCode(int code) { | ||||||
|  |         this.code = code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String getMessage() { | ||||||
|  |         return message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setMessage(String message) { | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Object getData() { | ||||||
|  |         return data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setData(Object data) { | ||||||
|  |         this.data = data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return "Info{" + | ||||||
|  |                 "code=" + code + | ||||||
|  |                 ", message='" + message + '\'' + | ||||||
|  |                 ", data=" + data + | ||||||
|  |                 '}'; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | package com.weilab.biology.core.data.vo.result; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-01-30 | ||||||
|  |  * Description : 通用异常返回的父接口 | ||||||
|  |  */ | ||||||
|  | public interface ResultError { | ||||||
|  |  | ||||||
|  |     int getCode(); | ||||||
|  |  | ||||||
|  |     String getMessage(); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,40 @@ | |||||||
|  | package com.weilab.biology.core.data.vo.result.error; | ||||||
|  |  | ||||||
|  | import com.weilab.biology.core.data.vo.result.ResultError; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-09-19 | ||||||
|  |  * Description : | ||||||
|  |  */ | ||||||
|  | public enum JobError implements ResultError { | ||||||
|  |     PARAM_CAN_NOT_BE_EMPTY(40100, "文本框和文件不能同时为空"), | ||||||
|  |     FILE_READ_FAIL(40101, "文件读取出错"), | ||||||
|  |     STATUS_UPDATE_FAIL(40102,"当前状态下不允许更新为指定状态"), | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  |     private int code; | ||||||
|  |  | ||||||
|  |     private String message; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private JobError(int code, String message) { | ||||||
|  |         this.code = code; | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public int getCode() { | ||||||
|  |         return code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setCode(int code) { | ||||||
|  |         this.code = code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public String getMessage() { | ||||||
|  |         return message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setMessage(String message) { | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,52 @@ | |||||||
|  | package com.weilab.biology.core.exception; | ||||||
|  |  | ||||||
|  | import com.weilab.biology.core.data.vo.result.ResultError; | ||||||
|  |  | ||||||
|  | public class BaseException extends RuntimeException { | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     private int code; | ||||||
|  |  | ||||||
|  |     private String message; | ||||||
|  |  | ||||||
|  |     private Object data; | ||||||
|  |  | ||||||
|  |     public BaseException(int code, String message, Object data) { | ||||||
|  |         this.code = code; | ||||||
|  |         this.message = message; | ||||||
|  |         this.data = data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public BaseException(int code, String message) { | ||||||
|  |         this(code, message, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public BaseException(ResultError error) { | ||||||
|  |         this(error.getCode(), error.getMessage(), null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public int getCode() { | ||||||
|  |         return code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setCode(int code) { | ||||||
|  |         this.code = code; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String getMessage() { | ||||||
|  |         return message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setMessage(String message) { | ||||||
|  |         this.message = message; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Object getData() { | ||||||
|  |         return data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setData(Object data) { | ||||||
|  |         this.data = data; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,119 @@ | |||||||
|  | package com.weilab.biology.core.exception; | ||||||
|  |  | ||||||
|  | import com.weilab.biology.core.data.vo.result.CommonError; | ||||||
|  | import com.weilab.biology.core.data.vo.result.Result; | ||||||
|  | import org.springframework.http.converter.HttpMessageNotReadableException; | ||||||
|  | import org.springframework.validation.BindingResult; | ||||||
|  | import org.springframework.validation.FieldError; | ||||||
|  | import org.springframework.validation.ObjectError; | ||||||
|  | import org.springframework.web.HttpRequestMethodNotSupportedException; | ||||||
|  | import org.springframework.web.bind.MethodArgumentNotValidException; | ||||||
|  | import org.springframework.web.bind.MissingServletRequestParameterException; | ||||||
|  | import org.springframework.web.bind.annotation.ExceptionHandler; | ||||||
|  | import org.springframework.web.bind.annotation.RestControllerAdvice; | ||||||
|  | import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; | ||||||
|  | import org.springframework.web.multipart.support.MissingServletRequestPartException; | ||||||
|  |  | ||||||
|  | import javax.validation.ConstraintViolationException; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | @RestControllerAdvice | ||||||
|  | public class GlobalExceptionHandler { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 自定义异常捕获 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(BaseException.class) | ||||||
|  |     public Result handleBaseException(BaseException e) { | ||||||
|  |         return Result.getResult(e.getCode(), e.getMessage(), e.getData()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 服务器错误。常见有数据库错误 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(Exception.class) | ||||||
|  |     public Result handleException(Exception e) { | ||||||
|  |         e.printStackTrace(); | ||||||
|  |         return Result.fail(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * JSON解析异常,最常见NullPointerException,这里均将其过滤 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler({NullPointerException.class}) | ||||||
|  |     public Result handleJSONException(Exception e){ | ||||||
|  |         return Result.getResult(CommonError.REQUEST_NOT_ALLOW); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 参数校验错误异常 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(MethodArgumentNotValidException.class) | ||||||
|  |     public Result validationBodyException(MethodArgumentNotValidException e) { | ||||||
|  |         BindingResult result = e.getBindingResult(); | ||||||
|  |         String message = CommonError.PARAM_WRONG.getMessage(); | ||||||
|  |         if (result.hasErrors()) { | ||||||
|  |             List<ObjectError> errors = result.getAllErrors(); | ||||||
|  |             if (errors.size() > 0) { | ||||||
|  |                 FieldError fieldError = (FieldError) errors.get(0); | ||||||
|  |                 message = fieldError.getDefaultMessage(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return Result.getResult(CommonError.PARAM_WRONG.getCode(), message); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 参数类型转换错误 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(MethodArgumentTypeMismatchException.class) | ||||||
|  |     public Result methodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) { | ||||||
|  |         return Result.getResult(CommonError.PARAM_WRONG.getCode(), | ||||||
|  |                 e.getName() + "参数类型转换错误"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 参数转换JSON出错 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(HttpMessageNotReadableException.class) | ||||||
|  |     public Result httpMessageNotReadableException(HttpMessageNotReadableException e) { | ||||||
|  |         return Result.getResult(CommonError.PARAM_WRONG); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求方法不允许 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(HttpRequestMethodNotSupportedException.class) | ||||||
|  |     public Result methodNotSupportedException(HttpRequestMethodNotSupportedException e) { | ||||||
|  |         return Result.getResult(CommonError.METHOD_NOT_ALLOW.getCode(), | ||||||
|  |                 e.getMethod() + "方法不允许"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 缺少请求参数 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler({MissingServletRequestParameterException.class, MissingServletRequestPartException.class}) | ||||||
|  |     public Result missingParameterException(Exception e) { | ||||||
|  |         String message = CommonError.PARAM_WRONG.getMessage(); | ||||||
|  |         if (e instanceof MissingServletRequestParameterException) { | ||||||
|  |             message = ((MissingServletRequestParameterException) e).getParameterName() + "不能为空"; | ||||||
|  |         } else if (e instanceof MissingServletRequestPartException) { | ||||||
|  |             message = ((MissingServletRequestPartException) e).getRequestPartName() + "不能为空"; | ||||||
|  |         } | ||||||
|  |         return Result.getResult(CommonError.PARAM_WRONG.getCode(), message); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 请求参数格式错误 | ||||||
|  |      */ | ||||||
|  |     @ExceptionHandler(ConstraintViolationException.class) | ||||||
|  |     public Result ConstraintViolationException(ConstraintViolationException e) { | ||||||
|  |         if (e.getConstraintViolations().size() > 0) { | ||||||
|  |             return Result.getResult(CommonError.PARAM_WRONG.getCode(), | ||||||
|  |                     e.getConstraintViolations().iterator().next().getMessageTemplate()); | ||||||
|  |         } | ||||||
|  |         return Result.getResult(CommonError.PARAM_WRONG); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | package com.weilab.biology.core.exception; | ||||||
|  |  | ||||||
|  | import com.weilab.biology.core.data.vo.result.CommonError; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-04-30 | ||||||
|  |  * Description : 网络异常 | ||||||
|  |  */ | ||||||
|  | public class NetworkException extends BaseException { | ||||||
|  |     public NetworkException() { | ||||||
|  |         super(CommonError.NETWORK_WRONG); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,60 @@ | |||||||
|  | package com.weilab.biology.core.validation; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import javax.validation.Constraint; | ||||||
|  | import javax.validation.Payload; | ||||||
|  | import java.lang.annotation.Documented; | ||||||
|  | import java.lang.annotation.Repeatable; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | import static java.lang.annotation.ElementType.*; | ||||||
|  | import static java.lang.annotation.RetentionPolicy.RUNTIME; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @Documented | ||||||
|  | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) | ||||||
|  | @Retention(RUNTIME) | ||||||
|  | @Repeatable(EnumValidation.List.class) | ||||||
|  | @Constraint(validatedBy = {EnumValidator.class}) | ||||||
|  | public @interface EnumValidation { | ||||||
|  |     String message() default "{*.validation.constraint.Enum.message}"; | ||||||
|  |  | ||||||
|  |     Class<?>[] groups() default {}; | ||||||
|  |  | ||||||
|  |     Class<? extends Payload>[] payload() default {}; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * the enum's class-type | ||||||
|  |      * | ||||||
|  |      * @return Class | ||||||
|  |      */ | ||||||
|  |     Class<?> clazz(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * the method's name ,which used to validate the enum's value | ||||||
|  |      * | ||||||
|  |      * @return method's name | ||||||
|  |      */ | ||||||
|  |     String method() default "getKey"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 是否允许为空 | ||||||
|  |      * | ||||||
|  |      * @return true or false | ||||||
|  |      */ | ||||||
|  |     boolean allowNull() default true; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Defines several {@link EnumValidation} annotations on the same element. | ||||||
|  |      * | ||||||
|  |      * @see EnumValidation | ||||||
|  |      */ | ||||||
|  |     @Documented | ||||||
|  |     @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) | ||||||
|  |     @Retention(RUNTIME) | ||||||
|  |     @interface List { | ||||||
|  |         EnumValidation[] value(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -0,0 +1,63 @@ | |||||||
|  | package com.weilab.biology.core.validation; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import javax.validation.ConstraintValidator; | ||||||
|  | import javax.validation.ConstraintValidatorContext; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Controller入参对象中属性枚举项校验 | ||||||
|  |  */ | ||||||
|  | public class EnumValidator implements ConstraintValidator<EnumValidation, Object> { | ||||||
|  |  | ||||||
|  |     private EnumValidation annotation; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Initializes the validator in preparation for | ||||||
|  |      * {@link #isValid(Object, ConstraintValidatorContext)} calls. | ||||||
|  |      * The constraint annotation for a given constraint declaration | ||||||
|  |      * is passed. | ||||||
|  |      * <p> | ||||||
|  |      * This method is guaranteed to be called before any use of this instance for | ||||||
|  |      * validation. | ||||||
|  |      * <p> | ||||||
|  |      * The default implementation is a no-op. | ||||||
|  |      * | ||||||
|  |      * @param constraintAnnotation annotation instance for a given constraint declaration | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void initialize(EnumValidation constraintAnnotation) { | ||||||
|  |         this.annotation = constraintAnnotation; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Implements the validation logic. | ||||||
|  |      * The state of {@code value} must not be altered. | ||||||
|  |      * <p> | ||||||
|  |      * This method can be accessed concurrently, thread-safety must be ensured | ||||||
|  |      * by the implementation. | ||||||
|  |      * | ||||||
|  |      * @param value   object to validate | ||||||
|  |      * @param context context in which the constraint is evaluated | ||||||
|  |      * @return {@code false} if {@code value} does not pass the constraint | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public boolean isValid(Object value, ConstraintValidatorContext context) { | ||||||
|  |         if (value == null) { | ||||||
|  |             return annotation.allowNull(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Object[] objects = annotation.clazz().getEnumConstants(); | ||||||
|  |         try { | ||||||
|  |             Method method = annotation.clazz().getMethod(annotation.method()); | ||||||
|  |             for (Object o : objects) { | ||||||
|  |                 if (value.equals(method.invoke(o))) { | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             throw new RuntimeException(e); | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/main/java/com/weilab/biology/mapper/JobMapper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/main/java/com/weilab/biology/mapper/JobMapper.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | package com.weilab.biology.mapper; | ||||||
|  |  | ||||||
|  | import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||||||
|  | import com.weilab.biology.core.data.dto.JobLessDto; | ||||||
|  | import com.weilab.biology.core.data.po.Job; | ||||||
|  | import org.apache.ibatis.annotations.Mapper; | ||||||
|  | import org.apache.ibatis.annotations.Param; | ||||||
|  | import org.python.modules.itertools.count; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-09-19 | ||||||
|  |  * Description : | ||||||
|  |  */ | ||||||
|  | @Mapper | ||||||
|  | public interface JobMapper extends BaseMapper<Job> { | ||||||
|  |  | ||||||
|  |     List<Job> selectRunningJobs(); | ||||||
|  |  | ||||||
|  |     Job selectNextWaitingJob(); | ||||||
|  |  | ||||||
|  |     List<Job> selectJobList(@Param("type") Integer type, | ||||||
|  |                             @Param("count") Integer count); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										242
									
								
								src/main/java/com/weilab/biology/service/JobService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								src/main/java/com/weilab/biology/service/JobService.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,242 @@ | |||||||
|  | package com.weilab.biology.service; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.io.FileUtil; | ||||||
|  | import com.alibaba.fastjson.JSON; | ||||||
|  | import com.alibaba.fastjson.JSONObject; | ||||||
|  | import com.weilab.biology.core.data.dto.JobDto; | ||||||
|  | import com.weilab.biology.core.data.dto.JobLessDto; | ||||||
|  | import com.weilab.biology.core.data.enums.JobStatusEnum; | ||||||
|  | import com.weilab.biology.core.data.po.Job; | ||||||
|  | import com.weilab.biology.core.data.vo.result.CommonError; | ||||||
|  | import com.weilab.biology.core.data.vo.result.Result; | ||||||
|  | import com.weilab.biology.core.data.vo.result.error.JobError; | ||||||
|  | import com.weilab.biology.mapper.JobMapper; | ||||||
|  | import com.weilab.biology.util.FileUtils; | ||||||
|  | import com.weilab.biology.util.MailUtil; | ||||||
|  | import com.weilab.biology.util.TaskExecutorUtil; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.beans.factory.annotation.Value; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  | import org.springframework.transaction.annotation.Transactional; | ||||||
|  |  | ||||||
|  | import java.io.BufferedInputStream; | ||||||
|  | import java.io.File; | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by skyyemperor on 2021-09-19 | ||||||
|  |  * Description : | ||||||
|  |  */ | ||||||
|  | @Service | ||||||
|  | @Slf4j | ||||||
|  | public class JobService { | ||||||
|  |  | ||||||
|  |     @Value("${biology.python-cmd}") | ||||||
|  |     private String pythonCmd; | ||||||
|  |  | ||||||
|  |     @Value("${biology.request-path}") | ||||||
|  |     private String requestPath; | ||||||
|  |  | ||||||
|  |     @Value("${biology.result-path}") | ||||||
|  |     private String resultDataPath; | ||||||
|  |  | ||||||
|  |     @Value("${biology.log-path}") | ||||||
|  |     private String logPath; | ||||||
|  |  | ||||||
|  |     @Value("${biology.concurrent-num}") | ||||||
|  |     private Integer concurrentNum; | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private JobMapper jobMapper; | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private MailUtil mailUtil; | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private TaskExecutorUtil<?> taskExecutorUtil; | ||||||
|  |  | ||||||
|  |     private static final String SUBJECT = "【DeepBIO Result Notice】"; | ||||||
|  |     private static final String SUCCESS_EMAIL_CONTENT = "Your request has been completed, click http://server.wei-group.net/front/biology/#/resultMail?jobId=%s to check the detail information"; | ||||||
|  |     private static final String FAIL_EMAIL_CONTENT = "We are very sorry, but some errors occurred in the task you submitted, click http://server.wei-group.net/front/biology/#/resultMail?jobId=%s to check the detail information"; | ||||||
|  |     private static final String TIMEOUT_EMAIL_CONTENT = "We are very sorry, but the task you submitted was overtime, click http://server.wei-group.net/front/biology/#/resultMail?jobId=%s to check the detail information"; | ||||||
|  |     private static final String RECEIVED_EMAIL_CONTENT = "Your request has been received,  click http://server.wei-group.net/front/biology/#/resultMail?jobId=%s to check the detail information"; | ||||||
|  |     private static final String START_RUNNING_EMAIL_CONTENT = "Your task has started running, click http://server.wei-group.net/front/biology/#/resultMail?jobId=%s to check the detail information"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 提交job | ||||||
|  |      * | ||||||
|  |      * @param dataStr 文本内容 | ||||||
|  |      * @param param   其他参数(json格式) | ||||||
|  |      * @param mail    邮箱 | ||||||
|  |      * @return | ||||||
|  |      * @throws Exception | ||||||
|  |      */ | ||||||
|  |     @Transactional | ||||||
|  |     public Result submit(String dataStr, BufferedInputStream dataStream, JSONObject param, String mail, Integer type) { | ||||||
|  |         Job job = new Job("", JSON.toJSONString(param), mail, JobStatusEnum.WAIT.getKey(), LocalDateTime.now(), type); | ||||||
|  |         jobMapper.insert(job); | ||||||
|  |         sendEmail(job.getJobId(), JobStatusEnum.WAIT, mail); | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             //将请求数据写入本地文件,之后向python传递文件路径参数 | ||||||
|  |             String dataPath = String.format(requestPath + File.separator + "job-%d-dataStr.txt", job.getJobId()); | ||||||
|  |             if (dataStream != null) { | ||||||
|  |                 FileUtil.writeFromStream(dataStream, dataPath); | ||||||
|  |             } else { | ||||||
|  |                 FileUtils.writeStringToFile(dataPath, dataStr); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             //将jobId和dataPath参数添加至param中 | ||||||
|  |             param.put("jobId", job.getJobId()); | ||||||
|  |             param.put("requestDataPath", dataPath); | ||||||
|  |             param.put("resultDataPath", resultDataPath); | ||||||
|  |  | ||||||
|  |             //更新数据库param字段 | ||||||
|  |             job.setParam(JSON.toJSONString(param)); | ||||||
|  |             jobMapper.updateById(job); | ||||||
|  |  | ||||||
|  |             runNextJob(); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             updateJobStatus(job.getJobId(), JobStatusEnum.FAIL); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return getJobInfo(job.getJobId()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Result getJobInfo(Integer jobId) { | ||||||
|  |         Job job = jobMapper.selectById(jobId); | ||||||
|  |         if (job == null) | ||||||
|  |             return Result.getResult(CommonError.CONTENT_NOT_FOUND); | ||||||
|  |         return Result.success(JobDto.parseJob(job)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Result updateJobStatus(Integer jobId, JobStatusEnum status) { | ||||||
|  |         return updateJobStatus(jobId, status, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Result updateJobStatus(Integer jobId, JobStatusEnum status, String result) { | ||||||
|  |         System.out.println(status.getRemark()); | ||||||
|  |         Job job = jobMapper.selectById(jobId); | ||||||
|  |         if (job == null) | ||||||
|  |             return Result.getResult(CommonError.CONTENT_NOT_FOUND); | ||||||
|  |  | ||||||
|  |         switch (status) { | ||||||
|  |             case WAIT: | ||||||
|  |                 break; | ||||||
|  |             case SUCCESS: | ||||||
|  |                 job.setCompleteTime(LocalDateTime.now()); | ||||||
|  |                 job.setResult(result); | ||||||
|  |                 break; | ||||||
|  |             case FAIL: | ||||||
|  |             case TIMEOUT: | ||||||
|  |                 if (!job.getStatus().equals(JobStatusEnum.RUNNING.getKey()) | ||||||
|  |                         && !job.getStatus().equals(JobStatusEnum.REQED.getKey())) | ||||||
|  |                     return Result.getResult(JobError.STATUS_UPDATE_FAIL); | ||||||
|  |                 job.setCompleteTime(LocalDateTime.now()); | ||||||
|  |                 break; | ||||||
|  |             case RUNNING: | ||||||
|  |                 if (!job.getStatus().equals(JobStatusEnum.REQED.getKey())) | ||||||
|  |                     return Result.getResult(JobError.STATUS_UPDATE_FAIL); | ||||||
|  |                 job.setCreateTime(LocalDateTime.now()); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         job.setStatus(status.getKey()); | ||||||
|  |         jobMapper.updateById(job); | ||||||
|  |  | ||||||
|  |         sendEmail(jobId, status, job.getMail()); | ||||||
|  |         runNextJob(); | ||||||
|  |  | ||||||
|  |         return getJobInfo(jobId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Result getJobList(Integer type) { | ||||||
|  |         List<Job> jobs = jobMapper.selectJobList(type, 200); | ||||||
|  |         return Result.success(jobs.stream().map(JobLessDto::parseJob).collect(Collectors.toList())); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 运行下一个job | ||||||
|  |      */ | ||||||
|  |     private synchronized void runNextJob() { | ||||||
|  |         Job nextJob = null; | ||||||
|  |         try { | ||||||
|  |             //并发数小于concurrentNum,运行该job | ||||||
|  |             if (jobMapper.selectRunningJobs().size() < concurrentNum) { | ||||||
|  |                 if ((nextJob = jobMapper.selectNextWaitingJob()) != null) { | ||||||
|  |                     //更新job状态 | ||||||
|  |                     nextJob.setStatus(JobStatusEnum.REQED.getKey()); | ||||||
|  |                     jobMapper.updateById(nextJob); | ||||||
|  |  | ||||||
|  |                     waitRunning(nextJob.getJobId()); | ||||||
|  |  | ||||||
|  |                     String logFilePath = String.format(logPath + File.separator + "task-log-%s.txt", nextJob.getJobId()); | ||||||
|  |                     String cmd = String.format("%s -setting '%s' >> %s 2>&1", pythonCmd, nextJob.getParam(), logFilePath); | ||||||
|  |  | ||||||
|  |                     log.info("执行命令: " + cmd); | ||||||
|  |  | ||||||
|  |                     String[] cmds = new String[]{"/bin/sh", "-c", cmd}; | ||||||
|  |  | ||||||
|  |                     Runtime.getRuntime().exec(cmds); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             if (nextJob != null) { | ||||||
|  |                 nextJob.setStatus(JobStatusEnum.FAIL.getKey()); | ||||||
|  |                 jobMapper.updateById(nextJob); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 等待运行,超时时间60秒 | ||||||
|  |      */ | ||||||
|  |     private void waitRunning(Integer jobId) { | ||||||
|  |         //等待60秒,检查是否已运行 | ||||||
|  |         taskExecutorUtil.schedule(() -> { | ||||||
|  |             Job job = jobMapper.selectById(jobId); | ||||||
|  |             if (job.getStatus().equals(JobStatusEnum.REQED.getKey())) { | ||||||
|  |                 updateJobStatus(jobId, JobStatusEnum.FAIL); | ||||||
|  |             } | ||||||
|  |         }, 60, TimeUnit.SECONDS); | ||||||
|  |  | ||||||
|  |         //等待4小时,查看是否执行完成 | ||||||
|  |         taskExecutorUtil.schedule(() -> { | ||||||
|  |             Job job = jobMapper.selectById(jobId); | ||||||
|  |             if (job.getStatus().equals(JobStatusEnum.RUNNING.getKey())) { | ||||||
|  |                 updateJobStatus(jobId, JobStatusEnum.TIMEOUT); | ||||||
|  |             } | ||||||
|  |         }, 4, TimeUnit.HOURS); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void sendEmail(Integer jobId, JobStatusEnum status, String mail) { | ||||||
|  |         String content = null; | ||||||
|  |         switch (status) { | ||||||
|  |             case WAIT: | ||||||
|  |                 content = String.format(RECEIVED_EMAIL_CONTENT, jobId); | ||||||
|  |                 break; | ||||||
|  |             case SUCCESS: | ||||||
|  |                 content = String.format(SUCCESS_EMAIL_CONTENT, jobId); | ||||||
|  |                 break; | ||||||
|  |             case FAIL: | ||||||
|  |                 content = String.format(FAIL_EMAIL_CONTENT, jobId); | ||||||
|  |                 break; | ||||||
|  |             case TIMEOUT: | ||||||
|  |                 content = String.format(TIMEOUT_EMAIL_CONTENT, jobId); | ||||||
|  |                 break; | ||||||
|  |             case RUNNING: | ||||||
|  |                 content = String.format(START_RUNNING_EMAIL_CONTENT, jobId); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         if (content != null) | ||||||
|  |             mailUtil.send(mail, SUBJECT, content); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										118
									
								
								src/main/java/com/weilab/biology/util/FileUtils.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								src/main/java/com/weilab/biology/util/FileUtils.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  | package com.weilab.biology.util; | ||||||
|  |  | ||||||
|  | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
|  | import java.io.*; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 文件读取工具类 | ||||||
|  |  */ | ||||||
|  | public class FileUtils { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * MultipartFile 转换成File | ||||||
|  |      * | ||||||
|  |      * @param multfile 原文件类型 | ||||||
|  |      * @return File | ||||||
|  |      */ | ||||||
|  |     public static File multipartToFile(MultipartFile multfile) { | ||||||
|  |         File file = null; | ||||||
|  |         try { | ||||||
|  |             file = File.createTempFile("prefix", "_" + multfile.getOriginalFilename()); | ||||||
|  |             multfile.transferTo(file); | ||||||
|  |         } catch (IOException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |         return file; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 读取文件内容,作为字符串返回 | ||||||
|  |      */ | ||||||
|  |     public static String readFileAsString(String filePath) throws IOException { | ||||||
|  |         File file = new File(filePath); | ||||||
|  |         if (!file.exists()) { | ||||||
|  |             throw new FileNotFoundException(filePath); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return readFileAsString(file); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 读取文件内容,作为字符串返回 | ||||||
|  |      */ | ||||||
|  |     public static String readFileAsString(File file) throws IOException { | ||||||
|  |         StringBuilder sb = new StringBuilder((int) (file.length())); | ||||||
|  |         // 创建字节输入流 | ||||||
|  |         FileInputStream fis = new FileInputStream(file); | ||||||
|  |         // 创建一个长度为10240的Buffer | ||||||
|  |         byte[] bbuf = new byte[10240]; | ||||||
|  |         // 用于保存实际读取的字节数 | ||||||
|  |         int hasRead = 0; | ||||||
|  |         while ((hasRead = fis.read(bbuf)) > 0) { | ||||||
|  |             sb.append(new String(bbuf, 0, hasRead)); | ||||||
|  |         } | ||||||
|  |         fis.close(); | ||||||
|  |         return sb.toString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 根据文件路径读取byte[] 数组 | ||||||
|  |      */ | ||||||
|  |     public static byte[] readFileAsBytes(String filePath) throws IOException { | ||||||
|  |         File file = new File(filePath); | ||||||
|  |         if (!file.exists()) { | ||||||
|  |             throw new FileNotFoundException(filePath); | ||||||
|  |         } else { | ||||||
|  |             return readFileAsBytes(file); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 根据文件读取byte[]数组 | ||||||
|  |      */ | ||||||
|  |     public static byte[] readFileAsBytes(File file) throws IOException { | ||||||
|  |         if (file == null) { | ||||||
|  |             throw new FileNotFoundException(); | ||||||
|  |         } else { | ||||||
|  |             ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length()); | ||||||
|  |             BufferedInputStream in = null; | ||||||
|  |  | ||||||
|  |             try { | ||||||
|  |                 in = new BufferedInputStream(new FileInputStream(file)); | ||||||
|  |                 short bufSize = 1024; | ||||||
|  |                 byte[] buffer = new byte[bufSize]; | ||||||
|  |                 int len1; | ||||||
|  |                 while (-1 != (len1 = in.read(buffer, 0, bufSize))) { | ||||||
|  |                     bos.write(buffer, 0, len1); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 return bos.toByteArray(); | ||||||
|  |             } finally { | ||||||
|  |                 try { | ||||||
|  |                     if (in != null) { | ||||||
|  |                         in.close(); | ||||||
|  |                     } | ||||||
|  |                 } catch (IOException var14) { | ||||||
|  |                     var14.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |                 bos.close(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     public static void writeStringToFile(String filePath, String content) throws IOException { | ||||||
|  |         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath)); | ||||||
|  |         bufferedOutputStream.write(content.getBytes()); | ||||||
|  |         bufferedOutputStream.flush(); | ||||||
|  |         bufferedOutputStream.close(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static void writeByteToFile(String filePath, byte[] content) throws IOException { | ||||||
|  |         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath)); | ||||||
|  |         bufferedOutputStream.write(content); | ||||||
|  |         bufferedOutputStream.flush(); | ||||||
|  |         bufferedOutputStream.close(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										39
									
								
								src/main/java/com/weilab/biology/util/MailUtil.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/main/java/com/weilab/biology/util/MailUtil.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | package com.weilab.biology.util; | ||||||
|  |  | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.beans.factory.annotation.Value; | ||||||
|  | import org.springframework.mail.SimpleMailMessage; | ||||||
|  | import org.springframework.mail.javamail.JavaMailSenderImpl; | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | @Component | ||||||
|  | @Slf4j | ||||||
|  | public class MailUtil { | ||||||
|  |     @Autowired | ||||||
|  |     private JavaMailSenderImpl mailSender; | ||||||
|  |  | ||||||
|  |     @Value("${spring.mail.username}") | ||||||
|  |     private String sender; | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private TaskExecutorUtil<?> taskExecutorUtil; | ||||||
|  |  | ||||||
|  |     public void send(String receiver, String subject, String content) { | ||||||
|  |         taskExecutorUtil.run(() -> { | ||||||
|  |             SimpleMailMessage message = new SimpleMailMessage(); | ||||||
|  |             message.setSubject(subject);//设置标题 | ||||||
|  |             message.setText(content);//设置内容 | ||||||
|  |  | ||||||
|  |             message.setTo(receiver); | ||||||
|  |             message.setFrom(sender); | ||||||
|  |  | ||||||
|  |             mailSender.send(message); | ||||||
|  |  | ||||||
|  |             log.info("Mail已发送: " + message); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								src/main/java/com/weilab/biology/util/TaskExecutorUtil.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/main/java/com/weilab/biology/util/TaskExecutorUtil.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | package com.weilab.biology.util; | ||||||
|  |  | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
|  | import java.util.concurrent.*; | ||||||
|  |  | ||||||
|  | @Component | ||||||
|  | public class TaskExecutorUtil<C> { | ||||||
|  |  | ||||||
|  |     public TaskExecutorUtil() { | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static final ThreadFactory factory = new ThreadFactory() { | ||||||
|  |         @Override | ||||||
|  |         public Thread newThread(Runnable r) { | ||||||
|  |             return new Thread(r); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     private static final ThreadPoolExecutor cachePool = new ThreadPoolExecutor( | ||||||
|  |             2, 40, | ||||||
|  |             60L, TimeUnit.SECONDS, | ||||||
|  |             new SynchronousQueue<Runnable>(), | ||||||
|  |             factory | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     private static final ScheduledExecutorService scheduledThreadPool = | ||||||
|  |             Executors.newScheduledThreadPool(5); | ||||||
|  |  | ||||||
|  |     public void run(Runnable r) { | ||||||
|  |         cachePool.execute(r); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Future<C> submit(Callable<C> c) { | ||||||
|  |         return cachePool.submit(c); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void schedule(Runnable runnable, long delay, TimeUnit timeUnit) { | ||||||
|  |         scheduledThreadPool.schedule(runnable, delay, timeUnit); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								src/main/resources/mapper/JobMapper.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/main/resources/mapper/JobMapper.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||||||
|  | <mapper namespace="com.weilab.biology.mapper.JobMapper"> | ||||||
|  |     <resultMap id="BaseResultMap" type="com.weilab.biology.core.data.po.Job"> | ||||||
|  |         <id column="job_id" jdbcType="INTEGER" property="jobId"/> | ||||||
|  |         <result column="data" jdbcType="LONGVARCHAR" property="data"/> | ||||||
|  |         <result column="param" jdbcType="VARCHAR" property="param"/> | ||||||
|  |         <result column="mail" jdbcType="VARCHAR" property="mail"/> | ||||||
|  |         <result column="result" jdbcType="LONGVARCHAR" property="result"/> | ||||||
|  |         <result column="status" jdbcType="TINYINT" property="status"/> | ||||||
|  |         <result column="request_time" jdbcType="TIMESTAMP" property="requestTime"/> | ||||||
|  |         <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/> | ||||||
|  |         <result column="complete_time" jdbcType="TIMESTAMP" property="completeTime"/> | ||||||
|  |         <result column="type" jdbcType="INTEGER" property="type"/> | ||||||
|  |     </resultMap> | ||||||
|  |     <sql id="JobSql"> | ||||||
|  |         SELECT job_id, | ||||||
|  |                `data`, | ||||||
|  |                param, | ||||||
|  |                mail, | ||||||
|  |                result, | ||||||
|  |                `status`, | ||||||
|  |                request_time, | ||||||
|  |                create_time, | ||||||
|  |                complete_time, | ||||||
|  |                type | ||||||
|  |         FROM job | ||||||
|  |     </sql> | ||||||
|  |     <sql id="JobLessSql"> | ||||||
|  |         SELECT job_id, | ||||||
|  |                `status`, | ||||||
|  |                request_time, | ||||||
|  |                create_time, | ||||||
|  |                complete_time, | ||||||
|  |                type | ||||||
|  |         FROM job | ||||||
|  |     </sql> | ||||||
|  |     <select id="selectRunningJobs" resultMap="BaseResultMap"> | ||||||
|  |         <include refid="JobSql"/> | ||||||
|  |         WHERE status = '${@com.weilab.biology.core.data.enums.JobStatusEnum@RUNNING.getKey()}' | ||||||
|  |            OR status = '${@com.weilab.biology.core.data.enums.JobStatusEnum@REQED.getKey()}' | ||||||
|  |     </select> | ||||||
|  |     <select id="selectNextWaitingJob" resultMap="BaseResultMap"> | ||||||
|  |         <include refid="JobSql"/> | ||||||
|  |         WHERE status = '${@com.weilab.biology.core.data.enums.JobStatusEnum@WAIT.getKey()}' | ||||||
|  |         ORDER BY request_time | ||||||
|  |         LIMIT 1 | ||||||
|  |     </select> | ||||||
|  |     <select id="selectJobList" resultMap="BaseResultMap"> | ||||||
|  |         <include refid="JobLessSql"/> | ||||||
|  |         <where> | ||||||
|  |             <if test="type != null"> | ||||||
|  |                 AND type = #{type} | ||||||
|  |             </if> | ||||||
|  |         </where> | ||||||
|  |         ORDER BY job_id DESC | ||||||
|  |         LIMIT #{count} | ||||||
|  |     </select> | ||||||
|  | </mapper> | ||||||
| @@ -0,0 +1,13 @@ | |||||||
|  | package com.weilab.biology; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | @SpringBootTest | ||||||
|  | class BiologyApplicationTests { | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void contextLoads() { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user