diff --git a/.gitignore b/.gitignore index 3856100..549e00a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,73 +1,33 @@ -# ---> Java -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* - -# ---> macOS -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# ---> Maven +HELP.md target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -# https://github.com/takari/maven-wrapper#usage-without-binary-jar -.mvn/wrapper/maven-wrapper.jar +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ -# Eclipse m2e generated files -# Eclipse Core -.project -# JDT-specific (Eclipse Java Development Tools) +### 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/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..7618087 --- /dev/null +++ b/pom.xml @@ -0,0 +1,115 @@ + + + 4.0.0 + com.athis.tech + athis-server + 0.0.1-SNAPSHOT + athis-server + athis-server + + 1.8 + UTF-8 + UTF-8 + 2.7.6 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-websocket + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.3.0 + + + org.projectlombok + lombok + true + + + io.vavr + vavr + 0.10.5 + + + com.google.guava + guava + 33.3.1-jre + + + org.apache.groovy + groovy + 4.0.23 + + + com.alibaba + fastjson + 2.0.53 + + + com.mysql + mysql-connector-j + runtime + + + com.oracle.database.jdbc + ojdbc8 + 18.3.0.0 + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + com.athis.tech.athisserver.AthisServerApplication + true + + + + repackage + + repackage + + + + + + + + diff --git a/src/main/java/com/athis/tech/athisserver/AthisServerApplication.java b/src/main/java/com/athis/tech/athisserver/AthisServerApplication.java new file mode 100644 index 0000000..df959ef --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/AthisServerApplication.java @@ -0,0 +1,13 @@ +package com.athis.tech.athisserver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AthisServerApplication { + + public static void main(String[] args) { + SpringApplication.run(AthisServerApplication.class, args); + } + +} diff --git a/src/main/java/com/athis/tech/athisserver/conf/HuginnRpcApplicationContextAware.java b/src/main/java/com/athis/tech/athisserver/conf/HuginnRpcApplicationContextAware.java new file mode 100644 index 0000000..a3210c3 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/conf/HuginnRpcApplicationContextAware.java @@ -0,0 +1,20 @@ +package com.athis.tech.athisserver.conf; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class HuginnRpcApplicationContextAware implements ApplicationContextAware { + private static ApplicationContext ctx; + + public static ApplicationContext getApplicationContext() { + return ctx; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.ctx = applicationContext; + } +} \ No newline at end of file diff --git a/src/main/java/com/athis/tech/athisserver/conf/WebConfig.java b/src/main/java/com/athis/tech/athisserver/conf/WebConfig.java new file mode 100644 index 0000000..548d658 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/conf/WebConfig.java @@ -0,0 +1,17 @@ +package com.athis.tech.athisserver.conf; + +import com.athis.tech.athisserver.controller.filter.LoginInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new LoginInterceptor()) + .addPathPatterns("/**") + .excludePathPatterns("/","/login","/login/**"); + } +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/ProcedureEngineController.java b/src/main/java/com/athis/tech/athisserver/controller/ProcedureEngineController.java new file mode 100644 index 0000000..97ccbd2 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/ProcedureEngineController.java @@ -0,0 +1,213 @@ +package com.athis.tech.athisserver.controller; + +import com.athis.tech.athisserver.controller.filter.LoginUtil; +import com.athis.tech.athisserver.mybatis.mapper.entity.TokenEntityData; +import com.athis.tech.athisserver.service.engine.ProcedureEngineService; +import com.athis.tech.athisserver.service.exception.NotFoundException; +import com.athis.tech.athisserver.service.exception.ServiceException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.*; + +@RestController +@Slf4j +@RequestMapping("/server/procedure") +public class ProcedureEngineController { + @Autowired + private ProcedureEngineService procedureEngineService; + + @GetMapping("/engine/run/{key}") + public ResponseEntity> procedureEngineGet(@PathVariable("key") String key, HttpServletRequest request) { + try { + Map parameterMap = request.getParameterMap(); + Map paramMap = new LinkedHashMap<>(); + for (Map.Entry stringEntry : parameterMap.entrySet()) { + if (stringEntry.getValue() == null) { + paramMap.put(stringEntry.getKey(), null); + } else if (stringEntry.getValue().length == 0) { + paramMap.put(stringEntry.getKey(), null); + } else if (stringEntry.getValue().length == 1) { + paramMap.put(stringEntry.getKey(), stringEntry.getValue()[0]); + } else { + List list = new ArrayList<>(stringEntry.getValue().length); + list.addAll(Arrays.asList(stringEntry.getValue())); + paramMap.put(stringEntry.getKey(), list); + } + } + return runProcedure(key,paramMap); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } + + @PostMapping("/engine/run/{key}") + public ResponseEntity> procedureEnginePost(@PathVariable("key") String key, @RequestBody Map param) { + return runProcedure(key, param); + } + + @PutMapping("/engine/run/{key}") + public ResponseEntity> procedureEnginePut(@PathVariable("key") String key, @RequestBody Map param) { + return runProcedure(key, param); + } + + @PatchMapping("/engine/run/{key}") + public ResponseEntity> procedureEnginePatch(@PathVariable("key") String key, @RequestBody Map param) { + return runProcedure(key, param); + } + + @GetMapping("/engine/group/run/{key}") + public ResponseEntity> procedureGroupEngineGet(@PathVariable("key") String key, HttpServletRequest request) { + try { + Map parameterMap = request.getParameterMap(); + Map paramMap = new LinkedHashMap<>(); + for (Map.Entry stringEntry : parameterMap.entrySet()) { + if (stringEntry.getValue() == null) { + paramMap.put(stringEntry.getKey(), null); + } else if (stringEntry.getValue().length == 0) { + paramMap.put(stringEntry.getKey(), null); + } else if (stringEntry.getValue().length == 1) { + paramMap.put(stringEntry.getKey(), stringEntry.getValue()[0]); + } else { + List list = new ArrayList<>(stringEntry.getValue().length); + list.addAll(Arrays.asList(stringEntry.getValue())); + paramMap.put(stringEntry.getKey(), list); + } + } + Map stringObjectMap = procedureEngineService.runProcedureGroup(key, paramMap, true); + return ResponseEntity.ok(stringObjectMap); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } + + + @PostMapping("/engine/group/run/{key}") + public ResponseEntity> procedureGroupEnginePost(@PathVariable("key") String key, @RequestBody Map param) { + return runProcedureGroup(key, param); + } + + @PutMapping("/engine/group/run/{key}") + public ResponseEntity> procedureGroupEnginePut(@PathVariable("key") String key, @RequestBody Map param) { + return runProcedureGroup(key, param); + } + + @PatchMapping("/engine/group/run/{key}") + public ResponseEntity> procedureGroupEnginePatch(@PathVariable("key") String key, @RequestBody Map param) { + return runProcedureGroup(key, param); + } + + private ResponseEntity> runProcedureGroup(String key, Map param) { + try { + Map stringObjectMap = procedureEngineService.runProcedureGroup(key, param, true); + return ResponseEntity.ok(stringObjectMap); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } + + private ResponseEntity> runProcedure(String key, Map param) { + try { + TokenEntityData tokenData = LoginUtil.getTokenData(); + if(tokenData != null) { + String tokenFrom = tokenData.getTokenFrom(); + String yhid = tokenData.getYhid(); + Long bmid = tokenData.getBmid(); + Long jsid = tokenData.getJsid(); + param.put("current_yhid", yhid); + param.put("current_from", tokenFrom); + param.put("current_bmid", bmid); + param.put("current_jsid", jsid); + } + Set ks = new HashSet<>(); + ks.addAll(param.keySet()); + Map stringObjectMap = procedureEngineService.runProcedure(key, param, true); + for (String k : ks) { + stringObjectMap.remove(k); + } + return ResponseEntity.ok(stringObjectMap); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/TestController.java b/src/main/java/com/athis/tech/athisserver/controller/TestController.java new file mode 100644 index 0000000..56c4d91 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/TestController.java @@ -0,0 +1,29 @@ +package com.athis.tech.athisserver.controller; + +import com.athis.tech.athisserver.mybatis.mapper.ProcedureEngineMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; + +@RestController +public class TestController { + @Autowired + private ProcedureEngineMapper procedureEngineMapper; + + @GetMapping("test") + public void test() { + try { + HashMap map = new HashMap<>(); + map.put("yhid", "888"); +// map.put("errcode",0); +// map.put("errmsg",""); +// map.put("paraCursor",new ArrayList<>()); + procedureEngineMapper.runProcedure(map); + System.out.println("---------"); + } catch (Throwable e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/filter/LoginInterceptor.java b/src/main/java/com/athis/tech/athisserver/controller/filter/LoginInterceptor.java new file mode 100644 index 0000000..9b57b5b --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/filter/LoginInterceptor.java @@ -0,0 +1,39 @@ +package com.athis.tech.athisserver.controller.filter; + +import com.athis.tech.athisserver.conf.HuginnRpcApplicationContextAware; +import com.athis.tech.athisserver.mybatis.mapper.entity.TokenEntityData; +import com.athis.tech.athisserver.service.token.TokenService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Slf4j +public class LoginInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String token = LoginUtil.getToken(request); + if (token == null || token.isEmpty()) { + response.sendError(401,"请登录"); + return false; + } + TokenService tokenService = HuginnRpcApplicationContextAware.getApplicationContext().getBean(TokenService.class); + TokenEntityData tokenEntityData = tokenService.checkToken(token); + boolean b = tokenEntityData != null; + if(b) { + LoginUtil.setTokenData(tokenEntityData); + } else { + response.sendError(401,"请登录"); + } + return b; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + LoginUtil.clearTokenData(); + } +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/filter/LoginUser.java b/src/main/java/com/athis/tech/athisserver/controller/filter/LoginUser.java new file mode 100644 index 0000000..a942a7e --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/filter/LoginUser.java @@ -0,0 +1,4 @@ +package com.athis.tech.athisserver.controller.filter; + +public class LoginUser { +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/filter/LoginUtil.java b/src/main/java/com/athis/tech/athisserver/controller/filter/LoginUtil.java new file mode 100644 index 0000000..db75a70 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/filter/LoginUtil.java @@ -0,0 +1,36 @@ +package com.athis.tech.athisserver.controller.filter; + +import com.athis.tech.athisserver.mybatis.mapper.entity.TokenEntityData; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; + +public class LoginUtil { + private static final String key = "access_token"; + private static final ThreadLocal tokenDatas = new ThreadLocal<>(); + + public static void setTokenData(TokenEntityData tokenEntityData) { + tokenDatas.set(tokenEntityData); + } + + public static TokenEntityData getTokenData() { + return tokenDatas.get(); + } + + public static void clearTokenData() { + tokenDatas.remove(); + } + + public static String getToken(HttpServletRequest request) { + String accessToken = request.getHeader(key); + if ((accessToken == null || accessToken.isEmpty()) && request.getCookies() != null) { + for (Cookie cookie : request.getCookies()) { + if (key.equals(cookie.getName())) { + accessToken = cookie.getValue(); + break; + } + } + } + return accessToken; + } +} \ No newline at end of file diff --git a/src/main/java/com/athis/tech/athisserver/controller/login/LoginCheckReq.java b/src/main/java/com/athis/tech/athisserver/controller/login/LoginCheckReq.java new file mode 100644 index 0000000..0a43e92 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/login/LoginCheckReq.java @@ -0,0 +1,10 @@ +package com.athis.tech.athisserver.controller.login; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LoginCheckReq { + private String username; +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/login/LoginCheckResp.java b/src/main/java/com/athis/tech/athisserver/controller/login/LoginCheckResp.java new file mode 100644 index 0000000..66e0b77 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/login/LoginCheckResp.java @@ -0,0 +1,10 @@ +package com.athis.tech.athisserver.controller.login; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LoginCheckResp { + private Boolean isUsing; +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/login/LoginController.java b/src/main/java/com/athis/tech/athisserver/controller/login/LoginController.java new file mode 100644 index 0000000..5e51b92 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/login/LoginController.java @@ -0,0 +1,197 @@ +package com.athis.tech.athisserver.controller.login; + +import com.athis.tech.athisserver.controller.filter.LoginUtil; +import com.athis.tech.athisserver.mybatis.mapper.entity.TokenEntityData; +import com.athis.tech.athisserver.service.engine.ProcedureEngineService; +import com.athis.tech.athisserver.service.exception.NotFoundException; +import com.athis.tech.athisserver.service.exception.ServiceException; +import com.athis.tech.athisserver.service.token.TokenService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@RestController +@Slf4j +public class LoginController { + @Autowired + private ProcedureEngineService procedureEngineService; + @Autowired + private TokenService tokenService; + + @GetMapping("/login/roles") + public ResponseEntity> rules(@RequestParam("yhid") String yhid) { + try { + Map paramMap = new LinkedHashMap<>(); + paramMap.put("yhid", yhid); + Map stringObjectMap = procedureEngineService.runProcedure("user-roles", paramMap, false); + Object o = stringObjectMap.get("paraCursor"); + if (o != null && o instanceof List) { + List> list = (List>) o; + for (Map objectMap : list) { + objectMap.remove("YHMM"); + } + } + return ResponseEntity.ok(stringObjectMap); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } + + @GetMapping("/login/departs") + public ResponseEntity> departs(@RequestParam("yhid") String yhid) { + try { + Map paramMap = new LinkedHashMap<>(); + paramMap.put("yhid", yhid); + Map stringObjectMap = procedureEngineService.runProcedure("user-departs", paramMap, false); + Object o = stringObjectMap.get("paraCursor"); + if (o != null && o instanceof List) { + List> list = (List>) o; + for (Map objectMap : list) { + objectMap.remove("YHMM"); + } + } + return ResponseEntity.ok(stringObjectMap); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } + + @PostMapping("/login/check-using") + public ResponseEntity loginCheck(@RequestBody LoginCheckReq req) { + try { + boolean b = tokenService.checkUsing(req.getUsername()); + LoginCheckResp loginCheckResp = new LoginCheckResp(); + loginCheckResp.setIsUsing(b); + return ResponseEntity.ok(loginCheckResp); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } + + @PostMapping("/login") + public ResponseEntity login(@RequestBody LoginReq loginReq) { + try { + TokenEntityData login = tokenService.login(loginReq); + return ResponseEntity.ok(login); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } + + @GetMapping("/logout") + public ResponseEntity logout(HttpServletRequest request) { + try { + String token = LoginUtil.getToken(request); + if (token == null || token.isEmpty()) { + return ResponseEntity.badRequest().body("token is null"); + } + tokenService.logout(token); + return ResponseEntity.ok(""); + } catch (ServiceException e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errCode", e.getErrCode()); + errorBody.put("errorMessage", e.getErrMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorBody); + } catch (NotFoundException e) { + log.error(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("error", e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(map); + } catch (Exception e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } catch (Throwable e) { + log.error(e.getMessage(), e); + Map errorBody = new HashMap<>(); + errorBody.put("errorMessage", e.getMessage()); + return ResponseEntity.internalServerError().body(errorBody); + } + } +} diff --git a/src/main/java/com/athis/tech/athisserver/controller/login/LoginReq.java b/src/main/java/com/athis/tech/athisserver/controller/login/LoginReq.java new file mode 100644 index 0000000..37061de --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/controller/login/LoginReq.java @@ -0,0 +1,14 @@ +package com.athis.tech.athisserver.controller.login; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LoginReq { + private String username; + private String password; + private Long bmid; + private Long jsid; + private String tokenFrom; +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/ProcedureEngineMapper.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/ProcedureEngineMapper.java new file mode 100644 index 0000000..ff9a900 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/ProcedureEngineMapper.java @@ -0,0 +1,23 @@ +package com.athis.tech.athisserver.mybatis.mapper; + +import com.athis.tech.athisserver.mybatis.mapper.entity.ProcedureEngineData; +import com.athis.tech.athisserver.mybatis.mapper.entity.ProcedureEngineGroupData; +import com.athis.tech.athisserver.mybatis.provider.ProcedureUtil; +import org.apache.ibatis.annotations.*; +import org.apache.ibatis.mapping.StatementType; + +import java.util.Map; + +@Mapper +public interface ProcedureEngineMapper { + + @SelectProvider(type = ProcedureUtil.class, method = "runProcedure") + @Options(statementType = StatementType.CALLABLE) + void runProcedure(Map map); + + @Select("select * from t_engine_procedure where apikey = #{key}") + ProcedureEngineData getProcedure(@Param("key") String key); + + @Select("select * from t_engine_procedure_group where apikey = #{key}") + ProcedureEngineGroupData getProcedureGroup(@Param("key") String key); +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/ScriptMapper.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/ScriptMapper.java new file mode 100644 index 0000000..fb610c9 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/ScriptMapper.java @@ -0,0 +1,12 @@ +package com.athis.tech.athisserver.mybatis.mapper; + +import com.athis.tech.athisserver.mybatis.mapper.entity.ScriptEntityData; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +@Mapper +public interface ScriptMapper { + @Select("select * from t_engine_script where apikey = #{key}") + ScriptEntityData getScript(@Param("key") String key); +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/TokenMapper.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/TokenMapper.java new file mode 100644 index 0000000..77cf9dd --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/TokenMapper.java @@ -0,0 +1,26 @@ +package com.athis.tech.athisserver.mybatis.mapper; + +import com.athis.tech.athisserver.mybatis.mapper.entity.TokenEntityData; +import org.apache.ibatis.annotations.*; + +import java.util.List; + +@Mapper +public interface TokenMapper { + @Select("select * from t_user_token where token = #{token}") + TokenEntityData getToken(@Param("token") String token); + + @Update("update t_user_token set end_time = #{endTime} where token = #{token}") + void updateToken(@Param("token") String token, @Param("endTime") Long endTime); + + @Select("select * from t_user_token where yhid = #{yhid} ") + List getTokensByUser(@Param("yhid") String yhid); + @Select("select count(token) cnt from t_user_token where yhid = #{yhid} ") + Integer getTokenCountByUser(@Param("yhid") String yhid); + + @Delete("delete from t_user_token where token = #{token}") + void deleteUserByToken(@Param("token") String token); + + @Insert("insert into t_user_token (token,yhid,bmid,jsid,end_time,token_from) values (#{token},#{yhid},#{bmid},#{jsid},#{endTime},#{tokenFrom})") + void insertUserToken(TokenEntityData tokenEntityData); +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/BaseEntityData.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/BaseEntityData.java new file mode 100644 index 0000000..014a102 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/BaseEntityData.java @@ -0,0 +1,14 @@ +package com.athis.tech.athisserver.mybatis.mapper.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class BaseEntityData { + private String id; + private Long createdTime; + private Long updatedTime; + private String createdUser; + private String updatedUser; +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ProcedureEngineData.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ProcedureEngineData.java new file mode 100644 index 0000000..58b5ab9 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ProcedureEngineData.java @@ -0,0 +1,14 @@ +package com.athis.tech.athisserver.mybatis.mapper.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ProcedureEngineData extends BaseEntityData { + private String apikey; + private String script; + private String paramScriptKey; + private String resultScriptKey; + private Integer isWeb; +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ProcedureEngineGroupData.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ProcedureEngineGroupData.java new file mode 100644 index 0000000..9b5cf13 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ProcedureEngineGroupData.java @@ -0,0 +1,15 @@ +package com.athis.tech.athisserver.mybatis.mapper.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ProcedureEngineGroupData extends BaseEntityData { + private String apikey; + private String procedureKeys; + private String paramScriptKey; + private String resultScriptKey; + private Integer isTransactional; + private Integer isWeb; +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ScriptEntityData.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ScriptEntityData.java new file mode 100644 index 0000000..4dd10d9 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/ScriptEntityData.java @@ -0,0 +1,12 @@ +package com.athis.tech.athisserver.mybatis.mapper.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ScriptEntityData extends BaseEntityData { + private String key; + private String type;//procedure_before,procedure_after, procedureGroup_before,procedureGroup_after,sql,sqlGroup 先支持procedure和procedureGroup + private String script; +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/TokenEntityData.java b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/TokenEntityData.java new file mode 100644 index 0000000..3d75deb --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/mapper/entity/TokenEntityData.java @@ -0,0 +1,15 @@ +package com.athis.tech.athisserver.mybatis.mapper.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class TokenEntityData { + private String token; + private String yhid; + private Long bmid; + private Long jsid; + private Long endTime; + private String tokenFrom; +} diff --git a/src/main/java/com/athis/tech/athisserver/mybatis/provider/ProcedureUtil.java b/src/main/java/com/athis/tech/athisserver/mybatis/provider/ProcedureUtil.java new file mode 100644 index 0000000..073b940 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/mybatis/provider/ProcedureUtil.java @@ -0,0 +1,74 @@ +package com.athis.tech.athisserver.mybatis.provider; + +import groovy.lang.Binding; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import io.vavr.Tuple; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class ProcedureUtil { + private static final ThreadLocal scriptThreadLocal = new ThreadLocal<>(); + public static void setProcedure(String script) { + scriptThreadLocal.set(script); + } + + public static void clear() { + scriptThreadLocal.remove(); + } + + public String runProcedure(Map map) { + StringBuilder sb = new StringBuilder(); + sb.append(""); + return sb.toString(); + } + + public static void main(String[] args) { + System.out.println(System.currentTimeMillis()); + System.out.println("Hello, Groovy"); + System.out.println(Tuple.of("xxx")); + System.out.println(System.currentTimeMillis()); + Binding binding = new Binding(); + binding.setVariable("message","hello groovy"); + List list = new ArrayList<>(); +// binding.setVariable("list", list); +// binding.setThreadVariables(vars); + + // 创建GroovyShell实例 + GroovyShell shell = new GroovyShell(binding); + System.out.println(System.currentTimeMillis()); + // 定义Groovy脚本 + String script = "import io.vavr.Tuple;" + + "list.add('xx1');" + + "println message;" + + "println Tuple.of('xxx')"; + Script script1 = shell.parse(script); +// 设置内置变量 +// shell.setVariable("message", "Hello, Groovy!"); +// shell.setVariable("list", new ArrayList<>()); + // 执行Groovy脚本 +// Object result = shell.evaluate(script1); +// shell.evaluate("println(list.size())"); +// System.out.println(System.currentTimeMillis()); + System.out.println(System.currentTimeMillis()); + Object run = script1.run(); + shell.removeVariable("list"); + script1.run(); + shell.evaluate("println(list.size())"); + System.out.println(System.currentTimeMillis()); + System.out.println(); + // 输出结果 +// System.out.println(result); + } +} diff --git a/src/main/java/com/athis/tech/athisserver/service/engine/ProcedureEngineService.java b/src/main/java/com/athis/tech/athisserver/service/engine/ProcedureEngineService.java new file mode 100644 index 0000000..f3b8afd --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/service/engine/ProcedureEngineService.java @@ -0,0 +1,148 @@ +package com.athis.tech.athisserver.service.engine; + +import com.alibaba.fastjson2.JSON; +import com.athis.tech.athisserver.mybatis.mapper.ProcedureEngineMapper; +import com.athis.tech.athisserver.mybatis.mapper.entity.ProcedureEngineData; +import com.athis.tech.athisserver.mybatis.mapper.entity.ProcedureEngineGroupData; +import com.athis.tech.athisserver.mybatis.provider.ProcedureUtil; +import com.athis.tech.athisserver.service.exception.NotFoundException; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import io.vavr.control.Option; +import org.mybatis.spring.SqlSessionTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +@Component +public class ProcedureEngineService { + @Autowired + private ProcedureEngineMapper procedureEngineMapper; + @Autowired + private ScriptService scriptService; + @Autowired + private SqlSessionTemplate sqlSessionTemplate; + @Value("${athis.engine.isCache}") + private Boolean useCache; + + + private final static Cache> procedureCache = CacheBuilder.newBuilder() + //设置cache的初始大小为10,要合理设置该值 + .initialCapacity(10) + //设置并发数为5,即同一时间最多只能有1000个线程往cache执行写入操作 + .concurrencyLevel(1000) + //设置cache中的数据在写入之后的存活时间为10分钟 + .expireAfterWrite(10, TimeUnit.MINUTES).build(); + + private final static Cache> procedureGroupCache = CacheBuilder.newBuilder() + //设置cache的初始大小为10,要合理设置该值 + .initialCapacity(10) + //设置并发数为5,即同一时间最多只能有1000个线程往cache执行写入操作 + .concurrencyLevel(1000) + //设置cache中的数据在写入之后的存活时间为10分钟 + .expireAfterWrite(10, TimeUnit.MINUTES).build(); + + public Map runProcedure(String key, Map paramMap, boolean isWeb) { + ProcedureEngineData procedure = getProcedure(key); + if (procedure == null) { + throw new NotFoundException("not found procedure key"); + } + if (isWeb) { + if (procedure.getIsWeb() == null || procedure.getIsWeb() != 1) { + throw new NotFoundException("not found web controller"); + } + } + ProcedureUtil.setProcedure(procedure.getScript()); + try { + Map newParamMap = scriptService.runBeforeScript(procedure.getParamScriptKey(), key, paramMap); + procedureEngineMapper.runProcedure(newParamMap); + return scriptService.runAfterScript(procedure.getResultScriptKey(), key, newParamMap); + } catch (Throwable e) { + throw e; + } finally { + ProcedureUtil.clear(); + } + } + + public Map runProcedureGroup(String key, Map paramMap, boolean isWeb) { + ProcedureEngineGroupData procedureGroup = getProcedureGroup(key); + if (procedureGroup == null) { + throw new NotFoundException("not found procedure group key"); + } + if (isWeb) { + if (procedureGroup.getIsWeb() == null || procedureGroup.getIsWeb() != 1) { + throw new NotFoundException("not found web controller"); + } + } + String procedureKeys = procedureGroup.getProcedureKeys(); + if (procedureKeys == null || procedureKeys.isEmpty()) { + return null; + } + if (procedureGroup.getIsTransactional() != null && procedureGroup.getIsTransactional() == 1) { + runProcedureGroupTransactional(key, paramMap, procedureGroup); + } + return toRunProcedureGroup(key, paramMap, procedureGroup); + } + + @Transactional + public Map runProcedureGroupTransactional(String key, Map paramMap, ProcedureEngineGroupData procedureGroup) { + return toRunProcedureGroup(key, paramMap, procedureGroup); + } + + private Map toRunProcedureGroup(String key, Map paramMap, ProcedureEngineGroupData procedureGroup) { + try { + String procedureKeys = procedureGroup.getProcedureKeys(); + String[] split = procedureKeys.split(","); + Map resultMap = new HashMap<>(); + for (String s : split) { + if (s.trim().isEmpty()) { + continue; + } + //复制入参,保持每个调用的入参都一致且不会被覆盖 + Map paramCopy = (Map) JSON.parse(JSON.toJSONString(paramMap)); + Map newParamMap = scriptService.runBeforeScript(procedureGroup.getParamScriptKey(), key, paramCopy); + ProcedureEngineData procedure = getProcedure(key); + ProcedureUtil.setProcedure(procedure.getScript()); + procedureEngineMapper.runProcedure(newParamMap); + resultMap.put(s, newParamMap); + } + return scriptService.runAfterScript(procedureGroup.getResultScriptKey(), key, resultMap); + } catch (Throwable e) { + throw e; + } finally { + ProcedureUtil.clear(); + } + } + + private ProcedureEngineData getProcedure(String key) { + try { + if(useCache) { + Option procedureEngineData = procedureCache.get(key, () -> Option.of(procedureEngineMapper.getProcedure(key))); + return procedureEngineData.getOrNull(); + } + return procedureEngineMapper.getProcedure(key); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + private ProcedureEngineGroupData getProcedureGroup(String key) { + try { + if(useCache) { + Option procedureEngineGroupData = procedureGroupCache.get(key, () -> Option.of(procedureEngineMapper.getProcedureGroup(key))); + return procedureEngineGroupData.getOrNull(); + } + return procedureEngineMapper.getProcedureGroup(key); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/athis/tech/athisserver/service/engine/ScriptService.java b/src/main/java/com/athis/tech/athisserver/service/engine/ScriptService.java new file mode 100644 index 0000000..bcf3d49 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/service/engine/ScriptService.java @@ -0,0 +1,130 @@ +package com.athis.tech.athisserver.service.engine; + +import com.athis.tech.athisserver.mybatis.mapper.ScriptMapper; +import com.athis.tech.athisserver.mybatis.mapper.entity.ScriptEntityData; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import io.vavr.Tuple; +import io.vavr.Tuple2; +import io.vavr.control.Option; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +@Component +public class ScriptService { + @Autowired + private ScriptMapper scriptMapper; + @Value("${athis.engine.isCache}") + private Boolean useCache; + private static final GroovyShell groovyShell = new GroovyShell(); + private static final String SCRIPT_IMPORT = "import com.athis.tech.athisserver.service.engine.ScriptUtil;\n"; + + private final static Cache>> scriptCache = CacheBuilder.newBuilder() + //设置cache的初始大小为10,要合理设置该值 + .initialCapacity(10) + //设置并发数为5,即同一时间最多只能有1000个线程往cache执行写入操作 + .concurrencyLevel(1000) + //设置cache中的数据在写入之后的存活时间为10分钟 + .expireAfterWrite(365, TimeUnit.DAYS).build(); + + private final static Cache> scriptDataCache = CacheBuilder.newBuilder() + //设置cache的初始大小为10,要合理设置该值 + .initialCapacity(10) + //设置并发数为5,即同一时间最多只能有1000个线程往cache执行写入操作 + .concurrencyLevel(1000) + //设置cache中的数据在写入之后的存活时间为10分钟 + .expireAfterWrite(10, TimeUnit.DAYS).build(); + + public Map runBeforeScript(String scriptKey, String procedureKey, Map paramMap) { + if(scriptKey == null || scriptKey.isEmpty()) { + return paramMap; + } + Script script = getScript(scriptKey); + if (script == null) { + return paramMap; + } + Option scriptEntity = getScriptEntity(scriptKey); + ScriptUtil.ScriptData scriptData = new ScriptUtil.ScriptData(); + scriptData.setData(paramMap); + scriptData.setKey(scriptKey); + scriptData.setType(scriptEntity.map(ScriptEntityData::getType).getOrNull()); + scriptData.setProcedureKey(procedureKey); + ScriptUtil.setData(scriptData); + return runScript(script); + } + + public Map runAfterScript(String scriptKey, String procedureKey, Map resultMap) { + if(scriptKey == null || scriptKey.isEmpty()) { + return resultMap; + } + Script script = getScript(scriptKey); + if (script == null) { + return resultMap; + } + Option scriptEntity = getScriptEntity(scriptKey); + ScriptUtil.ScriptData scriptData = new ScriptUtil.ScriptData(); + scriptData.setData(resultMap); + scriptData.setKey(scriptKey); + scriptData.setType(scriptEntity.map(ScriptEntityData::getType).getOrNull()); + scriptData.setProcedureKey(procedureKey); + ScriptUtil.setData(scriptData); + return runScript(script); + } + + private Option getScriptEntity(String key) { + try { + if(useCache) { + return scriptDataCache.get(key, () -> Option.of(scriptMapper.getScript(key))); + } + return Option.of(scriptMapper.getScript(key)); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + private Script getScript(String key) { + try { + //如果key在数据库中查不到,则清除编译后的script + + Option scriptEntityData = getScriptEntity(key); + if(useCache) { + if (scriptEntityData.isEmpty()) { + Option> ifPresent = scriptCache.getIfPresent(key); + if (ifPresent != null) { + scriptCache.invalidate(key); + } + return null; + } + Option> scriptT2 = scriptCache.get(key, () -> { + String scriptStr = scriptEntityData.get().getScript(); + scriptStr = SCRIPT_IMPORT + scriptStr; + Script parse = groovyShell.parse(scriptStr); + return Option.of(Tuple.of(scriptEntityData.get().getKey(), parse)); + }); + return scriptT2.map(t2 -> t2._2).getOrNull(); + } + String scriptStr = scriptEntityData.get().getScript(); + scriptStr = SCRIPT_IMPORT + scriptStr; + return groovyShell.parse(scriptStr); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + private Map runScript(Script script) { + try { + return (Map) script.run(); + } catch (Throwable e) { + throw e; + } finally { + ScriptUtil.clear(); + } + } +} diff --git a/src/main/java/com/athis/tech/athisserver/service/engine/ScriptUtil.java b/src/main/java/com/athis/tech/athisserver/service/engine/ScriptUtil.java new file mode 100644 index 0000000..477afe1 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/service/engine/ScriptUtil.java @@ -0,0 +1,60 @@ +package com.athis.tech.athisserver.service.engine; + +import lombok.Getter; +import lombok.Setter; +import oracle.jdbc.internal.OracleCallableStatement; + +import java.sql.*; +import java.util.Map; + +import static java.sql.JDBCType.*; + +public class ScriptUtil { + private static final ThreadLocal threadLocal = new ThreadLocal<>(); + + public static ScriptData getData() { + return threadLocal.get(); + } + + public static void setData(ScriptData scriptData) { + threadLocal.set(scriptData); + } + + public static void clear() { + threadLocal.remove(); + } + + @Getter + @Setter + public static class ScriptData { + private String key; + private String type; + private String procedureKey; + private Map data; + } + + public static void main(String[] args) { + try { + Class.forName("oracle.jdbc.driver.OracleDriver"); + Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@47.111.224.22:1521:athis", "athis", "jsjzxabc"); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("select a,b from (select 2001 a,2001 b from dual)"); + OracleCallableStatement callableStatement = (OracleCallableStatement) connection.prepareCall("{call FRAME.yhjsbc(?,?,?,?)}"); +// callableStatement.setCursor(1,resultSet); + callableStatement.setObject(1, resultSet); + callableStatement.registerOutParameter(2, INTEGER); + callableStatement.registerOutParameter(3, VARCHAR); + callableStatement.registerOutParameter(4, REF); + +// ResultSet cursor = (ResultSet) callableStatement.getObject(4); +// while (cursor.next()) { +// System.out.println(cursor.getObject(1)); +// System.out.println(cursor.getObject(2)); +// } + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/athis/tech/athisserver/service/exception/NotFoundException.java b/src/main/java/com/athis/tech/athisserver/service/exception/NotFoundException.java new file mode 100644 index 0000000..54ba99e --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/service/exception/NotFoundException.java @@ -0,0 +1,12 @@ +package com.athis.tech.athisserver.service.exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } + + @Override + public String getMessage() { + return super.getMessage(); + } +} diff --git a/src/main/java/com/athis/tech/athisserver/service/exception/ServiceException.java b/src/main/java/com/athis/tech/athisserver/service/exception/ServiceException.java new file mode 100644 index 0000000..3694f78 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/service/exception/ServiceException.java @@ -0,0 +1,15 @@ +package com.athis.tech.athisserver.service.exception; + +import lombok.Getter; + +@Getter +public class ServiceException extends RuntimeException { + private String errCode; + private String errMessage; + + public ServiceException(String code,String msg) { + super(msg); + this.errCode = code; + this.errMessage = msg; + } +} diff --git a/src/main/java/com/athis/tech/athisserver/service/token/Md5Util.java b/src/main/java/com/athis/tech/athisserver/service/token/Md5Util.java new file mode 100644 index 0000000..4c305a7 --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/service/token/Md5Util.java @@ -0,0 +1,17 @@ +package com.athis.tech.athisserver.service.token; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Md5Util { + public static String getMd5ByString(String str) throws NoSuchAlgorithmException { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(str.getBytes()); + byte[] digest = md.digest(); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02x", b & 0xff)); + } + return sb.toString(); + } +} diff --git a/src/main/java/com/athis/tech/athisserver/service/token/TokenService.java b/src/main/java/com/athis/tech/athisserver/service/token/TokenService.java new file mode 100644 index 0000000..ee2e39a --- /dev/null +++ b/src/main/java/com/athis/tech/athisserver/service/token/TokenService.java @@ -0,0 +1,116 @@ +package com.athis.tech.athisserver.service.token; + +import com.athis.tech.athisserver.controller.login.LoginReq; +import com.athis.tech.athisserver.mybatis.mapper.TokenMapper; +import com.athis.tech.athisserver.mybatis.mapper.entity.TokenEntityData; +import com.athis.tech.athisserver.service.engine.ProcedureEngineService; +import com.athis.tech.athisserver.service.exception.ServiceException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.security.NoSuchAlgorithmException; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Component +public class TokenService { + @Autowired + private TokenMapper tokenMapper; + @Autowired + private ProcedureEngineService procedureEngineService; + @Value("${athis.login.expiration}") + private Long expiration; + + public boolean checkUsing(String yhid) { + Map paramMap = new LinkedHashMap<>(); + paramMap.put("yhid", yhid); + paramMap.put("csdm", "SYS_USER_MODE"); + Map stringObjectMap = procedureEngineService.runProcedure("xtcs", paramMap, false); + Object o = stringObjectMap.get("csz"); + if (o != null && o.toString().equals("Y")) { + return false; + } + Integer tokenCountByUser = tokenMapper.getTokenCountByUser(yhid); + return tokenCountByUser > 0; + } + + public TokenEntityData login(LoginReq loginReq) throws NoSuchAlgorithmException { + if (loginReq.getUsername() == null || loginReq.getUsername().isEmpty() || loginReq.getPassword() == null || loginReq.getPassword().isEmpty()) { + throw new ServiceException("errornull", "用户名 密码 不能为空"); + } + + if (loginReq.getJsid() == null || loginReq.getBmid() == null) { + throw new ServiceException("errornull", "部门 角色 必选"); + } + + checkPassword(loginReq); + + boolean b = checkUsing(loginReq.getUsername()); + List tokens = tokenMapper.getTokensByUser(loginReq.getUsername()); + if (b) { + for (TokenEntityData token : tokens) { + tokenMapper.deleteUserByToken(token.getToken()); + } + } else { + long now = System.currentTimeMillis(); + for (TokenEntityData token : tokens) { + if (token.getEndTime() >= now) { + continue; + } + tokenMapper.deleteUserByToken(token.getToken()); + } + } + + UUID uuid = UUID.randomUUID(); + double random = Math.random(); + String endStr = uuid + Md5Util.getMd5ByString(random + ""); + String newTokenStr = loginReq.getUsername() + "_" + endStr; + TokenEntityData tokenEntityData = new TokenEntityData(); + tokenEntityData.setToken(newTokenStr); + tokenEntityData.setBmid(loginReq.getBmid()); + tokenEntityData.setYhid(loginReq.getUsername()); + tokenEntityData.setJsid(loginReq.getJsid()); + tokenEntityData.setTokenFrom(loginReq.getTokenFrom()); + tokenEntityData.setEndTime(System.currentTimeMillis() + expiration); + tokenMapper.insertUserToken(tokenEntityData); + return tokenEntityData; + } + + public TokenEntityData checkToken(String token) { + TokenEntityData token1 = tokenMapper.getToken(token); + if(token1 == null) { + return null; + } + long now = System.currentTimeMillis(); + if(token1.getEndTime() >= now) { + tokenMapper.updateToken(token, now + expiration); + return token1; + } + return null; + } + + public void logout(String token) { + tokenMapper.deleteUserByToken(token); + } + + private void checkPassword(LoginReq loginReq) throws NoSuchAlgorithmException { + Map paramMap = new LinkedHashMap<>(); + paramMap.put("yhid", loginReq.getUsername()); + Map stringObjectMap = procedureEngineService.runProcedure("user-roles", paramMap, false); + Object o = stringObjectMap.get("paraCursor"); + String yhmm = null; + if (o != null && o instanceof List) { + List> list = (List>) o; + if (!list.isEmpty()) { + yhmm = list.get(0).get("YHMM").toString(); + } + } + String md5ByString = Md5Util.getMd5ByString(loginReq.getPassword()); + if (!md5ByString.equals(yhmm)) { + throw new ServiceException("errornull", "用户名或密码错误"); + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..6d07698 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,23 @@ +# 应用服务 WEB 访问端口 +server.port=8089 +#下面这些内容是为了让MyBatis映射 +#指定Mybatis的Mapper文件 +mybatis.mapper-locations=classpath:mappers/*.xml +#指定Mybatis的实体目录 +mybatis.type-aliases-package=com.athis.tech.athisserver.mybatis.mapper +mybatis.configuration.map-underscore-to-camel-case=true + +spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver +spring.datasource.url=jdbc:oracle:thin:@47.111.224.22:1521:athis +spring.datasource.password=jsjzxabc +spring.datasource.username=athis +spring.datasource.hikari.connection-init-sql=select 1 from dual +spring.datasource.hikari.maximum-pool-size=10 +spring.datasource.hikari.minimum-idle=10 +spring.datasource.hikari.connection-timeout=30000 +spring.datasource.hikari.max-lifetime=1800000 +spring.datasource.hikari.connection-test-query=select 1 from dual +spring.datasource.hikari.idle-timeout=600000 + +athis.engine.isCache=false +athis.login.expiration=7200000 \ No newline at end of file diff --git a/src/main/resources/mappers/ProcedureEngineMapper.xml b/src/main/resources/mappers/ProcedureEngineMapper.xml new file mode 100644 index 0000000..d5212c6 --- /dev/null +++ b/src/main/resources/mappers/ProcedureEngineMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/com/athis/tech/athisserver/AthisServerApplicationTests.java b/src/test/java/com/athis/tech/athisserver/AthisServerApplicationTests.java new file mode 100644 index 0000000..823d33b --- /dev/null +++ b/src/test/java/com/athis/tech/athisserver/AthisServerApplicationTests.java @@ -0,0 +1,13 @@ +package com.athis.tech.athisserver; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AthisServerApplicationTests { + + @Test + void contextLoads() { + } + +}