diff --git a/packages/toolkits/pro/README.md b/packages/toolkits/pro/README.md index 1d244445..0d1e7868 100644 --- a/packages/toolkits/pro/README.md +++ b/packages/toolkits/pro/README.md @@ -2,7 +2,47 @@ ## 说明 -tiny-toolkit-pro 套件,开箱即用的中后台前端/设计解决方案 +tiny-toolkit-pro 套件,开箱即用的全栈开发基础平台 + +## 准备工作 +### 数据库准备工作 +如果要对接服务端,请提前安装配置本地数据库服务或者云数据库服务,确保连接正常可用,可使用本地数据库或云数据库。 + +**本地数据库:** 本地数据库安装MySQL +- 查看本机操作系统,选择合适的安装包版本[下载MySQL](https://dev.mysql.com/downloads/) +- 安装完成MySQL软件 +- 进行初始化配置,设置端口、用户、登录密码等,测试连接正常 + +**云数据库:** 云数据库推荐使用[华为云数据库RDS](https://support.huaweicloud.com/productdesc-rds/zh-cn_topic_dashboard.html) +- 注册华为帐号并开通华为云 +- 选择合适的计费模式购买并配置数据库实例 +- 选择合适的连接模式进行连接 +具体开通过程请参考:[RDS for MySQL快速入门](https://support.huaweicloud.com/qs-rds/rds_02_0008.html),也可使用TinyCLI云服务插件以命令行的方式开通创建,具体请参考:[TinyCLI 云服务插件](https://opentiny.design/vue-pro/docs/advanced/plugin) + +### Egg.js准备工作 +Egg.js 是一个Node.js服务端框架,开发环境准备好Node、Git等即可,[参考指南](https://www.eggjs.org/zh-CN/intro/quickstart) + +### Spring Cloud准备工作 +如选择对接Spring Cloud,需要提前安装好JDK、IDE、Maven、配置好环境变量等 +#### Java环境安装 +1. [下载JDK](https://www.oracle.com/java/technologies/downloads/) +2. [配置环境变量](https://www.runoob.com/java/java-environment-setup.html) +#### IDE安装 +建议安装使用 [IntelliJ IDEA](https://www.jetbrains.com/idea/),内置Maven,[下载链接](https://www.jetbrains.com/zh-cn/idea/download/) + +#### Maven安装 +tiny-toolkit-pro 套件中的 Spring Cloud 采用 Maven 构建项目和依赖管理 +1. [下载链接](https://maven.apache.org/download.cgi) +2. [环境配置](https://www.runoob.com/maven/maven-setup.html) + +#### 微服务引擎 +有两种方式可供选择: + + * 通过下载安装本地简化版 CSE 搭建本地开发环境,下载链接:[CSE 2.0](https://support.huaweicloud.com/devg-cse/cse_devg_0036.html),下载完成,一键启动cse.exe + + * 使用[华为云微服务引擎(CSE)](https://support.huaweicloud.com/qs-cse/cse_qs_0002.html) + +#### ## 用法 @@ -25,11 +65,12 @@ tiny init pro angular ``` ### 选择服务端技术栈(可选配置) -**目前仅 `Vue`工程支持对接服务端,且只支持`Egg.js`,剩余功能正在开发中。** +**目前仅 `Vue`工程支持对接服务端,剩余功能正在开发中。** 如果选择不对接服务端,全部接口将采用mock数据。 ``` ? 请选择您希望使用的服务端技术栈: (Use arrow keys) > Egg.js + Spring Cloud 暂不配置 ``` ### 选择数据库(可选配置) @@ -38,21 +79,6 @@ tiny init pro > mySQL 暂不配置 ``` -### 数据库准备工作 -可使用本地数据库或云数据库,请提前安装配置本地数据库服务或者云数据库服务,确保连接正常可用。 - -**本地数据库:** 本地数据库安装MySQL -- 查看本机操作系统,选择合适的安装包版本[下载MySQL](https://dev.mysql.com/downloads/) -- 安装完成MySQL软件 -- 进行初始化配置,设置端口、用户、登录密码等,测试连接正常 - -**云数据库:** 云数据库推荐使用[华为云数据库RDS](https://support.huaweicloud.com/productdesc-rds/zh-cn_topic_dashboard.html) -- 注册华为帐号并开通华为云 -- 选择合适的计费模式购买并配置数据库实例 -- 选择合适的连接模式进行连接 -具体开通过程请参考:[RDS for MySQL快速入门](https://support.huaweicloud.com/qs-rds/rds_02_0008.html),也可使用TinyCLI云服务插件以命令行的方式开通创建,具体请参考:[TinyCLI 云服务插件](https://opentiny.design/vue-pro/docs/advanced/plugin) - - ### 配置数据库信息 **初始化过程中会自动创建数据库和表,建议输入新的数据库名称以免造成数据库覆盖风险!** @@ -77,14 +103,32 @@ tiny init pro ``` cd web && npm run start ``` -后端 +后端 +* EggJS ``` cd server && npm run dev ``` +* Spring Cloud + * 直接使用IDEA一键启动所有服务(推荐) + * 使用 ```mvn``` 命令 + ``` + // 进入对应目录下 + mvn spring-boot:run + ``` + * 使用 ```java -jar ``` 命令 + ``` + // 使用IDEA或者mvn进行打包 + mvn clean package + + // 进入对应 target 目录下 + java -jar packagename.jar + ``` ### 构建部署 前端:Vue项目采用Vite工具构建,请参考[Vite 部署指南](https://cn.vitejs.dev/guide/static-deploy.html)、[Vite 生产环境指南](https://cn.vitejs.dev/guide/build.html) -后端:Egg项目请参考[Egg构建部署指南](https://www.eggjs.org/zh-CN/core/deployment) +后端: +* EggJS项目请参考[Egg构建部署指南](https://www.eggjs.org/zh-CN/core/deployment) +* Spring Cloud请参考[CSE部署微服务应用](https://support.huaweicloud.com/intl/zh-cn/devg-cse/cse_devg_0016.html) ## 维护者 diff --git a/packages/toolkits/pro/src/lib/init.ts b/packages/toolkits/pro/src/lib/init.ts index e3b1a45e..c1a73492 100644 --- a/packages/toolkits/pro/src/lib/init.ts +++ b/packages/toolkits/pro/src/lib/init.ts @@ -51,6 +51,7 @@ const getProjectInfo = (): Promise => { message: '请选择您希望使用的服务端技术栈:', choices: [ { name: 'Egg.js', value: ServerFrameworks.EggJs }, + { name: 'Spring Cloud', value: ServerFrameworks.SpringCloud }, { name: '暂不配置', value: ServerFrameworks.Skip }, ], default: ServerFrameworks.Skip, @@ -67,7 +68,7 @@ const getProjectInfo = (): Promise => { { name: '暂不配置服务端', value: false }, ], prefix: '*', - when: (answers) => answers.serverFramework === ServerFrameworks.EggJs, + when: (answers) => answers.serverFramework !== ServerFrameworks.Skip, }, { type: 'list', @@ -129,7 +130,16 @@ const getProjectInfo = (): Promise => { * @answers 询问客户端问题的选择值 */ const createDatabase = async (answers: ProjectInfo) => { - const { name, dialect, host, port, database, username, password } = answers; + const { + name, + dialect, + host, + port, + database, + username, + password, + serverFramework, + } = answers; if (!dialect) return; log.info('开始连接数据库服务...'); @@ -150,8 +160,22 @@ const createDatabase = async (answers: ProjectInfo) => { await connection.query(` USE ${database}`); // 读取sql文件、新建表 - const serverPath = utils.getDistPath(`${name}/server`); - const databaseSqlDir = path.join(serverPath, 'app', 'database'); + const serverPath = utils.getDistPath(`${name}/${serverFramework}`); + let databaseSqlDir = ''; + switch (serverFramework) { + case ServerFrameworks.EggJs: + databaseSqlDir = path.join(serverPath, 'app/database'); + break; + case ServerFrameworks.SpringCloud: + databaseSqlDir = path.join( + serverPath, + 'server/src/main/resources/database' + ); + break; + default: + break; + } + const tableSqlDirPath = path.join(databaseSqlDir, 'table'); const files = fs.readdirSync(tableSqlDirPath); for (const file of files) { @@ -184,7 +208,7 @@ const createServerSync = (answers: ProjectInfo) => { const { name, serverFramework, dialect } = answers; // 复制服务端相关目录 const serverFrom = utils.getTemplatePath(`server/${serverFramework}`); - const serverTo = utils.getDistPath(`${name}/server`); + const serverTo = utils.getDistPath(`${name}/${serverFramework}`); const defaultConfig = { // 在未配置数据库信息时,使用默认值替换ejs模板 dialect: 'mysql', @@ -197,6 +221,7 @@ const createServerSync = (answers: ProjectInfo) => { fs.copyTpl(serverFrom, serverTo, dialect ? answers : defaultConfig, { overwrite: true, + notTextFile: ['.jar'], }); }; @@ -260,7 +285,7 @@ export const installDependencies = (answers: ProjectInfo) => { if (serverConfirm && serverFramework === ServerFrameworks.EggJs) { log.info('正在安装服务端 npm 依赖,安装过程需要几十秒,请耐心等待...'); spawn.sync('npm', ['install'], { - cwd: `${name}/server/`, + cwd: `${name}/${serverFramework}/`, stdio: 'inherit', }); log.success('服务端 npm 依赖安装成功'); @@ -291,7 +316,7 @@ export const installDependencies = (answers: ProjectInfo) => { console.log( chalk.green( `${chalk.yellow( - `$ cd ${name}/server && npm run dev` + `$ cd ${name}/${serverFramework} && npm run dev` )} # 开启server开发环境` ) ); diff --git a/packages/toolkits/pro/template/server/springCloud/gateway/.gitignore b/packages/toolkits/pro/template/server/springCloud/.gitignore similarity index 77% rename from packages/toolkits/pro/template/server/springCloud/gateway/.gitignore rename to packages/toolkits/pro/template/server/springCloud/.gitignore index 549e00a2..4f6ab7a5 100644 --- a/packages/toolkits/pro/template/server/springCloud/gateway/.gitignore +++ b/packages/toolkits/pro/template/server/springCloud/.gitignore @@ -1,8 +1,4 @@ -HELP.md target/ -!.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ ### STS ### .apt_generated diff --git a/packages/toolkits/pro/template/server/springCloud/.idea/.gitignore b/packages/toolkits/pro/template/server/springCloud/.idea/.gitignore deleted file mode 100644 index 73f69e09..00000000 --- a/packages/toolkits/pro/template/server/springCloud/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/packages/toolkits/pro/template/server/springCloud/.idea/compiler.xml b/packages/toolkits/pro/template/server/springCloud/.idea/compiler.xml index a0006bb7..4fd18c7c 100644 --- a/packages/toolkits/pro/template/server/springCloud/.idea/compiler.xml +++ b/packages/toolkits/pro/template/server/springCloud/.idea/compiler.xml @@ -2,6 +2,7 @@ + diff --git a/packages/toolkits/pro/template/server/springCloud/.idea/jarRepositories.xml b/packages/toolkits/pro/template/server/springCloud/.idea/jarRepositories.xml index 176ae5d9..0b140cdd 100644 --- a/packages/toolkits/pro/template/server/springCloud/.idea/jarRepositories.xml +++ b/packages/toolkits/pro/template/server/springCloud/.idea/jarRepositories.xml @@ -4,12 +4,12 @@ - + + + + + + + + - - - - - - \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/springCloud/gateway/pom.xml b/packages/toolkits/pro/template/server/springCloud/gateway/pom.xml index cd258ba6..23cc3182 100644 --- a/packages/toolkits/pro/template/server/springCloud/gateway/pom.xml +++ b/packages/toolkits/pro/template/server/springCloud/gateway/pom.xml @@ -24,6 +24,10 @@ com.huaweicloud spring-cloud-starter-huawei-service-engine-gateway + + io.jsonwebtoken + jjwt + diff --git a/packages/toolkits/pro/template/server/springCloud/gateway/src/main/java/com/huawei/tiny/gateway/config/AuthorizeFilter.java b/packages/toolkits/pro/template/server/springCloud/gateway/src/main/java/com/huawei/tiny/gateway/config/AuthorizeFilter.java new file mode 100644 index 00000000..751fa9a6 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/gateway/src/main/java/com/huawei/tiny/gateway/config/AuthorizeFilter.java @@ -0,0 +1,74 @@ +package com.huawei.tiny.gateway.config; + +import io.jsonwebtoken.*; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.util.Arrays; + +@Component +public class AuthorizeFilter implements GlobalFilter, Ordered { + + private String[] skipAuthUrl = { + "/v1/user/login", + "/v1/user/register" + }; + + private static final String TOKEN_ENCRYPT_KEY = "tiny_pro_server"; + + private static final String TOKEN_PREFIX = "Bearer "; + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + // 获取请求对象和响应对象 + ServerHttpRequest request = exchange.getRequest(); + ServerHttpResponse response = exchange.getResponse(); + + // 获取请求地址 + String url = request.getURI().getPath(); + + // 如果在跳过列表里,则不进行鉴定 + if (skipAuthUrl != null && (Arrays.asList(skipAuthUrl).contains(url))) { + //放行 + return chain.filter(exchange); + } + + // 获取当前用户的请求头jwt信息 + HttpHeaders headers = request.getHeaders(); + String token = headers.getFirst("Authorization").replace(TOKEN_PREFIX, ""); + + // 判断当前令牌是否存在 + if (StringUtils.isEmpty(token)) { + //如果不存在,向客户端返回错误提示信息 + response.setStatusCode(HttpStatus.UNAUTHORIZED); + return response.setComplete(); + } + + try { + // 验证token + Jwts.parser().setSigningKey(TOKEN_ENCRYPT_KEY).parseClaimsJws(token); + } catch (Exception e) { + e.printStackTrace(); + // token失效 + response.setStatusCode(HttpStatus.UNAUTHORIZED); + return response.setComplete(); + } + // 放行 + return chain.filter(exchange); + } + + + @Override + public int getOrder() { + return 0; + } +} diff --git a/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/application.yaml b/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/application.yaml index 8e686c06..7960a545 100644 --- a/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/application.yaml +++ b/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/application.yaml @@ -6,7 +6,7 @@ spring: - id: server uri: lb://tiny-server predicates: - - Path=/v1/employee/** + - Path=/v1/** httpclient: diff --git a/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/bootstrap.yml b/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/bootstrap.yml index 3a831bc0..db49ca7f 100644 --- a/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/bootstrap.yml +++ b/packages/toolkits/pro/template/server/springCloud/gateway/src/main/resources/bootstrap.yml @@ -1,5 +1,5 @@ server: - port: 9090 + port: 7001 spring: application: diff --git a/packages/toolkits/pro/template/server/springCloud/pom.xml b/packages/toolkits/pro/template/server/springCloud/pom.xml index 0360a7b0..fe725031 100644 --- a/packages/toolkits/pro/template/server/springCloud/pom.xml +++ b/packages/toolkits/pro/template/server/springCloud/pom.xml @@ -2,66 +2,72 @@ - 4.0.0 + 4.0.0 - com.huaweicloud - tiny - 1.0-SNAPSHOT - pom + com.huaweicloud + tiny + 1.0-SNAPSHOT + pom - - 2021.0.5 - 2.7.10 - 1.10.13-2021.0.x - + + 2021.0.5 + 2.7.10 + 1.10.13-2021.0.x + - - - - com.huaweicloud - spring-cloud-huawei-dependencies - ${spring-cloud-huawei.version} - pom - import - - - + + + + com.huaweicloud + spring-cloud-huawei-dependencies + ${spring-cloud-huawei.version} + pom + import + + + io.jsonwebtoken + jjwt + 0.9.1 + compile + + + - - gateway - server - + + gateway + server + - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - -parameters - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - ${main.class} - - - - - - - + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + -parameters + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + ${main.class} + + + + + + + diff --git a/packages/toolkits/pro/template/server/springCloud/server/pom.xml b/packages/toolkits/pro/template/server/springCloud/server/pom.xml index 8cd3d23a..874ce9fc 100644 --- a/packages/toolkits/pro/template/server/springCloud/server/pom.xml +++ b/packages/toolkits/pro/template/server/springCloud/server/pom.xml @@ -90,6 +90,14 @@ hibernate-core 5.6.7.Final + + org.springframework.boot + spring-boot-starter-validation + + + io.jsonwebtoken + jjwt + diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/ServerApplication.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/ServerApplication.java index 56408df0..3d4d064e 100644 --- a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/ServerApplication.java +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/ServerApplication.java @@ -2,11 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.ImportResource; -@SpringBootApplication +@SpringBootApplication(exclude = TransactionAutoConfiguration.class) @EnableDiscoveryClient @EnableFeignClients @ImportResource("classpath:META-INF/spring/server.bean.xml") diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/controller/UserController.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/controller/UserController.java new file mode 100644 index 00000000..29c191f4 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/controller/UserController.java @@ -0,0 +1,171 @@ +package com.huawei.tiny.server.controller; + +import com.huawei.tiny.server.dao.RegisterUser; +import com.huawei.tiny.server.dao.UserInfo; +import com.huawei.tiny.server.service.UserService; +import com.huawei.tiny.server.service.impl.UserServiceImpl; +import com.huawei.tiny.server.util.Group; +import com.huawei.tiny.server.util.JWTUtil; +import com.huawei.tiny.server.util.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.bcrypt.BCrypt; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.TransactionAspectSupport; +import org.springframework.validation.Errors; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.groups.Default; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping(path = "/v1/user", produces = MediaType.APPLICATION_JSON_VALUE) +public class UserController { + private final UserService userService; + private static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); + + @Autowired + public UserController(UserService userService) { + this.userService = userService; + } + + /** + * 注册 + * + * @param registerUser + * @return + */ + @Transactional(rollbackFor = Exception.class) + @PostMapping(path = "/register", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity register(@Validated({Group.Register.class, Default.class}) @RequestBody RegisterUser registerUser, Errors errors) { + UserInfo resultMap = new UserInfo(); + try { + // 入参校验错误 + if (errors.hasErrors()) { + return Result.error("InvalidParameter"); + } + + // 判断用户是否已经存在 + RegisterUser user = userService.getRegisterUserByName(registerUser.getUsername()); + if (user != null) { + return Result.error("UserAlreadyExist"); + } + + String hashed = BCrypt.hashpw(registerUser.getPassword(), BCrypt.gensalt(10)); + registerUser.setPassword(hashed); + userService.createUser(registerUser); + resultMap.setUserId(registerUser.getId()); + resultMap.setUsername(registerUser.getUsername()); + userService.createUserInfo(resultMap); + return Result.success(resultMap); + } catch (Exception e) { + e.printStackTrace(); + // 回滚事务 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return Result.error("InternalError"); + } + } + + /** + * 登录 + * + * @param registerUser + * @return + */ + @PostMapping(path = "/login", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity login(@Validated({Group.Login.class, Default.class}) @RequestBody RegisterUser registerUser, Errors errors) { + try { + // 入参校验错误 + if (errors.hasErrors()) { + return Result.error("InvalidParameter"); + } + + // 判断用户是否已经存在 + RegisterUser user = userService.getRegisterUserByName(registerUser.getUsername()); + if (user == null) { + return Result.error("UserNotFound"); + } + + // 密码是否正确 + boolean matched = BCrypt.checkpw(registerUser.getPassword(), user.getPassword()); + if (!matched) { + return Result.error("ErrorPassword"); + } + UserInfo userInfo = userService.getUserInfoById(user.getId()); + JWTUtil.getToken(userInfo); + String token = JWTUtil.getToken(userInfo); + Map resultMap = new HashMap(); + resultMap.put("token", token); + resultMap.put("userInfo", userInfo); + return Result.success(resultMap); + } catch (Exception e) { + e.printStackTrace(); + return Result.error("InternalError"); + } + } + + /** + * 更新用户信息 + * + * @param userInfo + * @return + */ + @PutMapping(path = "/userInfo", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity updateUserInfo(@RequestBody UserInfo userInfo, HttpServletRequest request) { + try { + if (userInfo.getUserId() == null) { + String token = request.getHeader("Authorization"); + UserInfo info = JWTUtil.parseToken(token); + userInfo.setUserId(info.getUserId()); + } + + userService.updateUserInfo(userInfo); + UserInfo result = userService.getUserInfoById(userInfo.getUserId()); + return Result.success(result); + } catch (Exception e) { + e.printStackTrace(); + return Result.error("InternalError"); + } + } + + /** + * 获取指定userid用户信息 + * + * @param userId + * @return + */ + @GetMapping(path = "/userInfo/{userId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getUserInfo(@PathVariable("userId") Long userId) { + try { + UserInfo result = userService.getUserInfoById(userId); + return Result.success(result); + } catch (Exception e) { + e.printStackTrace(); + return Result.error("InternalError"); + } + } + + /** + * 获取当前用户信息 + * + * @return + */ + @GetMapping(path = "/userInfo", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getUserInfo(HttpServletRequest request) { + try { + String token = request.getHeader("Authorization"); + UserInfo userInfo = JWTUtil.parseToken(token); + UserInfo result = userService.getUserInfoById(userInfo.getUserId()); + return Result.success(result); + } catch (Exception e) { + e.printStackTrace(); + return Result.error("InternalError"); + } + } +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/RegisterUser.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/RegisterUser.java new file mode 100644 index 00000000..f2a23e41 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/RegisterUser.java @@ -0,0 +1,53 @@ +package com.huawei.tiny.server.dao; + +import com.huawei.tiny.server.util.Group; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +public class RegisterUser { + + private Long id; + + @Email(message = "邮箱格式错误") + private String username; + + @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$", message = "密码格式错误", groups = Group.Register.class) + @NotEmpty(groups = Group.Login.class) + private String password; + + private String registerType; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getRegisterType() { + return registerType; + } + + public void setRegisterType(String registerType) { + this.registerType = registerType; + } +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/RegisterUserMapper.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/RegisterUserMapper.java new file mode 100644 index 00000000..48ff1189 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/RegisterUserMapper.java @@ -0,0 +1,8 @@ +package com.huawei.tiny.server.dao; + +public interface RegisterUserMapper { + + Long insert(RegisterUser registerUser); + + RegisterUser getRegisterUserByName(String name); +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/UserInfo.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/UserInfo.java new file mode 100644 index 00000000..65a167eb --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/UserInfo.java @@ -0,0 +1,155 @@ +package com.huawei.tiny.server.dao; + +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +public class UserInfo { + + private Long id; + + private String username; + + private Long userId; + + private String department; + + private String employeeType; + + private String job; + + private String role; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + private Date probationStart; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + private Date probationEnd; + + private String probationDuration; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + private Date protocolStart; + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + private Date protocolEnd; + + private String address; + + private String status; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } + + public String getEmployeeType() { + return employeeType; + } + + public void setEmployeeType(String employeeType) { + this.employeeType = employeeType; + } + + public String getJob() { + return job; + } + + public void setJob(String job) { + this.job = job; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public Date getProbationStart() { + return probationStart; + } + + public void setProbationStart(Date probationStart) { + this.probationStart = probationStart; + } + + public Date getProbationEnd() { + return probationEnd; + } + + public void setProbationEnd(Date probationEnd) { + this.probationEnd = probationEnd; + } + + public String getProbationDuration() { + return probationDuration; + } + + public void setProbationDuration(String probationDuration) { + this.probationDuration = probationDuration; + } + + public Date getProtocolStart() { + return protocolStart; + } + + public void setProtocolStart(Date protocolStart) { + this.protocolStart = protocolStart; + } + + public Date getProtocolEnd() { + return protocolEnd; + } + + public void setProtocolEnd(Date protocolEnd) { + this.protocolEnd = protocolEnd; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} + + diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/UserInfoMapper.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/UserInfoMapper.java new file mode 100644 index 00000000..7303667c --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/dao/UserInfoMapper.java @@ -0,0 +1,9 @@ +package com.huawei.tiny.server.dao; + +public interface UserInfoMapper { + Long insert(UserInfo userInfo); + + Long update(UserInfo userInfo); + + UserInfo getUserInfoById(Long id); +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/service/UserService.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/service/UserService.java new file mode 100644 index 00000000..602d0f0e --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/service/UserService.java @@ -0,0 +1,16 @@ +package com.huawei.tiny.server.service; + +import com.huawei.tiny.server.dao.RegisterUser; +import com.huawei.tiny.server.dao.UserInfo; + +public interface UserService { + Long createUser(RegisterUser registerUser); + + RegisterUser getRegisterUserByName(String name); + + UserInfo getUserInfoById(Long id); + + Long createUserInfo(UserInfo userInfo); + + Long updateUserInfo(UserInfo userInfo); +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/service/impl/UserServiceImpl.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/service/impl/UserServiceImpl.java new file mode 100644 index 00000000..fcfdaf28 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/service/impl/UserServiceImpl.java @@ -0,0 +1,49 @@ +package com.huawei.tiny.server.service.impl; + +import com.huawei.tiny.server.dao.RegisterUser; +import com.huawei.tiny.server.dao.RegisterUserMapper; +import com.huawei.tiny.server.dao.UserInfo; +import com.huawei.tiny.server.dao.UserInfoMapper; +import com.huawei.tiny.server.service.UserService; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl implements UserService { + private static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); + + @Autowired + private RegisterUserMapper RegisterUserMapper; + + @Autowired + private UserInfoMapper UserInfoMapper; + + @Override + public Long createUser(RegisterUser registerUser) { + Long id = RegisterUserMapper.insert(registerUser); + return id; + } + + @Override + public RegisterUser getRegisterUserByName(String name) { + return RegisterUserMapper.getRegisterUserByName(name); + } + + @Override + public UserInfo getUserInfoById(Long id) { + return UserInfoMapper.getUserInfoById(id); + } + + @Override + public Long createUserInfo(UserInfo userInfo) { + return UserInfoMapper.insert(userInfo); + } + + @Override + public Long updateUserInfo(UserInfo userInfo) { + return UserInfoMapper.update(userInfo); + } +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/Group.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/Group.java new file mode 100644 index 00000000..725223e4 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/Group.java @@ -0,0 +1,14 @@ +package com.huawei.tiny.server.util; + +/** + * 验证分组 + * + */ +public class Group { + public interface Login{ + + } + public interface Register{ + + } +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/JWTUtil.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/JWTUtil.java new file mode 100644 index 00000000..9a786b6e --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/JWTUtil.java @@ -0,0 +1,73 @@ +package com.huawei.tiny.server.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.huawei.tiny.server.dao.UserInfo; +import io.jsonwebtoken.*; + +import java.util.*; + +public class JWTUtil { + + // TOKEN的有效期一天(S) + private static final int TOKEN_TIME_OUT = 3600; + // 加密KEY + private static final String TOKEN_ENCRYPT_KEY = "tiny_pro_server"; + // 最小刷新间隔(S) + private static ObjectMapper objectMapper = new ObjectMapper(); + + /** 生成token + * + * @param userInfo + * @return + */ + public static String getToken(UserInfo userInfo) { + Map claimMaps = new HashMap<>(); + claimMaps.put("id", userInfo.getUserId()); + long currentTime = System.currentTimeMillis(); + try { + return Jwts.builder() + .setId(UUID.randomUUID().toString()) + .setIssuedAt(new Date(currentTime)) //签发时间 + .setSubject(objectMapper.writeValueAsString(userInfo)) + .signWith(SignatureAlgorithm.HS256, TOKEN_ENCRYPT_KEY) //加密方式 + .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳 + .addClaims(claimMaps) //cla信息 + .compact(); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * 获取token中的claims信息 + * + * @param token + * @return + */ + private static Jws getJws(String token) { + return Jwts.parser() + .setSigningKey(TOKEN_ENCRYPT_KEY) + .parseClaimsJws(token); + } + + + /** + * 解析bearerToken中user信息 + * + * @param bearerToken + * @return + */ + public static UserInfo parseToken(String bearerToken) { + try { + String token = bearerToken.replace("Bearer ", ""); + String subject = getJws(token).getBody().getSubject(); + UserInfo userInfo = objectMapper.readValue(subject, UserInfo.class); + return userInfo; + } catch (ExpiredJwtException | JsonProcessingException e) { + return null; + } + } + +} + diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/Result.java b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/Result.java new file mode 100644 index 00000000..657ac5e4 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/java/com/huawei/tiny/server/util/Result.java @@ -0,0 +1,70 @@ +package com.huawei.tiny.server.util; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +/** + * 接口通用返回值数据结构 + * + * @param + */ +public class Result { + //错误码 + private String code; + //提示信息 + private String errMsg; + //数据 + private T data; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String msg) { + this.errMsg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public static ResponseEntity> success(T data) { + return success(data, ""); + } + + public static ResponseEntity> success(T data, String errMsg) { + Result result = new Result<>(); + result.setErrMsg(errMsg); + result.setCode("0"); + result.setData(data); + return ResponseEntity.ok(result); + } + + public static ResponseEntity> error(String code) { + return error(code, code); + } + + public static ResponseEntity> error(String code, String errMsg) { + return error(code, errMsg, null); + } + + public static ResponseEntity> error(String code, String errMsg, T data) { + Result result = new Result<>(); + result.setCode(code); + result.setErrMsg(errMsg); + result.setData(data); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result); + } +} diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/META-INF/spring/server.bean.xml b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/META-INF/spring/server.bean.xml index 8470458d..596d2344 100644 --- a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/META-INF/spring/server.bean.xml +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/META-INF/spring/server.bean.xml @@ -1,26 +1,58 @@ - - - - - - - - - - - - - - - - - + xmlns:tx="http://www.springframework.org/schema/tx" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/tx + http://www.springframework.org/schema/tx/spring-tx.xsd + +"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/RegisterUserMapper.xml b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/RegisterUserMapper.xml new file mode 100644 index 00000000..d5b254ca --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/RegisterUserMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + id, user_name, password, register_type + + + + insert into registerUser (user_name, password, register_type) + values ( #{username,jdbcType=VARCHAR},#{password,jdbcType=VARCHAR}, "email") + + + + + + diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/UserInfoMapper.xml b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/UserInfoMapper.xml new file mode 100644 index 00000000..f1794742 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/UserInfoMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + id, user_name, user_id, department, employee_type, job, role, probation_start, probation_end, probation_duration, protocol_start, protocol_end, address, status + + + + insert into userInfo (user_name, user_id, role) + values ( + #{username,jdbcType=VARCHAR}, #{userId,jdbcType=BIGINT}, "admin" + ) + + + + + UPDATE + userInfo + + user_name = #{username}, + user_id = #{userId}, + department = #{department}, + employee_type = #{employeeType}, + job = #{job}, + role = #{role}, + probation_start = #{probationStart}, + probation_end = #{probationEnd}, + probation_duration = #{probationDuration}, + protocol_start = #{protocolStart}, + protocol_end = #{protocolEnd}, + address = #{address}, + status = #{status}, + + WHERE + user_id = #{userId} + + + + + diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/mybatis-config.xml b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/mybatis-config.xml index cdfbb669..33f3f542 100644 --- a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/mybatis-config.xml +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/config/mybatis-config.xml @@ -5,6 +5,8 @@ + + diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/README.md b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/README.md new file mode 100644 index 00000000..4d13d815 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/README.md @@ -0,0 +1,5 @@ +# 关于数据库及表生成注意事项 + +**初始化数据库的时候建议直接使用sql语句** + +初始化新表时最好是将表对应的sql写到每个文件中 diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/createuser.sql b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/createuser.sql new file mode 100644 index 00000000..1be2fc5a --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/createuser.sql @@ -0,0 +1,30 @@ +INSERT INTO registeruser +VALUES ( + null, + 'admin@example.com', + '$2b$10$W2NoJWWldrv4ksIalH7po.4vsczt3TlP8SepiEVNEanXzYTIxnIVu', + 'email' + ); + +INSERT INTO userinfo +VALUES ( + null, + (SELECT id + FROM registeruser + WHERE + user_name = 'admin@example.com') + +, +'admin@example.com', +'Tiny-Vue-Pro', +'social recruitment', +'admin', +'2023-06-01', +'2023-09-30', +'90', +'2023-06-01', +'2026-06-01', +'beijing', +'1', +'Front end' +) \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/initdatabase.sql b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/initdatabase.sql new file mode 100644 index 00000000..e1940880 --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/initdatabase.sql @@ -0,0 +1,3 @@ +CREATE DATABASE tiny_server_test; + +USE tiny_server_test; diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/employee.sql b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/employee.sql new file mode 100644 index 00000000..f9bbfa3e --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/employee.sql @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS `employee`; + +CREATE TABLE + `employee` ( + `id` bigint(16) NOT NULL, + `name` varchar(20) DEFAULT NULL COMMENT '姓名', + `employee_no` varchar(50) DEFAULT NULL COMMENT '工号', + `department` varchar(50) DEFAULT NULL COMMENT '部门', + `department_level` varchar(50) DEFAULT NULL COMMENT '部门层级', + `status` varchar(10) DEFAULT NULL COMMENT '状态', + `workbench_name` varchar(50) DEFAULT NULL COMMENT '工作台名称', + `project` varchar(50) DEFAULT NULL COMMENT '赋能项目', + `type` varchar(50) DEFAULT NULL COMMENT '人员类型', + `address` varchar(50) DEFAULT NULL COMMENT '研究所', + `roles` varchar(50) DEFAULT NULL COMMENT '角色', + `last_update_user` varchar(50) DEFAULT NULL COMMENT '最后更新人', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE + ) ENGINE = InnoDB DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC; \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/registeruser.sql b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/registeruser.sql new file mode 100644 index 00000000..f423507b --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/registeruser.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS `registeruser`; +CREATE TABLE + `registeruser` ( + `id` bigint(50) unsigned NOT NULL AUTO_INCREMENT, + `user_name` varchar(20) NOT NULL COMMENT '用户名', + `password` varchar(60) NOT NULL COMMENT '密码', + `register_type` varchar(10) DEFAULT NULL COMMENT '注册类型', + PRIMARY KEY (`id`) + ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8; \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/userinfo.sql b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/userinfo.sql new file mode 100644 index 00000000..97ff504b --- /dev/null +++ b/packages/toolkits/pro/template/server/springCloud/server/src/main/resources/database/table/userinfo.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS `userinfo`; + +CREATE TABLE + `userinfo` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `user_id` bigint(20) unsigned DEFAULT NULL, + `user_name` varchar(32) NOT NULL COMMENT '用户名', + `department` varchar(32) NOT NULL DEFAULT '' COMMENT '部门', + `employee_type` varchar(32) DEFAULT NULL COMMENT '招聘类型', + `role` varchar(32) DEFAULT NULL COMMENT '角色', + `probation_start` date DEFAULT NULL COMMENT '试用期开始时间', + `probation_end` date DEFAULT NULL COMMENT '试用期结束时间', + `probation_duration` bigint(11) unsigned DEFAULT NULL COMMENT '试用期时长', + `protocol_start` date DEFAULT NULL COMMENT '合同开始日期', + `protocol_end` date DEFAULT NULL COMMENT '合同结束日期', + `address` varchar(32) DEFAULT NULL COMMENT '地址', + `status` varchar(32) DEFAULT NULL COMMENT '状态', + `job` varchar(32) DEFAULT NULL COMMENT '职位', + PRIMARY KEY (`id`) + ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8; \ No newline at end of file