diff --git a/build.gradle b/build.gradle index fc70e51..e71b684 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ configurations { } repositories { maven { url "http://maven.aliyun.com/nexus/content/groups/public/" } + maven { url "http://maven.aiprose.com/nexus/content/repositories/public/" } mavenCentral() } dependencies { @@ -48,6 +49,13 @@ dependencies { testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } + + implementation 'com.aiprose:utils:0.1.3' + implementation 'com.aiprose:jpa-common-utils:2.3.3' + compile group: 'com.alibaba', name: 'fastjson', version: '1.2.73' + + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.11' + compile group: 'io.springfox', name: 'springfox-boot-starter', version: '3.0.0' } test { useJUnitPlatform() diff --git a/src/main/java/com/aiprose/querydsl/QuerydslApplication.java b/src/main/java/com/aiprose/querydsl/QuerydslApplication.java index 754ec23..0c1e19f 100644 --- a/src/main/java/com/aiprose/querydsl/QuerydslApplication.java +++ b/src/main/java/com/aiprose/querydsl/QuerydslApplication.java @@ -1,8 +1,14 @@ package com.aiprose.querydsl; +import com.querydsl.jpa.impl.JPAQueryFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import springfox.documentation.oas.annotations.EnableOpenApi; +import javax.persistence.EntityManager; + +@EnableOpenApi @SpringBootApplication public class QuerydslApplication { @@ -10,4 +16,8 @@ public class QuerydslApplication { SpringApplication.run(QuerydslApplication.class, args); } + @Bean + public JPAQueryFactory jpaQueryFactory(EntityManager entityManager){ + return new JPAQueryFactory(entityManager); + } } diff --git a/src/main/java/com/aiprose/querydsl/config/DateConverter.java b/src/main/java/com/aiprose/querydsl/config/DateConverter.java new file mode 100644 index 0000000..1ad6434 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/config/DateConverter.java @@ -0,0 +1,31 @@ +package com.aiprose.querydsl.config; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +@Component +public class DateConverter implements Converter { + @Override + public Date convert(String source) { + if(StringUtils.isNoneBlank(source)){ + SimpleDateFormat dateFormat; + if(source.trim().length()<11){ + dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + }else{ + dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + } + dateFormat.setLenient(false); + try { + return dateFormat.parse(source); + } catch (ParseException e) { + e.printStackTrace(); + } + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/aiprose/querydsl/config/SwaggerConfiguration.java b/src/main/java/com/aiprose/querydsl/config/SwaggerConfiguration.java new file mode 100644 index 0000000..a2badf9 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/config/SwaggerConfiguration.java @@ -0,0 +1,52 @@ +package com.aiprose.querydsl.config; + +import com.google.common.collect.Lists; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.*; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; + +import java.util.List; + +@Configuration +public class SwaggerConfiguration { + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.OAS_30) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.aiprose.querydsl.controller")) + .paths(PathSelectors.any()) + .build() + .securityContexts(Lists.newArrayList(securityContext())).securitySchemes(Lists.newArrayList(new ApiKey("token", "token", "header"))); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("querydsl demo") + .description("springboot mybatis plus框架demo") + .contact(new Contact("nelson", "https://www.aiprose.com/", "mail_yanpeng@163.com")) + .version("1.0") + .build(); + } + + private SecurityContext securityContext() { + return SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex("/.*")) + .build(); + } + + List defaultAuth() { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + return Lists.newArrayList(new SecurityReference("token", authorizationScopes)); + } + +} diff --git a/src/main/java/com/aiprose/querydsl/config/TokenInterceptor.java b/src/main/java/com/aiprose/querydsl/config/TokenInterceptor.java new file mode 100644 index 0000000..1ba3c0c --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/config/TokenInterceptor.java @@ -0,0 +1,64 @@ +package com.aiprose.querydsl.config; + +import com.aiprose.querydsl.entity.Response; +import com.aiprose.utils.JwtUtil; +import com.alibaba.fastjson.JSON; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +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 org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +/** + * @version 1.0 + * @Auther: liuchao + * @company 北京中经网软件有限公司 + * @Date: 2020/9/15 + */ +@Component +public class TokenInterceptor implements WebFilter { + private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client"; + + @Autowired + private Response resp; + + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + ServerHttpResponse response = exchange.getResponse(); + if (request.getPath().value().contains("login") || request.getPath().value().contains("swagger") || request.getPath().value().contains("api-docs") || request.getPath().value().contains("regist")) { + return chain.filter(exchange); + } + String token = request.getHeaders().getFirst("token"); + if (request.getMethod() == HttpMethod.OPTIONS || StringUtils.isEmpty(token)) { + HttpHeaders headers = response.getHeaders(); + headers.add("Access-Control-Allow-Origin", "*"); + headers.add("Access-Control-Allow-Methods", "*"); + headers.add("Access-Control-Max-Age", "18000L"); + headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS); + headers.add("Access-Control-Expose-Headers", "*"); + headers.add("Access-Control-Allow-Credentials", "true"); + } + if (request.getMethod() == HttpMethod.OPTIONS) { + response.setStatusCode(HttpStatus.OK); + return Mono.empty(); + } + if (StringUtils.isEmpty(token)){ + return response.writeWith(Mono.just(response.bufferFactory().wrap(JSON.toJSON(resp.failure(HttpStatus.UNAUTHORIZED, "请先登录")).toString().getBytes()))); + } + try { + exchange.getAttributes().put("uid", JwtUtil.getUid(token)); + } catch (Exception e) { + return response.writeWith(Mono.just(response.bufferFactory().wrap(JSON.toJSON(resp.failure(HttpStatus.UNAUTHORIZED, "请先登录")).toString().getBytes()))); + } + return chain.filter(exchange); + } +} diff --git a/src/main/java/com/aiprose/querydsl/config/WebFluxConf.java b/src/main/java/com/aiprose/querydsl/config/WebFluxConf.java new file mode 100644 index 0000000..d64a3f2 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/config/WebFluxConf.java @@ -0,0 +1,27 @@ +package com.aiprose.querydsl.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.config.CorsRegistry; +import org.springframework.web.reactive.config.ResourceHandlerRegistry; +import org.springframework.web.reactive.config.WebFluxConfigurer; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/15 + */ +@Configuration +public class WebFluxConf implements WebFluxConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "DELETE").maxAge(3600); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/") + .resourceChain(false); + } +} diff --git a/src/main/java/com/aiprose/querydsl/controller/DeptController.java b/src/main/java/com/aiprose/querydsl/controller/DeptController.java new file mode 100644 index 0000000..138c3de --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/controller/DeptController.java @@ -0,0 +1,49 @@ +package com.aiprose.querydsl.controller; + +import com.aiprose.querydsl.entity.Dept; +import com.aiprose.querydsl.entity.Emp; +import com.aiprose.querydsl.entity.Response; +import com.aiprose.querydsl.service.DeptService; +import com.aiprose.querydsl.util.FixedPageData; +import com.aiprose.querydsl.vos.DeptTreeVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +@RestController +@RequestMapping("dept") +public class DeptController { + + @Autowired + private DeptService service; + + + @Autowired + private Response resp; + + @PostMapping("save") + public Mono save(@RequestBody Dept dept){ + Dept save = service.save(dept); + return Mono.just(resp.success(save)); + } + + @DeleteMapping("{id}") + public Mono delete(@PathVariable("id") Integer id){ + service.deleteById(id); + return Mono.just(resp.success()); + } + + @GetMapping("tree") + public Mono tree(){ + List tree= service.tree(); + return Mono.just(resp.success(tree)); + } +} diff --git a/src/main/java/com/aiprose/querydsl/controller/EmpController.java b/src/main/java/com/aiprose/querydsl/controller/EmpController.java new file mode 100644 index 0000000..f409ef0 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/controller/EmpController.java @@ -0,0 +1,51 @@ +package com.aiprose.querydsl.controller; + +import com.aiprose.querydsl.entity.Emp; +import com.aiprose.querydsl.service.EmpService; +import com.aiprose.querydsl.util.FixedPageData; +import com.aiprose.querydsl.vos.UserVo; +import com.aiprose.querydsl.entity.Response; +import com.aiprose.querydsl.entity.User; +import com.aiprose.querydsl.service.UserService; +import com.aiprose.utils.JwtUtil; +import com.aiprose.utils.MD5Encrypt; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.HashMap; +import java.util.Map; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +@RestController +public class EmpController { + + @Autowired + private EmpService service; + + @Autowired + private Response resp; + + @GetMapping("list") + public Mono list(@RequestParam Integer page, @RequestParam Integer size, Emp emp){ + FixedPageData pageData = service.list(page,size,emp); + return Mono.just(resp.page(pageData.getResults(),pageData.getTotal())); + } + + @PostMapping("save") + public Mono save(@RequestBody Emp emp){ + service.save(emp); + return Mono.just(resp.success()); + } + + @DeleteMapping("{id}") + public Mono delete(@PathVariable("id") Integer id){ + service.deleteById(id); + return Mono.just(resp.success()); + } +} diff --git a/src/main/java/com/aiprose/querydsl/controller/UserController.java b/src/main/java/com/aiprose/querydsl/controller/UserController.java index 557e2b2..8ca6f50 100644 --- a/src/main/java/com/aiprose/querydsl/controller/UserController.java +++ b/src/main/java/com/aiprose/querydsl/controller/UserController.java @@ -1,13 +1,18 @@ package com.aiprose.querydsl.controller; +import com.aiprose.querydsl.vos.UserVo; +import com.aiprose.querydsl.entity.Response; import com.aiprose.querydsl.entity.User; import com.aiprose.querydsl.service.UserService; +import com.aiprose.utils.JwtUtil; +import com.aiprose.utils.MD5Encrypt; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; +import java.util.HashMap; +import java.util.Map; + /** * @version 1.0 * @Auther: nelson @@ -18,17 +23,32 @@ import reactor.core.publisher.Mono; public class UserController { @Autowired - private UserService userService; + private UserService service; - @GetMapping("user/{username}") - public Mono getUser(@PathVariable("username") String username){ - User user = userService.findByUsername(username); - return Mono.just(user); + + @Autowired + private Response resp; + + @PostMapping("user/login") + public Mono getUser(@RequestBody UserVo user){ + User dbUser = service.findByUsername(user.getUsername()); + if(dbUser == null){ + return Mono.just(resp.failure("用户不存在")); + } + String pwd = MD5Encrypt.md5hash(user.getPassword(), dbUser.getSalt()); + if(!dbUser.getPassword().equals(pwd)){ + return Mono.just(resp.failure("用户名或者密码错误")); + } + Map map = new HashMap<>(); + map.put("id",dbUser.getId()); + map.put("username",dbUser.getUsername()); + String token = JwtUtil.createToken(map); + return Mono.just(resp.success(token,dbUser)); } - @GetMapping("user/save/{username}") + @GetMapping("user/regist/{username}") public Mono saveUser(@PathVariable("username") String username){ - User user = userService.save(username); + User user = service.save(username); return Mono.just(user); } } diff --git a/src/main/java/com/aiprose/querydsl/entity/Dept.java b/src/main/java/com/aiprose/querydsl/entity/Dept.java new file mode 100644 index 0000000..f0c9b54 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/entity/Dept.java @@ -0,0 +1,36 @@ +package com.aiprose.querydsl.entity; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.Date; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +@Data +@Entity +@Table(name = "tb_dept") +public class Dept extends IDEntity { + @Column(length = 10) + private String name; + + @Column(length = 30) + private String loc; //位置 + + @Column(columnDefinition = "INT UNSIGNED") + private Integer pid; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date cdate; //创建时间 +} diff --git a/src/main/java/com/aiprose/querydsl/entity/Emp.java b/src/main/java/com/aiprose/querydsl/entity/Emp.java new file mode 100644 index 0000000..f575d49 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/entity/Emp.java @@ -0,0 +1,35 @@ +package com.aiprose.querydsl.entity; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.Date; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +@Data +@Entity +@Table(name = "tb_emp") +public class Emp extends IDEntity { + @Column(nullable = false, length = 20) + private String empName; + + private Long mobile; + + @Column(columnDefinition = "INT UNSIGNED") + private Integer deptId; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date joindate; +} diff --git a/src/main/java/com/aiprose/querydsl/entity/IDEntity.java b/src/main/java/com/aiprose/querydsl/entity/IDEntity.java index 30c528b..adba37a 100644 --- a/src/main/java/com/aiprose/querydsl/entity/IDEntity.java +++ b/src/main/java/com/aiprose/querydsl/entity/IDEntity.java @@ -2,10 +2,7 @@ package com.aiprose.querydsl.entity; import lombok.Data; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; +import javax.persistence.*; import java.io.Serializable; /** @@ -21,6 +18,7 @@ public class IDEntity implements Serializable { * 主键 */ @Id + @Column(columnDefinition = "INT UNSIGNED") @GeneratedValue(strategy = GenerationType.AUTO) - protected Long id; + protected Integer id; } diff --git a/src/main/java/com/aiprose/querydsl/entity/LDEntity.java b/src/main/java/com/aiprose/querydsl/entity/LDEntity.java new file mode 100644 index 0000000..2eac8c7 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/entity/LDEntity.java @@ -0,0 +1,26 @@ +package com.aiprose.querydsl.entity; + +import lombok.Data; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import java.io.Serializable; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +@Data +@MappedSuperclass +public class LDEntity implements Serializable { + /** + * 主键 + */ + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + protected Long id; +} diff --git a/src/main/java/com/aiprose/querydsl/entity/Response.java b/src/main/java/com/aiprose/querydsl/entity/Response.java new file mode 100644 index 0000000..073a331 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/entity/Response.java @@ -0,0 +1,198 @@ +package com.aiprose.querydsl.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import org.springframework.context.annotation.Scope; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; + +@Component +@Scope("prototype") +@SuppressWarnings(value = "all") +public class Response { + /** + * 默认成功响应码 + */ + private static final Integer DEAFAULT_SUCCESS_CODE = HttpStatus.OK.value(); + /** + * 默认成功响应信息 + */ + private static final String DEAFAULT_SUCCESS_MSG = "请求/处理成功!"; + /** + * 默认失败响应码 + */ + private static final Integer DEAFAULT_FAILURE_CODE = HttpStatus.INTERNAL_SERVER_ERROR.value(); + /** + * 默认失败响应信息 + */ + private static final String DEAFAULT_FAILURE_MSG = "请求/处理失败!"; + + @Getter + private Meta meta; + + @Getter + private Object data; + + @Getter + private Long total =0l; + + + /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓成功↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ + + public Response success() { + this.meta = new Meta(DEAFAULT_SUCCESS_CODE, DEAFAULT_SUCCESS_MSG); + this.data = null; + return this; + } + + + /** + * 处理成功响应,返回自定义响应码、信息和数据。 + * + * @param msg 处理结果信息 + * @return 响应对象 + */ + public Response success(String msg) { + this.meta = new Meta(DEAFAULT_SUCCESS_CODE, msg); + this.data = null; + return this; + } + + /** + * 处理成功响应,返回自定义响应码、信息和数据。 + * + * @param data 返回数据 + * @return 响应对象 + */ + public Response success(Object data) { + this.meta = new Meta(DEAFAULT_SUCCESS_CODE, DEAFAULT_SUCCESS_MSG); + this.data = data; + return this; + } + + /** + * 处理成功响应,返回自定义响应码、信息和数据。 + * + * @param msg 处理结果信息 + * @param data 返回数据 + * @return 响应对象 + */ + public Response success(String msg, Object data) { + this.meta = new Meta(DEAFAULT_SUCCESS_CODE, msg); + this.data = data; + return this; + } + + /** + * 分页数据为空 + * @return + */ + public Response page() { + this.meta = new Meta(DEAFAULT_SUCCESS_CODE, DEAFAULT_SUCCESS_MSG); + this.data = new ArrayList<>(); + this.total = 0l; + return this; + } + + /** + * 分页数据和总数量 + * @return + */ + public Response page(Object data,Long total) { + this.meta = new Meta(DEAFAULT_SUCCESS_CODE, DEAFAULT_SUCCESS_MSG); + this.data = data; + this.total = total; + return this; + } + + /** + * 处理成功响应,返回自定义响应码、信息和数据。 + * + * @param httpStatus HTTP 响应码 + * @param msg 处理结果信息 + * @param data 返回数据 + * @return 响应对象 + */ + public Response success(HttpStatus httpStatus, String msg, Object data) { + this.meta = new Meta(httpStatus.value(), msg); + this.data = data; + return this; + } + + + /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓失败↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ + + /** + * 处理失败响应,返回自定义响应码、信息和数据。 + * + * @param msg 处理结果信息 + * @return 响应对象 + */ + public Response failure(String msg) { + this.meta = new Meta(DEAFAULT_FAILURE_CODE, msg); + this.data = null; + return this; + } + + /** + * 处理失败响应,返回自定义响应码、信息和数据。 + * + * @param data 返回数据 + * @return 响应对象 + */ + public Response failure(Object data) { + this.meta = new Meta(DEAFAULT_FAILURE_CODE, DEAFAULT_FAILURE_MSG); + this.data = data; + return this; + } + + /** + * 处理失败响应,返回自定义响应码、信息和数据。 + * + * @param msg 处理结果信息 + * @param data 返回数据 + * @return 响应对象 + */ + public Response failure(String msg, Object data) { + this.meta = new Meta(DEAFAULT_FAILURE_CODE, msg); + this.data = data; + return this; + } + + /** + * 处理失败响应,返回自定义响应码、信息和数据。 + * + * @param httpStatus HTTP 响应码 + * @param msg 处理结果信息 + * @param data 返回数据 + * @return 响应对象 + */ + public Response failure(HttpStatus httpStatus, String msg, Object data) { + this.meta = new Meta(httpStatus.value(), msg); + this.data = data; + return this; + } + + public Response failure(HttpStatus httpStatus, String msg) { + this.meta = new Meta(httpStatus.value(), msg); + return this; + } + + @Data + @AllArgsConstructor + private class Meta { + + /** + * 处理结果代码,与 HTTP 状态响应码对应 + */ + private Integer code; + + /** + * 处理结果信息 + */ + private String msg; + } +} diff --git a/src/main/java/com/aiprose/querydsl/entity/User.java b/src/main/java/com/aiprose/querydsl/entity/User.java index 2cddc45..29447b9 100644 --- a/src/main/java/com/aiprose/querydsl/entity/User.java +++ b/src/main/java/com/aiprose/querydsl/entity/User.java @@ -1,8 +1,11 @@ package com.aiprose.querydsl.entity; +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import lombok.Getter; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @@ -14,7 +17,14 @@ import javax.persistence.Table; */ @Data @Entity -@Table(name="tb_user") -public class User extends IDEntity{ +@Table(name = "tb_user") +public class User extends IDEntity { + @Column(unique = true) private String username; + + @JsonIgnore + private String password; + @JsonIgnore + @JSONField(serialize = false) + private String salt; } diff --git a/src/main/java/com/aiprose/querydsl/repository/DeptRepository.java b/src/main/java/com/aiprose/querydsl/repository/DeptRepository.java new file mode 100644 index 0000000..18453c2 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/repository/DeptRepository.java @@ -0,0 +1,15 @@ +package com.aiprose.querydsl.repository; + +import com.aiprose.querydsl.entity.Dept; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +public interface DeptRepository extends JpaRepository, + QuerydslPredicateExecutor { +} diff --git a/src/main/java/com/aiprose/querydsl/repository/EmpRepository.java b/src/main/java/com/aiprose/querydsl/repository/EmpRepository.java new file mode 100644 index 0000000..f0c0544 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/repository/EmpRepository.java @@ -0,0 +1,16 @@ +package com.aiprose.querydsl.repository; + +import com.aiprose.querydsl.entity.Emp; +import com.aiprose.querydsl.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +public interface EmpRepository extends JpaRepository, + QuerydslPredicateExecutor{ +} diff --git a/src/main/java/com/aiprose/querydsl/repository/UserRepository.java b/src/main/java/com/aiprose/querydsl/repository/UserRepository.java index fe20899..53b4a8f 100644 --- a/src/main/java/com/aiprose/querydsl/repository/UserRepository.java +++ b/src/main/java/com/aiprose/querydsl/repository/UserRepository.java @@ -10,6 +10,6 @@ import org.springframework.data.querydsl.QuerydslPredicateExecutor; * @company 北京中经网软件有限公司 * @Date: 2020/9/14 */ -public interface UserRepository extends JpaRepository, +public interface UserRepository extends JpaRepository, QuerydslPredicateExecutor{ } diff --git a/src/main/java/com/aiprose/querydsl/service/DeptService.java b/src/main/java/com/aiprose/querydsl/service/DeptService.java new file mode 100644 index 0000000..b0cc5a8 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/service/DeptService.java @@ -0,0 +1,74 @@ +package com.aiprose.querydsl.service; + +import com.aiprose.base.BasicServiceImpl; +import com.aiprose.querydsl.entity.Dept; +import com.aiprose.querydsl.entity.QDept; +import com.aiprose.querydsl.entity.QUser; +import com.aiprose.querydsl.entity.User; +import com.aiprose.querydsl.repository.DeptRepository; +import com.aiprose.querydsl.repository.UserRepository; +import com.aiprose.querydsl.util.FixedPageData; +import com.aiprose.querydsl.vos.DeptTreeVo; +import com.aiprose.utils.MD5Encrypt; +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +@Transactional +@Service +public class DeptService extends BasicServiceImpl { + + @Autowired + private DeptRepository repository; + + @Autowired + private JPAQueryFactory queryFactory; + + @Override + public JpaRepository getJpaRepository() { + return repository; + } + + @Override + public JpaSpecificationExecutor getJpaSpecificationExecutor() { + return null; + } + + public List tree() { + QDept qDept = QDept.dept; + List collect = queryFactory.selectFrom(qDept).where(qDept.pid.isNull()).fetch().stream().map(x -> { + DeptTreeVo vo = new DeptTreeVo(); + BeanUtils.copyProperties(x, vo); + List childs = getChilds(qDept, x.getId()); + vo.setChild(childs); + return vo; + }).collect(Collectors.toList()); + return collect; + } + + private List getChilds(QDept qDept, Integer id) { + return queryFactory.selectFrom(qDept).where(qDept.pid.eq(id)).fetch().stream().map(x -> { + DeptTreeVo vo = new DeptTreeVo(); + BeanUtils.copyProperties(x, vo); + List childs = getChilds(qDept, x.getId()); + vo.setChild(childs); + return vo; + }).collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/aiprose/querydsl/service/EmpService.java b/src/main/java/com/aiprose/querydsl/service/EmpService.java new file mode 100644 index 0000000..afdab98 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/service/EmpService.java @@ -0,0 +1,71 @@ +package com.aiprose.querydsl.service; + +import com.aiprose.base.BasicServiceImpl; +import com.aiprose.querydsl.entity.Emp; +import com.aiprose.querydsl.entity.QEmp; +import com.aiprose.querydsl.repository.EmpRepository; +import com.aiprose.querydsl.util.FixedPageData; +import com.querydsl.core.QueryResults; +import com.querydsl.core.types.ExpressionUtils; +import com.querydsl.core.types.Predicate; +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/14 + */ +@Transactional +@Service +public class EmpService extends BasicServiceImpl { + + @Autowired + private JPAQueryFactory queryFactory; + + @Autowired + private EmpRepository repository; + + @Override + public JpaRepository getJpaRepository() { + return repository; + } + + @Override + public JpaSpecificationExecutor getJpaSpecificationExecutor() { + return null; + } + + public FixedPageData list(Integer page, Integer size, Emp emp) { + FixedPageData pageData = new FixedPageData(page, size); + QEmp qEmp = QEmp.emp; + Integer deptId = emp.getDeptId(); + String empName = emp.getEmpName(); + Long mobile = emp.getMobile(); + Predicate predicate = qEmp.isNotNull(); + if (StringUtils.isNotBlank(empName)) { + predicate = ExpressionUtils.and(predicate, qEmp.empName.eq(empName)); + } + if (deptId != null) { + predicate = ExpressionUtils.and(predicate, qEmp.deptId.eq(deptId)); + } + if (mobile != null) { + predicate = ExpressionUtils.and(predicate, qEmp.mobile.eq(mobile)); + } + QueryResults queryResults = queryFactory.selectFrom(qEmp).where(predicate).offset(pageData.getOffset()) + .limit(pageData.getSize()).fetchResults(); + pageData.setResults(queryResults.getResults()); + pageData.setTotal(queryResults.getTotal()); + return pageData; + } +} diff --git a/src/main/java/com/aiprose/querydsl/service/UserService.java b/src/main/java/com/aiprose/querydsl/service/UserService.java index 98ff594..eea3186 100644 --- a/src/main/java/com/aiprose/querydsl/service/UserService.java +++ b/src/main/java/com/aiprose/querydsl/service/UserService.java @@ -1,8 +1,11 @@ package com.aiprose.querydsl.service; +import com.aiprose.querydsl.entity.Emp; import com.aiprose.querydsl.entity.QUser; import com.aiprose.querydsl.entity.User; import com.aiprose.querydsl.repository.UserRepository; +import com.aiprose.querydsl.util.FixedPageData; +import com.aiprose.utils.MD5Encrypt; import com.querydsl.jpa.impl.JPAQueryFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -36,12 +39,22 @@ public class UserService { public User findByUsername(String username) { QUser qUser = QUser.user; - return queryFactory.select(qUser).from(qUser).where(qUser.username.eq(username)).fetchOne(); + try { + User user = queryFactory.select(qUser).from(qUser).where(qUser.username.eq(username)).fetchOne(); + return user; + }catch (Exception e){ + e.printStackTrace(); + } + return null; } public User save(String username) { User user = new User(); user.setUsername(username); + String salt = MD5Encrypt.generateSalt(); + String pwd = MD5Encrypt.md5hash("123456", salt); + user.setPassword(pwd); + user.setSalt(salt); repository.saveAndFlush(user); return user; } diff --git a/src/main/java/com/aiprose/querydsl/util/FixedPageData.java b/src/main/java/com/aiprose/querydsl/util/FixedPageData.java new file mode 100644 index 0000000..cadd1f1 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/util/FixedPageData.java @@ -0,0 +1,167 @@ +package com.aiprose.querydsl.util; + +import java.util.ArrayList; +import java.util.List; + +public class FixedPageData { + protected long total; + protected long offset; + protected long size; + protected long startIndex; + protected long endIndex; + protected long showIndex = 2L; + protected List results = new ArrayList(); + + protected FixedPageData() { + } + + public FixedPageData(long page, long size) { + this.setSize(size); + this.setOffset(page * size - size); + } + + public boolean isLastPage() { + return this.getActivePage() >= this.getPages(); + } + + public long getActivePage() { + if (this.total == 0L) { + return 1L; + } else if (this.size == 0L) { + return 1L; + } else { + long activePage = (this.offset + this.size) / this.size; + return activePage; + } + } + + public long getPages() { + if (this.total == 0L) { + return 1L; + } else if (this.total < this.size) { + return 1L; + } else { + long pages = this.total / this.size; + if (this.total % this.size != 0L) { + ++pages; + } + + return pages; + } + } + + public boolean isFirstPage() { + return this.getActivePage() == 1L; + } + + public long getAscNo(long index) { + long n = this.getOffset() + 1L; + return n + index; + } + + public long getOffset() { + return this.offset; + } + + public void setOffset(long offset) { + if (offset < 0L) { + this.offset = 0L; + } else if (this.size == 0L) { + this.offset = 0L; + } else { + this.offset = offset - offset % this.size; + } + + } + + public long getDescNo(long index) { + long n = this.getOffset() + 1L; + n = this.getTotal() + 1L - n; + return n - index; + } + + public long getTotal() { + return this.total; + } + + public void setTotal(long total) { + this.total = total; + if (this.offset >= total) { + long extra = total % this.size; + long lastStart = extra != 0L ? total - extra : total - this.size; + if (lastStart > 0L) { + this.offset = lastStart; + } else { + this.offset = 0L; + } + } + + } + + public long getSize() { + return this.size; + } + + public void setSize(long size) { + if (size <= 0L) { + this.size = 10L; + } else { + this.size = size; + } + + } + + public long getStartIndex() { + if (this.getPages() <= 2L * this.getShowIndex()) { + this.startIndex = 1L; + } else { + this.startIndex = this.getActivePage() - this.getShowIndex(); + if (this.startIndex < 1L) { + this.startIndex = 1L; + } + } + + return this.startIndex; + } + + public void setStartIndex(long startIndex) { + this.startIndex = startIndex; + } + + public long getShowIndex() { + return this.showIndex; + } + + public void setShowIndex(long showIndex) { + this.showIndex = showIndex; + } + + public long getEndIndex() { + if (this.getPages() <= 2L * this.getShowIndex()) { + this.endIndex = this.getPages(); + } else { + this.endIndex = this.getActivePage() + this.getShowIndex() - 0L; + if (this.endIndex > this.getPages()) { + this.endIndex = this.getPages(); + } + } + + return this.endIndex; + } + + public void setPage(long page) { + this.setOffset(page * this.size - this.size); + } + + public void setEndIndex(long endIndex) { + this.endIndex = endIndex; + } + + public List getResults() { + return this.results; + } + + public void setResults(List results) { + this.results = results; + } +} \ No newline at end of file diff --git a/src/main/java/com/aiprose/querydsl/vos/DeptTreeVo.java b/src/main/java/com/aiprose/querydsl/vos/DeptTreeVo.java new file mode 100644 index 0000000..2fc4cf2 --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/vos/DeptTreeVo.java @@ -0,0 +1,25 @@ +package com.aiprose.querydsl.vos; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Column; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @version 1.0 + * @Auther: liuchao + * @company 北京中经网软件有限公司 + * @Date: 2020/9/15 + */ +@Data +public class DeptTreeVo implements Serializable { + private String name; + private String loc; + private Integer pid; + private Date cdate; + private List child; +} diff --git a/src/main/java/com/aiprose/querydsl/vos/UserVo.java b/src/main/java/com/aiprose/querydsl/vos/UserVo.java new file mode 100644 index 0000000..770303f --- /dev/null +++ b/src/main/java/com/aiprose/querydsl/vos/UserVo.java @@ -0,0 +1,19 @@ +package com.aiprose.querydsl.vos; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import javax.persistence.Column; +import java.io.Serializable; + +/** + * @version 1.0 + * @Auther: nelson + * @company 北京中经网软件有限公司 + * @Date: 2020/9/15 + */ +@Data +public class UserVo implements Serializable { + private String username; + private String password; +}