| @@ -42,10 +42,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { | |||||
| for (String[] user : usersGroupsAndRoles) { | for (String[] user : usersGroupsAndRoles) { | ||||
| List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length)); | List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length)); | ||||
| log.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]"); | log.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]"); | ||||
| inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]), authoritiesStrings | |||||
| .stream() | |||||
| .map(SimpleGrantedAuthority::new) | |||||
| .collect(Collectors.toList()))); | |||||
| inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]), authoritiesStrings.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()))); | |||||
| } | } | ||||
| @@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoActuatorApplication { | public class SpringBootDemoActuatorApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoActuatorApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoActuatorApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoActuatorApplicationTests { | public class SpringBootDemoActuatorApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoAdminClientApplication { | public class SpringBootDemoAdminClientApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoAdminClientApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoAdminClientApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -13,8 +13,8 @@ import org.springframework.web.bind.annotation.RestController; | |||||
| */ | */ | ||||
| @RestController | @RestController | ||||
| public class IndexController { | public class IndexController { | ||||
| @GetMapping(value = {"", "/"}) | |||||
| public String index() { | |||||
| return "This is a Spring Boot Admin Client."; | |||||
| } | |||||
| @GetMapping(value = {"", "/"}) | |||||
| public String index() { | |||||
| return "This is a Spring Boot Admin Client."; | |||||
| } | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoAdminClientApplicationTests { | public class SpringBootDemoAdminClientApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -16,7 +16,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoAdminServerApplication { | public class SpringBootDemoAdminServerApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoAdminServerApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoAdminServerApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoAdminServerApplicationTests { | public class SpringBootDemoAdminServerApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -179,9 +179,7 @@ public class CodeGenUtil { | |||||
| try { | try { | ||||
| //添加到zip | //添加到zip | ||||
| zip.putNextEntry(new ZipEntry(Objects.requireNonNull(getFileName(template, tableEntity.getCaseClassName(), map | |||||
| .get("package") | |||||
| .toString(), map.get("moduleName").toString())))); | |||||
| zip.putNextEntry(new ZipEntry(Objects.requireNonNull(getFileName(template, tableEntity.getCaseClassName(), map.get("package").toString(), map.get("moduleName").toString())))); | |||||
| IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString()); | IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString()); | ||||
| IoUtil.close(sw); | IoUtil.close(sw); | ||||
| zip.closeEntry(); | zip.closeEntry(); | ||||
| @@ -78,6 +78,7 @@ public enum DatasourceHolder { | |||||
| /** | /** | ||||
| * 清除动态数据源 | * 清除动态数据源 | ||||
| * | |||||
| * @param id 数据源id | * @param id 数据源id | ||||
| */ | */ | ||||
| public synchronized void removeDatasource(Long id) { | public synchronized void removeDatasource(Long id) { | ||||
| @@ -37,7 +37,7 @@ public enum DatasourceScheduler { | |||||
| } | } | ||||
| } | } | ||||
| public void schedule(Runnable task,long delay){ | |||||
| public void schedule(Runnable task, long delay) { | |||||
| this.scheduler.scheduleAtFixedRate(task, delay, delay, TimeUnit.MILLISECONDS); | this.scheduler.scheduleAtFixedRate(task, delay, delay, TimeUnit.MILLISECONDS); | ||||
| } | } | ||||
| @@ -35,6 +35,7 @@ public class DynamicDataSource extends HikariDataSource { | |||||
| /** | /** | ||||
| * 初始化数据源 | * 初始化数据源 | ||||
| * | |||||
| * @param id 数据源id | * @param id 数据源id | ||||
| * @return 数据源 | * @return 数据源 | ||||
| */ | */ | ||||
| @@ -54,7 +54,6 @@ public class Result<T> implements Serializable { | |||||
| } | } | ||||
| /** | /** | ||||
| * 返回成功 | * 返回成功 | ||||
| * | * | ||||
| @@ -70,7 +69,7 @@ public class Result<T> implements Serializable { | |||||
| * 返回成功-携带数据 | * 返回成功-携带数据 | ||||
| * | * | ||||
| * @param data 响应数据 | * @param data 响应数据 | ||||
| * @param <T> 泛型标记 | |||||
| * @param <T> 泛型标记 | |||||
| * @return 响应信息 {@code Result} | * @return 响应信息 {@code Result} | ||||
| */ | */ | ||||
| public static <T> Result<T> success(@Nullable T data) { | public static <T> Result<T> success(@Nullable T data) { | ||||
| @@ -78,7 +77,4 @@ public class Result<T> implements Serializable { | |||||
| } | } | ||||
| } | } | ||||
| @@ -17,51 +17,51 @@ public interface PersonService { | |||||
| /** | /** | ||||
| * create Index | * create Index | ||||
| * | * | ||||
| * @author fxbin | |||||
| * @param index elasticsearch index name | * @param index elasticsearch index name | ||||
| * @author fxbin | |||||
| */ | */ | ||||
| void createIndex(String index); | void createIndex(String index); | ||||
| /** | /** | ||||
| * delete Index | * delete Index | ||||
| * | * | ||||
| * @author fxbin | |||||
| * @param index elasticsearch index name | * @param index elasticsearch index name | ||||
| * @author fxbin | |||||
| */ | */ | ||||
| void deleteIndex(String index); | void deleteIndex(String index); | ||||
| /** | /** | ||||
| * insert document source | * insert document source | ||||
| * | * | ||||
| * @author fxbin | |||||
| * @param index elasticsearch index name | * @param index elasticsearch index name | ||||
| * @param list data source | |||||
| * @param list data source | |||||
| * @author fxbin | |||||
| */ | */ | ||||
| void insert(String index, List<Person> list); | void insert(String index, List<Person> list); | ||||
| /** | /** | ||||
| * update document source | * update document source | ||||
| * | * | ||||
| * @author fxbin | |||||
| * @param index elasticsearch index name | * @param index elasticsearch index name | ||||
| * @param list data source | |||||
| * @param list data source | |||||
| * @author fxbin | |||||
| */ | */ | ||||
| void update(String index, List<Person> list); | void update(String index, List<Person> list); | ||||
| /** | /** | ||||
| * delete document source | * delete document source | ||||
| * | * | ||||
| * @author fxbin | |||||
| * @param person delete data source and allow null object | * @param person delete data source and allow null object | ||||
| * @author fxbin | |||||
| */ | */ | ||||
| void delete(String index, @Nullable Person person); | void delete(String index, @Nullable Person person); | ||||
| /** | /** | ||||
| * search all doc records | * search all doc records | ||||
| * | * | ||||
| * @author fxbin | |||||
| * @param index elasticsearch index name | * @param index elasticsearch index name | ||||
| * @return person list | * @return person list | ||||
| * @author fxbin | |||||
| */ | */ | ||||
| List<Person> searchList(String index); | List<Person> searchList(String index); | ||||
| @@ -2,8 +2,8 @@ package com.xkcoding.elasticsearch.service.impl; | |||||
| import cn.hutool.core.bean.BeanUtil; | import cn.hutool.core.bean.BeanUtil; | ||||
| import com.xkcoding.elasticsearch.model.Person; | import com.xkcoding.elasticsearch.model.Person; | ||||
| import com.xkcoding.elasticsearch.service.base.BaseElasticsearchService; | |||||
| import com.xkcoding.elasticsearch.service.PersonService; | import com.xkcoding.elasticsearch.service.PersonService; | ||||
| import com.xkcoding.elasticsearch.service.base.BaseElasticsearchService; | |||||
| import org.elasticsearch.action.index.IndexRequest; | import org.elasticsearch.action.index.IndexRequest; | ||||
| import org.elasticsearch.action.search.SearchResponse; | import org.elasticsearch.action.search.SearchResponse; | ||||
| import org.elasticsearch.search.SearchHit; | import org.elasticsearch.search.SearchHit; | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoElasticsearchApplicationTests { | public class SpringBootDemoElasticsearchApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -92,8 +92,7 @@ public class PersonRepositoryTest extends SpringBootDemoElasticsearchApplication | |||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void select() { | public void select() { | ||||
| repo.findAll(Sort.by(Sort.Direction.DESC, "birthday")) | |||||
| .forEach(person -> log.info("{} 生日: {}", person.getName(), DateUtil.formatDateTime(person.getBirthday()))); | |||||
| repo.findAll(Sort.by(Sort.Direction.DESC, "birthday")).forEach(person -> log.info("{} 生日: {}", person.getName(), DateUtil.formatDateTime(person.getBirthday()))); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -167,8 +166,8 @@ public class PersonRepositoryTest extends SpringBootDemoElasticsearchApplication | |||||
| // 1. 添加一个新的聚合,聚合类型为terms,聚合名称为country,聚合字段为age | // 1. 添加一个新的聚合,聚合类型为terms,聚合名称为country,聚合字段为age | ||||
| queryBuilder.addAggregation(AggregationBuilders.terms("country").field("country") | queryBuilder.addAggregation(AggregationBuilders.terms("country").field("country") | ||||
| // 2. 在国家聚合桶内进行嵌套聚合,求平均年龄 | |||||
| .subAggregation(AggregationBuilders.avg("avg").field("age"))); | |||||
| // 2. 在国家聚合桶内进行嵌套聚合,求平均年龄 | |||||
| .subAggregation(AggregationBuilders.avg("avg").field("age"))); | |||||
| log.info("【queryBuilder】= {}", JSONUtil.toJsonStr(queryBuilder.build())); | log.info("【queryBuilder】= {}", JSONUtil.toJsonStr(queryBuilder.build())); | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoEmailApplicationTests { | public class SpringBootDemoEmailApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoExceptionHandlerApplication { | public class SpringBootDemoExceptionHandlerApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoExceptionHandlerApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoExceptionHandlerApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -12,26 +12,26 @@ import lombok.Getter; | |||||
| */ | */ | ||||
| @Getter | @Getter | ||||
| public enum Status { | public enum Status { | ||||
| /** | |||||
| * 操作成功 | |||||
| */ | |||||
| OK(200, "操作成功"), | |||||
| /** | |||||
| * 操作成功 | |||||
| */ | |||||
| OK(200, "操作成功"), | |||||
| /** | |||||
| * 未知异常 | |||||
| */ | |||||
| UNKNOWN_ERROR(500, "服务器出错啦"); | |||||
| /** | |||||
| * 状态码 | |||||
| */ | |||||
| private Integer code; | |||||
| /** | |||||
| * 内容 | |||||
| */ | |||||
| private String message; | |||||
| /** | |||||
| * 未知异常 | |||||
| */ | |||||
| UNKNOWN_ERROR(500, "服务器出错啦"); | |||||
| /** | |||||
| * 状态码 | |||||
| */ | |||||
| private Integer code; | |||||
| /** | |||||
| * 内容 | |||||
| */ | |||||
| private String message; | |||||
| Status(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| Status(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| } | } | ||||
| @@ -20,14 +20,14 @@ import org.springframework.web.servlet.ModelAndView; | |||||
| @Controller | @Controller | ||||
| public class TestController { | public class TestController { | ||||
| @GetMapping("/json") | |||||
| @ResponseBody | |||||
| public ApiResponse jsonException() { | |||||
| throw new JsonException(Status.UNKNOWN_ERROR); | |||||
| } | |||||
| @GetMapping("/json") | |||||
| @ResponseBody | |||||
| public ApiResponse jsonException() { | |||||
| throw new JsonException(Status.UNKNOWN_ERROR); | |||||
| } | |||||
| @GetMapping("/page") | |||||
| public ModelAndView pageException() { | |||||
| throw new PageException(Status.UNKNOWN_ERROR); | |||||
| } | |||||
| @GetMapping("/page") | |||||
| public ModelAndView pageException() { | |||||
| throw new PageException(Status.UNKNOWN_ERROR); | |||||
| } | |||||
| } | } | ||||
| @@ -15,18 +15,18 @@ import lombok.EqualsAndHashCode; | |||||
| @Data | @Data | ||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||
| public class BaseException extends RuntimeException { | public class BaseException extends RuntimeException { | ||||
| private Integer code; | |||||
| private String message; | |||||
| private Integer code; | |||||
| private String message; | |||||
| public BaseException(Status status) { | |||||
| super(status.getMessage()); | |||||
| this.code = status.getCode(); | |||||
| this.message = status.getMessage(); | |||||
| } | |||||
| public BaseException(Status status) { | |||||
| super(status.getMessage()); | |||||
| this.code = status.getCode(); | |||||
| this.message = status.getMessage(); | |||||
| } | |||||
| public BaseException(Integer code, String message) { | |||||
| super(message); | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public BaseException(Integer code, String message) { | |||||
| super(message); | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| } | } | ||||
| @@ -14,11 +14,11 @@ import lombok.Getter; | |||||
| @Getter | @Getter | ||||
| public class JsonException extends BaseException { | public class JsonException extends BaseException { | ||||
| public JsonException(Status status) { | |||||
| super(status); | |||||
| } | |||||
| public JsonException(Status status) { | |||||
| super(status); | |||||
| } | |||||
| public JsonException(Integer code, String message) { | |||||
| super(code, message); | |||||
| } | |||||
| public JsonException(Integer code, String message) { | |||||
| super(code, message); | |||||
| } | |||||
| } | } | ||||
| @@ -14,11 +14,11 @@ import lombok.Getter; | |||||
| @Getter | @Getter | ||||
| public class PageException extends BaseException { | public class PageException extends BaseException { | ||||
| public PageException(Status status) { | |||||
| super(status); | |||||
| } | |||||
| public PageException(Status status) { | |||||
| super(status); | |||||
| } | |||||
| public PageException(Integer code, String message) { | |||||
| super(code, message); | |||||
| } | |||||
| public PageException(Integer code, String message) { | |||||
| super(code, message); | |||||
| } | |||||
| } | } | ||||
| @@ -20,33 +20,33 @@ import org.springframework.web.servlet.ModelAndView; | |||||
| @ControllerAdvice | @ControllerAdvice | ||||
| @Slf4j | @Slf4j | ||||
| public class DemoExceptionHandler { | public class DemoExceptionHandler { | ||||
| private static final String DEFAULT_ERROR_VIEW = "error"; | |||||
| private static final String DEFAULT_ERROR_VIEW = "error"; | |||||
| /** | |||||
| * 统一 json 异常处理 | |||||
| * | |||||
| * @param exception JsonException | |||||
| * @return 统一返回 json 格式 | |||||
| */ | |||||
| @ExceptionHandler(value = JsonException.class) | |||||
| @ResponseBody | |||||
| public ApiResponse jsonErrorHandler(JsonException exception) { | |||||
| log.error("【JsonException】:{}", exception.getMessage()); | |||||
| return ApiResponse.ofException(exception); | |||||
| } | |||||
| /** | |||||
| * 统一 json 异常处理 | |||||
| * | |||||
| * @param exception JsonException | |||||
| * @return 统一返回 json 格式 | |||||
| */ | |||||
| @ExceptionHandler(value = JsonException.class) | |||||
| @ResponseBody | |||||
| public ApiResponse jsonErrorHandler(JsonException exception) { | |||||
| log.error("【JsonException】:{}", exception.getMessage()); | |||||
| return ApiResponse.ofException(exception); | |||||
| } | |||||
| /** | |||||
| * 统一 页面 异常处理 | |||||
| * | |||||
| * @param exception PageException | |||||
| * @return 统一跳转到异常页面 | |||||
| */ | |||||
| @ExceptionHandler(value = PageException.class) | |||||
| public ModelAndView pageErrorHandler(PageException exception) { | |||||
| log.error("【DemoPageException】:{}", exception.getMessage()); | |||||
| ModelAndView view = new ModelAndView(); | |||||
| view.addObject("message", exception.getMessage()); | |||||
| view.setViewName(DEFAULT_ERROR_VIEW); | |||||
| return view; | |||||
| } | |||||
| /** | |||||
| * 统一 页面 异常处理 | |||||
| * | |||||
| * @param exception PageException | |||||
| * @return 统一跳转到异常页面 | |||||
| */ | |||||
| @ExceptionHandler(value = PageException.class) | |||||
| public ModelAndView pageErrorHandler(PageException exception) { | |||||
| log.error("【DemoPageException】:{}", exception.getMessage()); | |||||
| ModelAndView view = new ModelAndView(); | |||||
| view.addObject("message", exception.getMessage()); | |||||
| view.setViewName(DEFAULT_ERROR_VIEW); | |||||
| return view; | |||||
| } | |||||
| } | } | ||||
| @@ -14,114 +14,114 @@ import lombok.Data; | |||||
| */ | */ | ||||
| @Data | @Data | ||||
| public class ApiResponse { | public class ApiResponse { | ||||
| /** | |||||
| * 状态码 | |||||
| */ | |||||
| private Integer code; | |||||
| /** | |||||
| * 状态码 | |||||
| */ | |||||
| private Integer code; | |||||
| /** | |||||
| * 返回内容 | |||||
| */ | |||||
| private String message; | |||||
| /** | |||||
| * 返回内容 | |||||
| */ | |||||
| private String message; | |||||
| /** | |||||
| * 返回数据 | |||||
| */ | |||||
| private Object data; | |||||
| /** | |||||
| * 返回数据 | |||||
| */ | |||||
| private Object data; | |||||
| /** | |||||
| * 无参构造函数 | |||||
| */ | |||||
| private ApiResponse() { | |||||
| /** | |||||
| * 无参构造函数 | |||||
| */ | |||||
| private ApiResponse() { | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 全参构造函数 | |||||
| * | |||||
| * @param code 状态码 | |||||
| * @param message 返回内容 | |||||
| * @param data 返回数据 | |||||
| */ | |||||
| private ApiResponse(Integer code, String message, Object data) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| this.data = data; | |||||
| } | |||||
| /** | |||||
| * 全参构造函数 | |||||
| * | |||||
| * @param code 状态码 | |||||
| * @param message 返回内容 | |||||
| * @param data 返回数据 | |||||
| */ | |||||
| private ApiResponse(Integer code, String message, Object data) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| this.data = data; | |||||
| } | |||||
| /** | |||||
| * 构造一个自定义的API返回 | |||||
| * | |||||
| * @param code 状态码 | |||||
| * @param message 返回内容 | |||||
| * @param data 返回数据 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse of(Integer code, String message, Object data) { | |||||
| return new ApiResponse(code, message, data); | |||||
| } | |||||
| /** | |||||
| * 构造一个自定义的API返回 | |||||
| * | |||||
| * @param code 状态码 | |||||
| * @param message 返回内容 | |||||
| * @param data 返回数据 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse of(Integer code, String message, Object data) { | |||||
| return new ApiResponse(code, message, data); | |||||
| } | |||||
| /** | |||||
| * 构造一个成功且带数据的API返回 | |||||
| * | |||||
| * @param data 返回数据 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofSuccess(Object data) { | |||||
| return ofStatus(Status.OK, data); | |||||
| } | |||||
| /** | |||||
| * 构造一个成功且带数据的API返回 | |||||
| * | |||||
| * @param data 返回数据 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofSuccess(Object data) { | |||||
| return ofStatus(Status.OK, data); | |||||
| } | |||||
| /** | |||||
| * 构造一个成功且自定义消息的API返回 | |||||
| * | |||||
| * @param message 返回内容 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofMessage(String message) { | |||||
| return of(Status.OK.getCode(), message, null); | |||||
| } | |||||
| /** | |||||
| * 构造一个成功且自定义消息的API返回 | |||||
| * | |||||
| * @param message 返回内容 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofMessage(String message) { | |||||
| return of(Status.OK.getCode(), message, null); | |||||
| } | |||||
| /** | |||||
| * 构造一个有状态的API返回 | |||||
| * | |||||
| * @param status 状态 {@link Status} | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofStatus(Status status) { | |||||
| return ofStatus(status, null); | |||||
| } | |||||
| /** | |||||
| * 构造一个有状态的API返回 | |||||
| * | |||||
| * @param status 状态 {@link Status} | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofStatus(Status status) { | |||||
| return ofStatus(status, null); | |||||
| } | |||||
| /** | |||||
| * 构造一个有状态且带数据的API返回 | |||||
| * | |||||
| * @param status 状态 {@link Status} | |||||
| * @param data 返回数据 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofStatus(Status status, Object data) { | |||||
| return of(status.getCode(), status.getMessage(), data); | |||||
| } | |||||
| /** | |||||
| * 构造一个有状态且带数据的API返回 | |||||
| * | |||||
| * @param status 状态 {@link Status} | |||||
| * @param data 返回数据 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static ApiResponse ofStatus(Status status, Object data) { | |||||
| return of(status.getCode(), status.getMessage(), data); | |||||
| } | |||||
| /** | |||||
| * 构造一个异常且带数据的API返回 | |||||
| * | |||||
| * @param t 异常 | |||||
| * @param data 返回数据 | |||||
| * @param <T> {@link BaseException} 的子类 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static <T extends BaseException> ApiResponse ofException(T t, Object data) { | |||||
| return of(t.getCode(), t.getMessage(), data); | |||||
| } | |||||
| /** | |||||
| * 构造一个异常且带数据的API返回 | |||||
| * | |||||
| * @param t 异常 | |||||
| * @param data 返回数据 | |||||
| * @param <T> {@link BaseException} 的子类 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static <T extends BaseException> ApiResponse ofException(T t, Object data) { | |||||
| return of(t.getCode(), t.getMessage(), data); | |||||
| } | |||||
| /** | |||||
| * 构造一个异常且带数据的API返回 | |||||
| * | |||||
| * @param t 异常 | |||||
| * @param <T> {@link BaseException} 的子类 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static <T extends BaseException> ApiResponse ofException(T t) { | |||||
| return ofException(t, null); | |||||
| } | |||||
| /** | |||||
| * 构造一个异常且带数据的API返回 | |||||
| * | |||||
| * @param t 异常 | |||||
| * @param <T> {@link BaseException} 的子类 | |||||
| * @return ApiResponse | |||||
| */ | |||||
| public static <T extends BaseException> ApiResponse ofException(T t) { | |||||
| return ofException(t, null); | |||||
| } | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoExceptionHandlerApplicationTests { | public class SpringBootDemoExceptionHandlerApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -1,20 +1,18 @@ | |||||
| package com.xkcoding; | package com.xkcoding; | ||||
| import static org.junit.Assert.assertTrue; | |||||
| import org.junit.Test; | import org.junit.Test; | ||||
| import static org.junit.Assert.assertTrue; | |||||
| /** | /** | ||||
| * Unit test for simple App. | * Unit test for simple App. | ||||
| */ | */ | ||||
| public class AppTest | |||||
| { | |||||
| public class AppTest { | |||||
| /** | /** | ||||
| * Rigorous Test :-) | * Rigorous Test :-) | ||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void shouldAnswerWithTrue() | |||||
| { | |||||
| assertTrue( true ); | |||||
| public void shouldAnswerWithTrue() { | |||||
| assertTrue(true); | |||||
| } | } | ||||
| } | } | ||||
| @@ -19,21 +19,21 @@ import org.springframework.web.bind.annotation.RestController; | |||||
| @RestController | @RestController | ||||
| public class SpringBootDemoHelloworldApplication { | public class SpringBootDemoHelloworldApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoHelloworldApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoHelloworldApplication.class, args); | |||||
| } | |||||
| /** | |||||
| * Hello,World | |||||
| * | |||||
| * @param who 参数,非必须 | |||||
| * @return Hello, ${who} | |||||
| */ | |||||
| @GetMapping("/hello") | |||||
| public String sayHello(@RequestParam(required = false, name = "who") String who) { | |||||
| if (StrUtil.isBlank(who)) { | |||||
| who = "World"; | |||||
| } | |||||
| return StrUtil.format("Hello, {}!", who); | |||||
| } | |||||
| /** | |||||
| * Hello,World | |||||
| * | |||||
| * @param who 参数,非必须 | |||||
| * @return Hello, ${who} | |||||
| */ | |||||
| @GetMapping("/hello") | |||||
| public String sayHello(@RequestParam(required = false, name = "who") String who) { | |||||
| if (StrUtil.isBlank(who)) { | |||||
| who = "World"; | |||||
| } | |||||
| return StrUtil.format("Hello, {}!", who); | |||||
| } | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoHelloworldApplicationTests { | public class SpringBootDemoHelloworldApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -1,5 +1,5 @@ | |||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||
| <html lang="en" xmlns:th="http://www.thymeleaf.org"> | |||||
| <html lang="en"> | |||||
| <head> | <head> | ||||
| <meta charset="UTF-8"> | <meta charset="UTF-8"> | ||||
| <title>spring boot demo https</title> | <title>spring boot demo https</title> | ||||
| @@ -54,7 +54,6 @@ public class Result<T> implements Serializable { | |||||
| } | } | ||||
| /** | /** | ||||
| * 返回成功 | * 返回成功 | ||||
| * | * | ||||
| @@ -70,7 +69,7 @@ public class Result<T> implements Serializable { | |||||
| * 返回成功-携带数据 | * 返回成功-携带数据 | ||||
| * | * | ||||
| * @param data 响应数据 | * @param data 响应数据 | ||||
| * @param <T> 泛型标记 | |||||
| * @param <T> 泛型标记 | |||||
| * @return 响应信息 {@code Result} | * @return 响应信息 {@code Result} | ||||
| */ | */ | ||||
| public static <T> Result<T> success(@Nullable T data) { | public static <T> Result<T> success(@Nullable T data) { | ||||
| @@ -78,7 +77,4 @@ public class Result<T> implements Serializable { | |||||
| } | } | ||||
| } | } | ||||
| @@ -17,10 +17,7 @@ import java.io.Serializable; | |||||
| * @since 2019-08-26 0:51 | * @since 2019-08-26 0:51 | ||||
| */ | */ | ||||
| @Data | @Data | ||||
| @Entry( | |||||
| base = "ou=people", | |||||
| objectClasses = {"posixAccount", "inetOrgPerson", "top"} | |||||
| ) | |||||
| @Entry(base = "ou=people", objectClasses = {"posixAccount", "inetOrgPerson", "top"}) | |||||
| public class Person implements Serializable { | public class Person implements Serializable { | ||||
| private static final long serialVersionUID = -7946768337975852352L; | private static final long serialVersionUID = -7946768337975852352L; | ||||
| @@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoLogAopApplication { | public class SpringBootDemoLogAopApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoLogAopApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoLogAopApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -26,65 +26,65 @@ import java.util.Objects; | |||||
| @Component | @Component | ||||
| @Slf4j | @Slf4j | ||||
| public class AopLog { | public class AopLog { | ||||
| private static final String START_TIME = "request-start"; | |||||
| private static final String START_TIME = "request-start"; | |||||
| /** | |||||
| * 切入点 | |||||
| */ | |||||
| @Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))") | |||||
| public void log() { | |||||
| /** | |||||
| * 切入点 | |||||
| */ | |||||
| @Pointcut("execution(public * com.xkcoding.log.aop.controller.*Controller.*(..))") | |||||
| public void log() { | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 前置操作 | |||||
| * | |||||
| * @param point 切入点 | |||||
| */ | |||||
| @Before("log()") | |||||
| public void beforeLog(JoinPoint point) { | |||||
| ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
| /** | |||||
| * 前置操作 | |||||
| * | |||||
| * @param point 切入点 | |||||
| */ | |||||
| @Before("log()") | |||||
| public void beforeLog(JoinPoint point) { | |||||
| ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
| HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); | |||||
| HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); | |||||
| log.info("【请求 URL】:{}", request.getRequestURL()); | |||||
| log.info("【请求 IP】:{}", request.getRemoteAddr()); | |||||
| log.info("【请求类名】:{},【请求方法名】:{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName()); | |||||
| log.info("【请求 URL】:{}", request.getRequestURL()); | |||||
| log.info("【请求 IP】:{}", request.getRemoteAddr()); | |||||
| log.info("【请求类名】:{},【请求方法名】:{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName()); | |||||
| Map<String, String[]> parameterMap = request.getParameterMap(); | |||||
| log.info("【请求参数】:{},", JSONUtil.toJsonStr(parameterMap)); | |||||
| Long start = System.currentTimeMillis(); | |||||
| request.setAttribute(START_TIME, start); | |||||
| } | |||||
| Map<String, String[]> parameterMap = request.getParameterMap(); | |||||
| log.info("【请求参数】:{},", JSONUtil.toJsonStr(parameterMap)); | |||||
| Long start = System.currentTimeMillis(); | |||||
| request.setAttribute(START_TIME, start); | |||||
| } | |||||
| /** | |||||
| * 环绕操作 | |||||
| * | |||||
| * @param point 切入点 | |||||
| * @return 原方法返回值 | |||||
| * @throws Throwable 异常信息 | |||||
| */ | |||||
| @Around("log()") | |||||
| public Object aroundLog(ProceedingJoinPoint point) throws Throwable { | |||||
| Object result = point.proceed(); | |||||
| log.info("【返回值】:{}", JSONUtil.toJsonStr(result)); | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 环绕操作 | |||||
| * | |||||
| * @param point 切入点 | |||||
| * @return 原方法返回值 | |||||
| * @throws Throwable 异常信息 | |||||
| */ | |||||
| @Around("log()") | |||||
| public Object aroundLog(ProceedingJoinPoint point) throws Throwable { | |||||
| Object result = point.proceed(); | |||||
| log.info("【返回值】:{}", JSONUtil.toJsonStr(result)); | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 后置操作 | |||||
| */ | |||||
| @AfterReturning("log()") | |||||
| public void afterReturning() { | |||||
| ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
| HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); | |||||
| /** | |||||
| * 后置操作 | |||||
| */ | |||||
| @AfterReturning("log()") | |||||
| public void afterReturning() { | |||||
| ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | |||||
| HttpServletRequest request = Objects.requireNonNull(attributes).getRequest(); | |||||
| Long start = (Long) request.getAttribute(START_TIME); | |||||
| Long end = System.currentTimeMillis(); | |||||
| log.info("【请求耗时】:{}毫秒", end - start); | |||||
| Long start = (Long) request.getAttribute(START_TIME); | |||||
| Long end = System.currentTimeMillis(); | |||||
| log.info("【请求耗时】:{}毫秒", end - start); | |||||
| String header = request.getHeader("User-Agent"); | |||||
| UserAgent userAgent = UserAgent.parseUserAgentString(header); | |||||
| log.info("【浏览器类型】:{},【操作系统】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header); | |||||
| } | |||||
| String header = request.getHeader("User-Agent"); | |||||
| UserAgent userAgent = UserAgent.parseUserAgentString(header); | |||||
| log.info("【浏览器类型】:{},【操作系统】:{},【原始User-Agent】:{}", userAgent.getBrowser().toString(), userAgent.getOperatingSystem().toString(), header); | |||||
| } | |||||
| } | } | ||||
| @@ -16,15 +16,15 @@ import org.springframework.web.bind.annotation.RestController; | |||||
| @RestController | @RestController | ||||
| public class TestController { | public class TestController { | ||||
| /** | |||||
| * 测试方法 | |||||
| * | |||||
| * @param who 测试参数 | |||||
| * @return {@link Dict} | |||||
| */ | |||||
| @GetMapping("/test") | |||||
| public Dict test(String who) { | |||||
| return Dict.create().set("who", StrUtil.isBlank(who) ? "me" : who); | |||||
| } | |||||
| /** | |||||
| * 测试方法 | |||||
| * | |||||
| * @param who 测试参数 | |||||
| * @return {@link Dict} | |||||
| */ | |||||
| @GetMapping("/test") | |||||
| public Dict test(String who) { | |||||
| return Dict.create().set("who", StrUtil.isBlank(who) ? "me" : who); | |||||
| } | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoLogAopApplicationTests { | public class SpringBootDemoLogAopApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -17,19 +17,19 @@ import org.springframework.context.ConfigurableApplicationContext; | |||||
| @Slf4j | @Slf4j | ||||
| public class SpringBootDemoLogbackApplication { | public class SpringBootDemoLogbackApplication { | ||||
| public static void main(String[] args) { | |||||
| ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoLogbackApplication.class, args); | |||||
| int length = context.getBeanDefinitionNames().length; | |||||
| log.trace("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.debug("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.info("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.warn("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.error("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| try { | |||||
| int i = 0; | |||||
| int j = 1 / i; | |||||
| } catch (Exception e) { | |||||
| log.error("【SpringBootDemoLogbackApplication】启动异常:", e); | |||||
| } | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| ConfigurableApplicationContext context = SpringApplication.run(SpringBootDemoLogbackApplication.class, args); | |||||
| int length = context.getBeanDefinitionNames().length; | |||||
| log.trace("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.debug("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.info("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.warn("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| log.error("Spring boot启动初始化了 {} 个 Bean", length); | |||||
| try { | |||||
| int i = 0; | |||||
| int j = 1 / i; | |||||
| } catch (Exception e) { | |||||
| log.error("【SpringBootDemoLogbackApplication】启动异常:", e); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoLogbackApplicationTests { | public class SpringBootDemoLogbackApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -45,8 +45,7 @@ public class ArticleRepositoryTest extends SpringBootDemoMongodbApplicationTests | |||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void testSave() { | public void testSave() { | ||||
| Article article = new Article(1L, RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil.date(), DateUtil | |||||
| .date(), 0L, 0L); | |||||
| Article article = new Article(1L, RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil.date(), DateUtil.date(), 0L, 0L); | |||||
| articleRepo.save(article); | articleRepo.save(article); | ||||
| log.info("【article】= {}", JSONUtil.toJsonStr(article)); | log.info("【article】= {}", JSONUtil.toJsonStr(article)); | ||||
| } | } | ||||
| @@ -58,14 +57,11 @@ public class ArticleRepositoryTest extends SpringBootDemoMongodbApplicationTests | |||||
| public void testSaveList() { | public void testSaveList() { | ||||
| List<Article> articles = Lists.newArrayList(); | List<Article> articles = Lists.newArrayList(); | ||||
| for (int i = 0; i < 10; i++) { | for (int i = 0; i < 10; i++) { | ||||
| articles.add(new Article(snowflake.nextId(), RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil | |||||
| .date(), DateUtil.date(), 0L, 0L)); | |||||
| articles.add(new Article(snowflake.nextId(), RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil.date(), DateUtil.date(), 0L, 0L)); | |||||
| } | } | ||||
| articleRepo.saveAll(articles); | articleRepo.saveAll(articles); | ||||
| log.info("【articles】= {}", JSONUtil.toJsonStr(articles.stream() | |||||
| .map(Article::getId) | |||||
| .collect(Collectors.toList()))); | |||||
| log.info("【articles】= {}", JSONUtil.toJsonStr(articles.stream().map(Article::getId).collect(Collectors.toList()))); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -118,9 +114,7 @@ public class ArticleRepositoryTest extends SpringBootDemoMongodbApplicationTests | |||||
| update.inc("visits", 1L); | update.inc("visits", 1L); | ||||
| mongoTemplate.updateFirst(query, update, "article"); | mongoTemplate.updateFirst(query, update, "article"); | ||||
| articleRepo.findById(1L) | |||||
| .ifPresent(article -> log.info("【标题】= {}【点赞数】= {}【访客数】= {}", article.getTitle(), article.getThumbUp(), article | |||||
| .getVisits())); | |||||
| articleRepo.findById(1L).ifPresent(article -> log.info("【标题】= {}【点赞数】= {}【访客数】= {}", article.getTitle(), article.getThumbUp(), article.getVisits())); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -133,10 +127,7 @@ public class ArticleRepositoryTest extends SpringBootDemoMongodbApplicationTests | |||||
| Page<Article> all = articleRepo.findAll(pageRequest); | Page<Article> all = articleRepo.findAll(pageRequest); | ||||
| log.info("【总页数】= {}", all.getTotalPages()); | log.info("【总页数】= {}", all.getTotalPages()); | ||||
| log.info("【总条数】= {}", all.getTotalElements()); | log.info("【总条数】= {}", all.getTotalElements()); | ||||
| log.info("【当前页数据】= {}", JSONUtil.toJsonStr(all.getContent() | |||||
| .stream() | |||||
| .map(article -> "文章标题:" + article.getTitle() + "点赞数:" + article.getThumbUp() + "更新时间:" + article.getUpdateTime()) | |||||
| .collect(Collectors.toList()))); | |||||
| log.info("【当前页数据】= {}", JSONUtil.toJsonStr(all.getContent().stream().map(article -> "文章标题:" + article.getTitle() + "点赞数:" + article.getThumbUp() + "更新时间:" + article.getUpdateTime()).collect(Collectors.toList()))); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -61,18 +61,15 @@ public class SpringBootDemoMqRabbitmqApplicationTests { | |||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void sendDelay() { | public void sendDelay() { | ||||
| rabbitTemplate.convertAndSend(RabbitConsts.DELAY_MODE_QUEUE, RabbitConsts.DELAY_QUEUE, new MessageStruct("delay message, delay 5s, " + DateUtil | |||||
| .date()), message -> { | |||||
| rabbitTemplate.convertAndSend(RabbitConsts.DELAY_MODE_QUEUE, RabbitConsts.DELAY_QUEUE, new MessageStruct("delay message, delay 5s, " + DateUtil.date()), message -> { | |||||
| message.getMessageProperties().setHeader("x-delay", 5000); | message.getMessageProperties().setHeader("x-delay", 5000); | ||||
| return message; | return message; | ||||
| }); | }); | ||||
| rabbitTemplate.convertAndSend(RabbitConsts.DELAY_MODE_QUEUE, RabbitConsts.DELAY_QUEUE, new MessageStruct("delay message, delay 2s, " + DateUtil | |||||
| .date()), message -> { | |||||
| rabbitTemplate.convertAndSend(RabbitConsts.DELAY_MODE_QUEUE, RabbitConsts.DELAY_QUEUE, new MessageStruct("delay message, delay 2s, " + DateUtil.date()), message -> { | |||||
| message.getMessageProperties().setHeader("x-delay", 2000); | message.getMessageProperties().setHeader("x-delay", 2000); | ||||
| return message; | return message; | ||||
| }); | }); | ||||
| rabbitTemplate.convertAndSend(RabbitConsts.DELAY_MODE_QUEUE, RabbitConsts.DELAY_QUEUE, new MessageStruct("delay message, delay 8s, " + DateUtil | |||||
| .date()), message -> { | |||||
| rabbitTemplate.convertAndSend(RabbitConsts.DELAY_MODE_QUEUE, RabbitConsts.DELAY_QUEUE, new MessageStruct("delay message, delay 8s, " + DateUtil.date()), message -> { | |||||
| message.getMessageProperties().setHeader("x-delay", 8000); | message.getMessageProperties().setHeader("x-delay", 8000); | ||||
| return message; | return message; | ||||
| }); | }); | ||||
| @@ -28,12 +28,12 @@ import javax.sql.DataSource; | |||||
| @Configuration | @Configuration | ||||
| @EnableTransactionManagement | @EnableTransactionManagement | ||||
| @EnableJpaRepositories( | @EnableJpaRepositories( | ||||
| // repository包名 | |||||
| basePackages = PrimaryJpaConfig.REPOSITORY_PACKAGE, | |||||
| // 实体管理bean名称 | |||||
| entityManagerFactoryRef = "primaryEntityManagerFactory", | |||||
| // 事务管理bean名称 | |||||
| transactionManagerRef = "primaryTransactionManager") | |||||
| // repository包名 | |||||
| basePackages = PrimaryJpaConfig.REPOSITORY_PACKAGE, | |||||
| // 实体管理bean名称 | |||||
| entityManagerFactoryRef = "primaryEntityManagerFactory", | |||||
| // 事务管理bean名称 | |||||
| transactionManagerRef = "primaryTransactionManager") | |||||
| public class PrimaryJpaConfig { | public class PrimaryJpaConfig { | ||||
| static final String REPOSITORY_PACKAGE = "com.xkcoding.multi.datasource.jpa.repository.primary"; | static final String REPOSITORY_PACKAGE = "com.xkcoding.multi.datasource.jpa.repository.primary"; | ||||
| private static final String ENTITY_PACKAGE = "com.xkcoding.multi.datasource.jpa.entity.primary"; | private static final String ENTITY_PACKAGE = "com.xkcoding.multi.datasource.jpa.entity.primary"; | ||||
| @@ -63,14 +63,14 @@ public class PrimaryJpaConfig { | |||||
| @Bean(name = "primaryEntityManagerFactory") | @Bean(name = "primaryEntityManagerFactory") | ||||
| public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource, @Qualifier("primaryJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) { | public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource, @Qualifier("primaryJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) { | ||||
| return builder | return builder | ||||
| // 设置数据源 | |||||
| .dataSource(primaryDataSource) | |||||
| // 设置jpa配置 | |||||
| .properties(jpaProperties.getProperties()) | |||||
| // 设置实体包名 | |||||
| .packages(ENTITY_PACKAGE) | |||||
| // 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源 | |||||
| .persistenceUnit("primaryPersistenceUnit").build(); | |||||
| // 设置数据源 | |||||
| .dataSource(primaryDataSource) | |||||
| // 设置jpa配置 | |||||
| .properties(jpaProperties.getProperties()) | |||||
| // 设置实体包名 | |||||
| .packages(ENTITY_PACKAGE) | |||||
| // 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源 | |||||
| .persistenceUnit("primaryPersistenceUnit").build(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -27,12 +27,12 @@ import javax.sql.DataSource; | |||||
| @Configuration | @Configuration | ||||
| @EnableTransactionManagement | @EnableTransactionManagement | ||||
| @EnableJpaRepositories( | @EnableJpaRepositories( | ||||
| // repository包名 | |||||
| basePackages = SecondJpaConfig.REPOSITORY_PACKAGE, | |||||
| // 实体管理bean名称 | |||||
| entityManagerFactoryRef = "secondEntityManagerFactory", | |||||
| // 事务管理bean名称 | |||||
| transactionManagerRef = "secondTransactionManager") | |||||
| // repository包名 | |||||
| basePackages = SecondJpaConfig.REPOSITORY_PACKAGE, | |||||
| // 实体管理bean名称 | |||||
| entityManagerFactoryRef = "secondEntityManagerFactory", | |||||
| // 事务管理bean名称 | |||||
| transactionManagerRef = "secondTransactionManager") | |||||
| public class SecondJpaConfig { | public class SecondJpaConfig { | ||||
| static final String REPOSITORY_PACKAGE = "com.xkcoding.multi.datasource.jpa.repository.second"; | static final String REPOSITORY_PACKAGE = "com.xkcoding.multi.datasource.jpa.repository.second"; | ||||
| private static final String ENTITY_PACKAGE = "com.xkcoding.multi.datasource.jpa.entity.second"; | private static final String ENTITY_PACKAGE = "com.xkcoding.multi.datasource.jpa.entity.second"; | ||||
| @@ -60,14 +60,14 @@ public class SecondJpaConfig { | |||||
| @Bean(name = "secondEntityManagerFactory") | @Bean(name = "secondEntityManagerFactory") | ||||
| public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("secondDataSource") DataSource secondDataSource, @Qualifier("secondJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) { | public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("secondDataSource") DataSource secondDataSource, @Qualifier("secondJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) { | ||||
| return builder | return builder | ||||
| // 设置数据源 | |||||
| .dataSource(secondDataSource) | |||||
| // 设置jpa配置 | |||||
| .properties(jpaProperties.getProperties()) | |||||
| // 设置实体包名 | |||||
| .packages(ENTITY_PACKAGE) | |||||
| // 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源 | |||||
| .persistenceUnit("secondPersistenceUnit").build(); | |||||
| // 设置数据源 | |||||
| .dataSource(secondDataSource) | |||||
| // 设置jpa配置 | |||||
| .properties(jpaProperties.getProperties()) | |||||
| // 设置实体包名 | |||||
| .packages(ENTITY_PACKAGE) | |||||
| // 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源 | |||||
| .persistenceUnit("secondPersistenceUnit").build(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -16,7 +16,7 @@ import org.springframework.context.annotation.Configuration; | |||||
| @Configuration | @Configuration | ||||
| public class SnowflakeConfig { | public class SnowflakeConfig { | ||||
| @Bean | @Bean | ||||
| public Snowflake snowflake(){ | |||||
| return IdUtil.createSnowflake(1,1); | |||||
| public Snowflake snowflake() { | |||||
| return IdUtil.createSnowflake(1, 1); | |||||
| } | } | ||||
| } | } | ||||
| @@ -28,7 +28,7 @@ public class SpringBootDemoMultiDatasourceJpaApplicationTests { | |||||
| @Test | @Test | ||||
| public void testInsert() { | public void testInsert() { | ||||
| PrimaryMultiTable primary = new PrimaryMultiTable(snowflake.nextId(),"测试名称-1"); | |||||
| PrimaryMultiTable primary = new PrimaryMultiTable(snowflake.nextId(), "测试名称-1"); | |||||
| primaryRepo.save(primary); | primaryRepo.save(primary); | ||||
| SecondMultiTable second = new SecondMultiTable(); | SecondMultiTable second = new SecondMultiTable(); | ||||
| @@ -39,7 +39,7 @@ public class SpringBootDemoMultiDatasourceJpaApplicationTests { | |||||
| @Test | @Test | ||||
| public void testUpdate() { | public void testUpdate() { | ||||
| primaryRepo.findAll().forEach(primary -> { | primaryRepo.findAll().forEach(primary -> { | ||||
| primary.setName("修改后的"+primary.getName()); | |||||
| primary.setName("修改后的" + primary.getName()); | |||||
| primaryRepo.save(primary); | primaryRepo.save(primary); | ||||
| SecondMultiTable second = new SecondMultiTable(); | SecondMultiTable second = new SecondMultiTable(); | ||||
| @@ -90,10 +90,8 @@ public class NeoService { | |||||
| classRepo.save(seven); | classRepo.save(seven); | ||||
| // 初始化学生 | // 初始化学生 | ||||
| List<Student> threeClass = Lists.newArrayList(Student.of("漩涡鸣人", Lists.newArrayList(tishu, shoulijian, luoxuanwan, xianshu), seven), Student | |||||
| .of("宇智波佐助", Lists.newArrayList(huanshu, zhouyin, shoulijian), seven), Student.of("春野樱", Lists.newArrayList(tishu, yiliao, shoulijian), seven)); | |||||
| List<Student> sevenClass = Lists.newArrayList(Student.of("李洛克", Lists.newArrayList(tishu), three), Student.of("日向宁次", Lists | |||||
| .newArrayList(tishu), three), Student.of("天天", Lists.newArrayList(tishu), three)); | |||||
| List<Student> threeClass = Lists.newArrayList(Student.of("漩涡鸣人", Lists.newArrayList(tishu, shoulijian, luoxuanwan, xianshu), seven), Student.of("宇智波佐助", Lists.newArrayList(huanshu, zhouyin, shoulijian), seven), Student.of("春野樱", Lists.newArrayList(tishu, yiliao, shoulijian), seven)); | |||||
| List<Student> sevenClass = Lists.newArrayList(Student.of("李洛克", Lists.newArrayList(tishu), three), Student.of("日向宁次", Lists.newArrayList(tishu), three), Student.of("天天", Lists.newArrayList(tishu), three)); | |||||
| studentRepo.saveAll(threeClass); | studentRepo.saveAll(threeClass); | ||||
| studentRepo.saveAll(sevenClass); | studentRepo.saveAll(sevenClass); | ||||
| @@ -155,8 +153,7 @@ public class NeoService { | |||||
| List<ClassmateInfoGroupByLesson> groupByLesson = studentRepo.findByClassmateGroupByLesson(); | List<ClassmateInfoGroupByLesson> groupByLesson = studentRepo.findByClassmateGroupByLesson(); | ||||
| Map<String, List<Student>> result = Maps.newHashMap(); | Map<String, List<Student>> result = Maps.newHashMap(); | ||||
| groupByLesson.forEach(classmateInfoGroupByLesson -> result.put(classmateInfoGroupByLesson.getLessonName(), classmateInfoGroupByLesson | |||||
| .getStudents())); | |||||
| groupByLesson.forEach(classmateInfoGroupByLesson -> result.put(classmateInfoGroupByLesson.getLessonName(), classmateInfoGroupByLesson.getStudents())); | |||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -171,11 +168,9 @@ public class NeoService { | |||||
| List<TeacherStudent> teacherStudentByLesson = studentRepo.findTeacherStudentByLesson(); | List<TeacherStudent> teacherStudentByLesson = studentRepo.findTeacherStudentByLesson(); | ||||
| Map<String, Set<Student>> result = Maps.newHashMap(); | Map<String, Set<Student>> result = Maps.newHashMap(); | ||||
| teacherStudentByClass.forEach(teacherStudent -> result.put(teacherStudent.getTeacherName(), Sets.newHashSet(teacherStudent | |||||
| .getStudents()))); | |||||
| teacherStudentByClass.forEach(teacherStudent -> result.put(teacherStudent.getTeacherName(), Sets.newHashSet(teacherStudent.getStudents()))); | |||||
| teacherStudentByLesson.forEach(teacherStudent -> result.put(teacherStudent.getTeacherName(), Sets.newHashSet(teacherStudent | |||||
| .getStudents()))); | |||||
| teacherStudentByLesson.forEach(teacherStudent -> result.put(teacherStudent.getTeacherName(), Sets.newHashSet(teacherStudent.getStudents()))); | |||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -71,9 +71,7 @@ public class Neo4jTest extends SpringBootDemoNeo4jApplicationTests { | |||||
| @Test | @Test | ||||
| public void testFindClassmates() { | public void testFindClassmates() { | ||||
| Map<String, List<Student>> classmates = neoService.findClassmatesGroupByLesson(); | Map<String, List<Student>> classmates = neoService.findClassmatesGroupByLesson(); | ||||
| classmates.forEach((k, v) -> log.info("因为一起上了【{}】这门课,成为同学关系的有:{}", k, JSONUtil.toJsonStr(v.stream() | |||||
| .map(Student::getName) | |||||
| .collect(Collectors.toList())))); | |||||
| classmates.forEach((k, v) -> log.info("因为一起上了【{}】这门课,成为同学关系的有:{}", k, JSONUtil.toJsonStr(v.stream().map(Student::getName).collect(Collectors.toList())))); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -82,8 +80,6 @@ public class Neo4jTest extends SpringBootDemoNeo4jApplicationTests { | |||||
| @Test | @Test | ||||
| public void testFindTeacherStudent() { | public void testFindTeacherStudent() { | ||||
| Map<String, Set<Student>> teacherStudent = neoService.findTeacherStudent(); | Map<String, Set<Student>> teacherStudent = neoService.findTeacherStudent(); | ||||
| teacherStudent.forEach((k, v) -> log.info("【{}】教的学生有 {}", k, JSONUtil.toJsonStr(v.stream() | |||||
| .map(Student::getName) | |||||
| .collect(Collectors.toList())))); | |||||
| teacherStudent.forEach((k, v) -> log.info("【{}】教的学生有 {}", k, JSONUtil.toJsonStr(v.stream().map(Student::getName).collect(Collectors.toList())))); | |||||
| } | } | ||||
| } | } | ||||
| @@ -21,11 +21,9 @@ import java.net.URLEncoder; | |||||
| @Component | @Component | ||||
| public class ClientLoginFailureHandler implements AuthenticationFailureHandler { | public class ClientLoginFailureHandler implements AuthenticationFailureHandler { | ||||
| @Override | @Override | ||||
| public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, | |||||
| AuthenticationException exception) throws IOException { | |||||
| public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException { | |||||
| log.debug("Login failed!"); | log.debug("Login failed!"); | ||||
| response.setStatus(HttpStatus.UNAUTHORIZED.value()); | response.setStatus(HttpStatus.UNAUTHORIZED.value()); | ||||
| response.sendRedirect("/oauth/login?error=" | |||||
| + URLEncoder.encode(exception.getLocalizedMessage(), "UTF-8")); | |||||
| response.sendRedirect("/oauth/login?error=" + URLEncoder.encode(exception.getLocalizedMessage(), "UTF-8")); | |||||
| } | } | ||||
| } | } | ||||
| @@ -31,10 +31,7 @@ public class Oauth2AuthorizationServerConfig extends AuthorizationServerConfigur | |||||
| @Override | @Override | ||||
| public void configure(AuthorizationServerEndpointsConfigurer endpoints) { | public void configure(AuthorizationServerEndpointsConfigurer endpoints) { | ||||
| endpoints.authenticationManager(authenticationManager) | |||||
| .userDetailsService(sysUserService) | |||||
| .tokenStore(tokenStore) | |||||
| .accessTokenConverter(jwtAccessTokenConverter); | |||||
| endpoints.authenticationManager(authenticationManager).userDetailsService(sysUserService).tokenStore(tokenStore).accessTokenConverter(jwtAccessTokenConverter); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -24,20 +24,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||||
| @Override | @Override | ||||
| protected void configure(HttpSecurity http) throws Exception { | protected void configure(HttpSecurity http) throws Exception { | ||||
| http | |||||
| .formLogin() | |||||
| .loginPage("/oauth/login") | |||||
| .failureHandler(clientLoginFailureHandler) | |||||
| .loginProcessingUrl("/authorization/form") | |||||
| .and() | |||||
| .logout() | |||||
| .logoutUrl("/oauth/logout") | |||||
| .logoutSuccessHandler(clientLogoutSuccessHandler) | |||||
| .and() | |||||
| .authorizeRequests() | |||||
| .antMatchers("/oauth/**").permitAll() | |||||
| .anyRequest() | |||||
| .authenticated(); | |||||
| http.formLogin().loginPage("/oauth/login").failureHandler(clientLoginFailureHandler).loginProcessingUrl("/authorization/form").and().logout().logoutUrl("/oauth/logout").logoutSuccessHandler(clientLogoutSuccessHandler).and().authorizeRequests().antMatchers("/oauth/**").permitAll().anyRequest().authenticated(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -4,10 +4,10 @@ | |||||
| * {@link com.xkcoding.oauth.config.Oauth2AuthorizationServerConfig} | * {@link com.xkcoding.oauth.config.Oauth2AuthorizationServerConfig} | ||||
| * 授权服务器相关的配置,主要设置授权服务器如何读取客户端、用户信息和一些端点配置 | * 授权服务器相关的配置,主要设置授权服务器如何读取客户端、用户信息和一些端点配置 | ||||
| * 可以在这里配置更多的东西,例如端点映射,token 增强等 | * 可以在这里配置更多的东西,例如端点映射,token 增强等 | ||||
| * | |||||
| * <p> | |||||
| * {@link com.xkcoding.oauth.config.Oauth2AuthorizationTokenConfig} | * {@link com.xkcoding.oauth.config.Oauth2AuthorizationTokenConfig} | ||||
| * 授权服务器 token 相关的配置,主要设置 jwt、加密方式等信息 | * 授权服务器 token 相关的配置,主要设置 jwt、加密方式等信息 | ||||
| * | |||||
| * <p> | |||||
| * {@link com.xkcoding.oauth.config.ClientLogoutSuccessHandler} | * {@link com.xkcoding.oauth.config.ClientLogoutSuccessHandler} | ||||
| * 资源服务器退出以后的处理。在授权码模式中,所有的客户端都需要跳转到授权服务器进行登录 | * 资源服务器退出以后的处理。在授权码模式中,所有的客户端都需要跳转到授权服务器进行登录 | ||||
| * 当登录成功以后跳转到回调地址,如果用户需要登出,也要跳转到授权服务器这里进行登出 | * 当登录成功以后跳转到回调地址,如果用户需要登出,也要跳转到授权服务器这里进行登出 | ||||
| @@ -15,7 +15,6 @@ | |||||
| * 所以自己给登出端点加了一个 redirect_url 参数,表示登出成功以后要跳转的地址 | * 所以自己给登出端点加了一个 redirect_url 参数,表示登出成功以后要跳转的地址 | ||||
| * 这个处理器就是来完成登出成功以后的跳转操作的。 | * 这个处理器就是来完成登出成功以后的跳转操作的。 | ||||
| * | * | ||||
| * | |||||
| * @author <a href="https://echocow.cn">EchoCow</a> | * @author <a href="https://echocow.cn">EchoCow</a> | ||||
| * @date 2020-01-07 9:16 | * @date 2020-01-07 9:16 | ||||
| */ | */ | ||||
| @@ -36,12 +36,11 @@ public class Oauth2Controller { | |||||
| * 退出登录 | * 退出登录 | ||||
| * | * | ||||
| * @param redirectUrl 退出完成后的回调地址 | * @param redirectUrl 退出完成后的回调地址 | ||||
| * @param principal 用户信息 | |||||
| * @param principal 用户信息 | |||||
| * @return 结果 | * @return 结果 | ||||
| */ | */ | ||||
| @GetMapping("/logout") | @GetMapping("/logout") | ||||
| public ModelAndView logoutView( | |||||
| @RequestParam("redirect_url") String redirectUrl, Principal principal) { | |||||
| public ModelAndView logoutView(@RequestParam("redirect_url") String redirectUrl, Principal principal) { | |||||
| if (Objects.isNull(principal)) { | if (Objects.isNull(principal)) { | ||||
| throw new ResourceAccessException("请求错误,用户尚未登录"); | throw new ResourceAccessException("请求错误,用户尚未登录"); | ||||
| } | } | ||||
| @@ -2,7 +2,7 @@ | |||||
| * 控制器。除了业务逻辑的以外,提供两个控制器来帮助完成自定义: | * 控制器。除了业务逻辑的以外,提供两个控制器来帮助完成自定义: | ||||
| * {@link com.xkcoding.oauth.controller.AuthorizationController} | * {@link com.xkcoding.oauth.controller.AuthorizationController} | ||||
| * 自定义的授权控制器,重新设置到我们的界面中去,不使用他的默认实现 | * 自定义的授权控制器,重新设置到我们的界面中去,不使用他的默认实现 | ||||
| * | |||||
| * <p> | |||||
| * {@link com.xkcoding.oauth.controller.Oauth2Controller} | * {@link com.xkcoding.oauth.controller.Oauth2Controller} | ||||
| * 页面跳转的控制器,这里拿出来是因为真的可以做很多事。比如登录的时候携带点什么 | * 页面跳转的控制器,这里拿出来是因为真的可以做很多事。比如登录的时候携带点什么 | ||||
| * 或者退出的时候携带什么标识,都可以。 | * 或者退出的时候携带什么标识,都可以。 | ||||
| @@ -47,9 +47,6 @@ public class SysUser { | |||||
| * 当前用户所有角色. | * 当前用户所有角色. | ||||
| */ | */ | ||||
| @ManyToMany(fetch = FetchType.EAGER) | @ManyToMany(fetch = FetchType.EAGER) | ||||
| @JoinTable(name = "sys_user_role", | |||||
| joinColumns = @JoinColumn(name = "user_id"), | |||||
| inverseJoinColumns = @JoinColumn(name = "role_id") | |||||
| ) | |||||
| @JoinTable(name = "sys_user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) | |||||
| private Set<SysRole> roles; | private Set<SysRole> roles; | ||||
| } | } | ||||
| @@ -5,7 +5,10 @@ import com.xkcoding.oauth.repostiory.SysClientDetailsRepository; | |||||
| import com.xkcoding.oauth.service.SysClientDetailsService; | import com.xkcoding.oauth.service.SysClientDetailsService; | ||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.security.crypto.password.PasswordEncoder; | import org.springframework.security.crypto.password.PasswordEncoder; | ||||
| import org.springframework.security.oauth2.provider.*; | |||||
| import org.springframework.security.oauth2.provider.ClientAlreadyExistsException; | |||||
| import org.springframework.security.oauth2.provider.ClientDetails; | |||||
| import org.springframework.security.oauth2.provider.ClientRegistrationException; | |||||
| import org.springframework.security.oauth2.provider.NoSuchClientException; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import java.util.List; | import java.util.List; | ||||
| @@ -25,14 +28,12 @@ public class SysClientDetailsServiceImpl implements SysClientDetailsService { | |||||
| @Override | @Override | ||||
| public ClientDetails loadClientByClientId(String id) throws ClientRegistrationException { | public ClientDetails loadClientByClientId(String id) throws ClientRegistrationException { | ||||
| return sysClientDetailsRepository.findFirstByClientId(id) | |||||
| .orElseThrow(() -> new ClientRegistrationException("Loading client exception.")); | |||||
| return sysClientDetailsRepository.findFirstByClientId(id).orElseThrow(() -> new ClientRegistrationException("Loading client exception.")); | |||||
| } | } | ||||
| @Override | @Override | ||||
| public SysClientDetails findByClientId(String clientId) { | public SysClientDetails findByClientId(String clientId) { | ||||
| return sysClientDetailsRepository.findFirstByClientId(clientId) | |||||
| .orElseThrow(() -> new ClientRegistrationException("Loading client exception.")); | |||||
| return sysClientDetailsRepository.findFirstByClientId(clientId).orElseThrow(() -> new ClientRegistrationException("Loading client exception.")); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -46,16 +47,14 @@ public class SysClientDetailsServiceImpl implements SysClientDetailsService { | |||||
| @Override | @Override | ||||
| public void updateClientDetails(SysClientDetails clientDetails) throws NoSuchClientException { | public void updateClientDetails(SysClientDetails clientDetails) throws NoSuchClientException { | ||||
| SysClientDetails exist = sysClientDetailsRepository.findFirstByClientId(clientDetails.getClientId()) | |||||
| .orElseThrow(() -> new NoSuchClientException("No such client!")); | |||||
| SysClientDetails exist = sysClientDetailsRepository.findFirstByClientId(clientDetails.getClientId()).orElseThrow(() -> new NoSuchClientException("No such client!")); | |||||
| clientDetails.setClientSecret(exist.getClientSecret()); | clientDetails.setClientSecret(exist.getClientSecret()); | ||||
| sysClientDetailsRepository.save(clientDetails); | sysClientDetailsRepository.save(clientDetails); | ||||
| } | } | ||||
| @Override | @Override | ||||
| public void updateClientSecret(String clientId, String clientSecret) throws NoSuchClientException { | public void updateClientSecret(String clientId, String clientSecret) throws NoSuchClientException { | ||||
| SysClientDetails exist = sysClientDetailsRepository.findFirstByClientId(clientId) | |||||
| .orElseThrow(() -> new NoSuchClientException("No such client!")); | |||||
| SysClientDetails exist = sysClientDetailsRepository.findFirstByClientId(clientId).orElseThrow(() -> new NoSuchClientException("No such client!")); | |||||
| exist.setClientSecret(passwordEncoder.encode(clientSecret)); | exist.setClientSecret(passwordEncoder.encode(clientSecret)); | ||||
| sysClientDetailsRepository.save(exist); | sysClientDetailsRepository.save(exist); | ||||
| } | } | ||||
| @@ -29,11 +29,8 @@ public class SysUserServiceImpl implements SysUserService { | |||||
| @Override | @Override | ||||
| public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | ||||
| SysUser sysUser = sysUserRepository.findFirstByUsername(username) | |||||
| .orElseThrow(() -> new UsernameNotFoundException("User not found!")); | |||||
| List<SimpleGrantedAuthority> roles = sysUser.getRoles().stream() | |||||
| .map(sysRole -> new SimpleGrantedAuthority(sysRole.getName())) | |||||
| .collect(Collectors.toList()); | |||||
| SysUser sysUser = sysUserRepository.findFirstByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found!")); | |||||
| List<SimpleGrantedAuthority> roles = sysUser.getRoles().stream().map(sysRole -> new SimpleGrantedAuthority(sysRole.getName())).collect(Collectors.toList()); | |||||
| // 在这里手动构建 UserDetails 的默认实现 | // 在这里手动构建 UserDetails 的默认实现 | ||||
| return new User(sysUser.getUsername(), sysUser.getPassword(), roles); | return new User(sysUser.getUsername(), sysUser.getPassword(), roles); | ||||
| } | } | ||||
| @@ -45,8 +42,7 @@ public class SysUserServiceImpl implements SysUserService { | |||||
| @Override | @Override | ||||
| public SysUser findById(Long id) { | public SysUser findById(Long id) { | ||||
| return sysUserRepository.findById(id) | |||||
| .orElseThrow(() -> new RuntimeException("找不到用户")); | |||||
| return sysUserRepository.findById(id).orElseThrow(() -> new RuntimeException("找不到用户")); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -46,15 +46,13 @@ public class AuthorizationCodeGrantTests { | |||||
| @Test | @Test | ||||
| void testCannotConnectWithoutToken() { | void testCannotConnectWithoutToken() { | ||||
| OAuth2RestTemplate template = new OAuth2RestTemplate(resource); | OAuth2RestTemplate template = new OAuth2RestTemplate(resource); | ||||
| assertThrows(UserRedirectRequiredException.class, | |||||
| () -> template.getForObject(getUrl("/oauth/me"), String.class)); | |||||
| assertThrows(UserRedirectRequiredException.class, () -> template.getForObject(getUrl("/oauth/me"), String.class)); | |||||
| } | } | ||||
| @Test | @Test | ||||
| void testAttemptedTokenAcquisitionWithNoRedirect() { | void testAttemptedTokenAcquisitionWithNoRedirect() { | ||||
| AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); | AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider(); | ||||
| assertThrows(UserRedirectRequiredException.class, | |||||
| () -> provider.obtainAccessToken(resource, new DefaultAccessTokenRequest())); | |||||
| assertThrows(UserRedirectRequiredException.class, () -> provider.obtainAccessToken(resource, new DefaultAccessTokenRequest())); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -80,8 +78,7 @@ public class AuthorizationCodeGrantTests { | |||||
| form.add("_csrf", matcher.group(1)); | form.add("_csrf", matcher.group(1)); | ||||
| // 3. 登录授权并获取登录成功的 cookie | // 3. 登录授权并获取登录成功的 cookie | ||||
| ResponseEntity<Void> response = authorizationServerInfo | |||||
| .postForStatus("/authorization/form", headers, form); | |||||
| ResponseEntity<Void> response = authorizationServerInfo.postForStatus("/authorization/form", headers, form); | |||||
| assertNotNull(response); | assertNotNull(response); | ||||
| cookie = response.getHeaders().getFirst("Set-Cookie"); | cookie = response.getHeaders().getFirst("Set-Cookie"); | ||||
| headers = new HttpHeaders(); | headers = new HttpHeaders(); | ||||
| @@ -89,8 +86,7 @@ public class AuthorizationCodeGrantTests { | |||||
| headers.setAccept(Collections.singletonList(MediaType.ALL)); | headers.setAccept(Collections.singletonList(MediaType.ALL)); | ||||
| // 4. 请求到 确认授权页面 ,获取确认授权页面的 _csrf 的 value | // 4. 请求到 确认授权页面 ,获取确认授权页面的 _csrf 的 value | ||||
| ResponseEntity<String> confirm = authorizationServerInfo | |||||
| .getForString("/oauth/authorize?response_type=code&client_id=oauth2&redirect_uri=http://example.com&scope=READ", headers); | |||||
| ResponseEntity<String> confirm = authorizationServerInfo.getForString("/oauth/authorize?response_type=code&client_id=oauth2&redirect_uri=http://example.com&scope=READ", headers); | |||||
| headers = confirm.getHeaders(); | headers = confirm.getHeaders(); | ||||
| // 确认过一次后,后面都会自动确认了,这里判断下是不是重定向请求 | // 确认过一次后,后面都会自动确认了,这里判断下是不是重定向请求 | ||||
| @@ -55,8 +55,7 @@ public class AuthorizationServerInfo { | |||||
| HttpHeaders actualHeaders = new HttpHeaders(); | HttpHeaders actualHeaders = new HttpHeaders(); | ||||
| actualHeaders.putAll(headers); | actualHeaders.putAll(headers); | ||||
| actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); | actualHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); | ||||
| return client.exchange(getUrl(path), HttpMethod.POST, | |||||
| new HttpEntity<>(formData, actualHeaders), (Class<Void>) null); | |||||
| return client.exchange(getUrl(path), HttpMethod.POST, new HttpEntity<>(formData, actualHeaders), (Class<Void>) null); | |||||
| } | } | ||||
| @@ -83,8 +82,7 @@ public class AuthorizationServerInfo { | |||||
| } | } | ||||
| builder.deleteCharAt(builder.length() - 1); | builder.deleteCharAt(builder.length() - 1); | ||||
| return client.execute(builder.toString(), HttpMethod.POST, requestCallback, | |||||
| HttpMessage::getHeaders); | |||||
| return client.execute(builder.toString(), HttpMethod.POST, requestCallback, HttpMessage::getHeaders); | |||||
| } | } | ||||
| private static final class NullRequestCallback implements RequestCallback { | private static final class NullRequestCallback implements RequestCallback { | ||||
| @@ -8,7 +8,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; | |||||
| import java.util.Arrays; | import java.util.Arrays; | ||||
| import static com.xkcoding.oauth.oauth.AuthorizationServerInfo.getUrl; | import static com.xkcoding.oauth.oauth.AuthorizationServerInfo.getUrl; | ||||
| import static org.junit.jupiter.api.Assertions.*; | |||||
| import static org.junit.jupiter.api.Assertions.assertNotNull; | |||||
| /** | /** | ||||
| * . | * . | ||||
| @@ -8,8 +8,8 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.E | |||||
| * 启动器. | * 启动器. | ||||
| * | * | ||||
| * @author <a href="https://echocow.cn">EchoCow</a> | * @author <a href="https://echocow.cn">EchoCow</a> | ||||
| * @date 2020-01-09 11:38 | |||||
| * @version V1.0 | * @version V1.0 | ||||
| * @date 2020-01-09 11:38 | |||||
| */ | */ | ||||
| @EnableResourceServer | @EnableResourceServer | ||||
| @SpringBootApplication | @SpringBootApplication | ||||
| @@ -28,9 +28,7 @@ public class OauthResourceServerConfig extends ResourceServerConfigurerAdapter { | |||||
| @Override | @Override | ||||
| public void configure(ResourceServerSecurityConfigurer resources) { | public void configure(ResourceServerSecurityConfigurer resources) { | ||||
| resources | |||||
| .tokenStore(tokenStore) | |||||
| .resourceId(resourceServerProperties.getResourceId()); | |||||
| resources.tokenStore(tokenStore).resourceId(resourceServerProperties.getResourceId()); | |||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -62,9 +62,7 @@ public class OauthResourceTokenConfig { | |||||
| */ | */ | ||||
| private String getPubKey() { | private String getPubKey() { | ||||
| // 如果本地没有密钥,就从授权服务器中获取 | // 如果本地没有密钥,就从授权服务器中获取 | ||||
| return StringUtils.isEmpty(resourceServerProperties.getJwt().getKeyValue()) | |||||
| ? getKeyFromAuthorizationServer() | |||||
| : resourceServerProperties.getJwt().getKeyValue(); | |||||
| return StringUtils.isEmpty(resourceServerProperties.getJwt().getKeyValue()) ? getKeyFromAuthorizationServer() : resourceServerProperties.getJwt().getKeyValue(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -78,8 +76,7 @@ public class OauthResourceTokenConfig { | |||||
| HttpHeaders httpHeaders = new HttpHeaders(); | HttpHeaders httpHeaders = new HttpHeaders(); | ||||
| httpHeaders.add(HttpHeaders.AUTHORIZATION, encodeClient()); | httpHeaders.add(HttpHeaders.AUTHORIZATION, encodeClient()); | ||||
| HttpEntity<String> requestEntity = new HttpEntity<>(null, httpHeaders); | HttpEntity<String> requestEntity = new HttpEntity<>(null, httpHeaders); | ||||
| String pubKey = new RestTemplate() | |||||
| .getForObject(resourceServerProperties.getJwt().getKeyUri(), String.class, requestEntity); | |||||
| String pubKey = new RestTemplate().getForObject(resourceServerProperties.getJwt().getKeyUri(), String.class, requestEntity); | |||||
| try { | try { | ||||
| JSONObject body = objectMapper.readValue(pubKey, JSONObject.class); | JSONObject body = objectMapper.readValue(pubKey, JSONObject.class); | ||||
| log.info("Get Key From Authorization Server."); | log.info("Get Key From Authorization Server."); | ||||
| @@ -96,7 +93,6 @@ public class OauthResourceTokenConfig { | |||||
| * @return basic | * @return basic | ||||
| */ | */ | ||||
| private String encodeClient() { | private String encodeClient() { | ||||
| return "Basic " + Base64.getEncoder().encodeToString((resourceServerProperties.getClientId() | |||||
| + ":" + resourceServerProperties.getClientSecret()).getBytes()); | |||||
| return "Basic " + Base64.getEncoder().encodeToString((resourceServerProperties.getClientId() + ":" + resourceServerProperties.getClientSecret()).getBytes()); | |||||
| } | } | ||||
| } | } | ||||
| @@ -32,7 +32,6 @@ public class AuthorizationTest { | |||||
| @Test | @Test | ||||
| void testAccessTokenWhenPassed() { | void testAccessTokenWhenPassed() { | ||||
| assertNotNull(oauth2RestTemplate("admin", "123456", Collections.singletonList("READ")) | |||||
| .getAccessToken()); | |||||
| assertNotNull(oauth2RestTemplate("admin", "123456", Collections.singletonList("READ")).getAccessToken()); | |||||
| } | } | ||||
| } | } | ||||
| @@ -32,8 +32,7 @@ public class TestControllerTest extends AuthorizationTest { | |||||
| ResponseEntity<String> response = template.exchange(URL + "/admin", GET, null, String.class); | ResponseEntity<String> response = template.exchange(URL + "/admin", GET, null, String.class); | ||||
| assertEquals(HttpStatus.OK, response.getStatusCode()); | assertEquals(HttpStatus.OK, response.getStatusCode()); | ||||
| assertEquals("ADMIN", response.getBody()); | assertEquals("ADMIN", response.getBody()); | ||||
| assertThrows(OAuth2AccessDeniedException.class, | |||||
| () -> template.exchange(URL + "/test", GET, null, String.class)); | |||||
| assertThrows(OAuth2AccessDeniedException.class, () -> template.exchange(URL + "/test", GET, null, String.class)); | |||||
| } | } | ||||
| @Test | @Test | ||||
| @@ -43,8 +42,7 @@ public class TestControllerTest extends AuthorizationTest { | |||||
| ResponseEntity<String> response = template.exchange(URL + "/test", GET, null, String.class); | ResponseEntity<String> response = template.exchange(URL + "/test", GET, null, String.class); | ||||
| assertEquals(HttpStatus.OK, response.getStatusCode()); | assertEquals(HttpStatus.OK, response.getStatusCode()); | ||||
| assertEquals("TEST", response.getBody()); | assertEquals("TEST", response.getBody()); | ||||
| assertThrows(OAuth2AccessDeniedException.class, | |||||
| () -> template.exchange(URL + "/admin", GET, null, String.class)); | |||||
| assertThrows(OAuth2AccessDeniedException.class, () -> template.exchange(URL + "/admin", GET, null, String.class)); | |||||
| } | } | ||||
| @Test | @Test | ||||
| @@ -54,8 +52,7 @@ public class TestControllerTest extends AuthorizationTest { | |||||
| ResponseEntity<String> response = template.exchange(URL + "/read", GET, null, String.class); | ResponseEntity<String> response = template.exchange(URL + "/read", GET, null, String.class); | ||||
| assertEquals(HttpStatus.OK, response.getStatusCode()); | assertEquals(HttpStatus.OK, response.getStatusCode()); | ||||
| assertEquals("READ", response.getBody()); | assertEquals("READ", response.getBody()); | ||||
| assertThrows(OAuth2AccessDeniedException.class, | |||||
| () -> template.exchange(URL + "/write", GET, null, String.class)); | |||||
| assertThrows(OAuth2AccessDeniedException.class, () -> template.exchange(URL + "/write", GET, null, String.class)); | |||||
| } | } | ||||
| @Test | @Test | ||||
| @@ -65,8 +62,7 @@ public class TestControllerTest extends AuthorizationTest { | |||||
| ResponseEntity<String> response = template.exchange(URL + "/write", GET, null, String.class); | ResponseEntity<String> response = template.exchange(URL + "/write", GET, null, String.class); | ||||
| assertEquals(HttpStatus.OK, response.getStatusCode()); | assertEquals(HttpStatus.OK, response.getStatusCode()); | ||||
| assertEquals("WRITE", response.getBody()); | assertEquals("WRITE", response.getBody()); | ||||
| assertThrows(OAuth2AccessDeniedException.class, | |||||
| () -> template.exchange(URL + "/read", GET, null, String.class)); | |||||
| assertThrows(OAuth2AccessDeniedException.class, () -> template.exchange(URL + "/read", GET, null, String.class)); | |||||
| } | } | ||||
| @Test | @Test | ||||
| @@ -22,7 +22,7 @@ public class BeetlConfig { | |||||
| * Beetl需要显示的配置数据源,方可启动项目,大坑,切记! | * Beetl需要显示的配置数据源,方可启动项目,大坑,切记! | ||||
| */ | */ | ||||
| @Bean(name = "datasource") | @Bean(name = "datasource") | ||||
| public DataSource getDataSource(Environment env){ | |||||
| public DataSource getDataSource(Environment env) { | |||||
| HikariDataSource dataSource = new HikariDataSource(); | HikariDataSource dataSource = new HikariDataSource(); | ||||
| dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name")); | dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name")); | ||||
| dataSource.setJdbcUrl(env.getProperty("spring.datasource.url")); | dataSource.setJdbcUrl(env.getProperty("spring.datasource.url")); | ||||
| @@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoOrmJdbctemplateApplication { | public class SpringBootDemoOrmJdbctemplateApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoOrmJdbctemplateApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoOrmJdbctemplateApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -16,10 +16,10 @@ import java.lang.annotation.Target; | |||||
| @Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||
| @Target({ElementType.FIELD}) | @Target({ElementType.FIELD}) | ||||
| public @interface Column { | public @interface Column { | ||||
| /** | |||||
| * 列名 | |||||
| * | |||||
| * @return 列名 | |||||
| */ | |||||
| String name(); | |||||
| /** | |||||
| * 列名 | |||||
| * | |||||
| * @return 列名 | |||||
| */ | |||||
| String name(); | |||||
| } | } | ||||
| @@ -16,10 +16,10 @@ import java.lang.annotation.Target; | |||||
| @Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||
| @Target({ElementType.FIELD}) | @Target({ElementType.FIELD}) | ||||
| public @interface Pk { | public @interface Pk { | ||||
| /** | |||||
| * 自增 | |||||
| * | |||||
| * @return 自增主键 | |||||
| */ | |||||
| boolean auto() default true; | |||||
| /** | |||||
| * 自增 | |||||
| * | |||||
| * @return 自增主键 | |||||
| */ | |||||
| boolean auto() default true; | |||||
| } | } | ||||
| @@ -16,10 +16,10 @@ import java.lang.annotation.Target; | |||||
| @Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||
| @Target({ElementType.TYPE}) | @Target({ElementType.TYPE}) | ||||
| public @interface Table { | public @interface Table { | ||||
| /** | |||||
| * 表名 | |||||
| * | |||||
| * @return 表名 | |||||
| */ | |||||
| String name(); | |||||
| /** | |||||
| * 表名 | |||||
| * | |||||
| * @return 表名 | |||||
| */ | |||||
| String name(); | |||||
| } | } | ||||
| @@ -9,13 +9,13 @@ package com.xkcoding.orm.jdbctemplate.constant; | |||||
| * @date Created in 2018-10-15 10:59 | * @date Created in 2018-10-15 10:59 | ||||
| */ | */ | ||||
| public interface Const { | public interface Const { | ||||
| /** | |||||
| * 加密盐前缀 | |||||
| */ | |||||
| String SALT_PREFIX = "::SpringBootDemo::"; | |||||
| /** | |||||
| * 加密盐前缀 | |||||
| */ | |||||
| String SALT_PREFIX = "::SpringBootDemo::"; | |||||
| /** | |||||
| * 逗号分隔符 | |||||
| */ | |||||
| String SEPARATOR_COMMA = ","; | |||||
| /** | |||||
| * 逗号分隔符 | |||||
| */ | |||||
| String SEPARATOR_COMMA = ","; | |||||
| } | } | ||||
| @@ -20,40 +20,40 @@ import java.util.List; | |||||
| @RestController | @RestController | ||||
| @Slf4j | @Slf4j | ||||
| public class UserController { | public class UserController { | ||||
| private final IUserService userService; | |||||
| @Autowired | |||||
| public UserController(IUserService userService) { | |||||
| this.userService = userService; | |||||
| } | |||||
| @PostMapping("/user") | |||||
| public Dict save(@RequestBody User user) { | |||||
| Boolean save = userService.save(user); | |||||
| return Dict.create().set("code", save ? 200 : 500).set("msg", save ? "成功" : "失败").set("data", save ? user : null); | |||||
| } | |||||
| @DeleteMapping("/user/{id}") | |||||
| public Dict delete(@PathVariable Long id) { | |||||
| Boolean delete = userService.delete(id); | |||||
| return Dict.create().set("code", delete ? 200 : 500).set("msg", delete ? "成功" : "失败"); | |||||
| } | |||||
| @PutMapping("/user/{id}") | |||||
| public Dict update(@RequestBody User user, @PathVariable Long id) { | |||||
| Boolean update = userService.update(user, id); | |||||
| return Dict.create().set("code", update ? 200 : 500).set("msg", update ? "成功" : "失败").set("data", update ? user : null); | |||||
| } | |||||
| @GetMapping("/user/{id}") | |||||
| public Dict getUser(@PathVariable Long id) { | |||||
| User user = userService.getUser(id); | |||||
| return Dict.create().set("code", 200).set("msg", "成功").set("data", user); | |||||
| } | |||||
| @GetMapping("/user") | |||||
| public Dict getUser(User user) { | |||||
| List<User> userList = userService.getUser(user); | |||||
| return Dict.create().set("code", 200).set("msg", "成功").set("data", userList); | |||||
| } | |||||
| private final IUserService userService; | |||||
| @Autowired | |||||
| public UserController(IUserService userService) { | |||||
| this.userService = userService; | |||||
| } | |||||
| @PostMapping("/user") | |||||
| public Dict save(@RequestBody User user) { | |||||
| Boolean save = userService.save(user); | |||||
| return Dict.create().set("code", save ? 200 : 500).set("msg", save ? "成功" : "失败").set("data", save ? user : null); | |||||
| } | |||||
| @DeleteMapping("/user/{id}") | |||||
| public Dict delete(@PathVariable Long id) { | |||||
| Boolean delete = userService.delete(id); | |||||
| return Dict.create().set("code", delete ? 200 : 500).set("msg", delete ? "成功" : "失败"); | |||||
| } | |||||
| @PutMapping("/user/{id}") | |||||
| public Dict update(@RequestBody User user, @PathVariable Long id) { | |||||
| Boolean update = userService.update(user, id); | |||||
| return Dict.create().set("code", update ? 200 : 500).set("msg", update ? "成功" : "失败").set("data", update ? user : null); | |||||
| } | |||||
| @GetMapping("/user/{id}") | |||||
| public Dict getUser(@PathVariable Long id) { | |||||
| User user = userService.getUser(id); | |||||
| return Dict.create().set("code", 200).set("msg", "成功").set("data", user); | |||||
| } | |||||
| @GetMapping("/user") | |||||
| public Dict getUser(User user) { | |||||
| List<User> userList = userService.getUser(user); | |||||
| return Dict.create().set("code", 200).set("msg", "成功").set("data", userList); | |||||
| } | |||||
| } | } | ||||
| @@ -19,59 +19,59 @@ import java.util.List; | |||||
| @Repository | @Repository | ||||
| public class UserDao extends BaseDao<User, Long> { | public class UserDao extends BaseDao<User, Long> { | ||||
| @Autowired | |||||
| public UserDao(JdbcTemplate jdbcTemplate) { | |||||
| super(jdbcTemplate); | |||||
| } | |||||
| @Autowired | |||||
| public UserDao(JdbcTemplate jdbcTemplate) { | |||||
| super(jdbcTemplate); | |||||
| } | |||||
| /** | |||||
| * 保存用户 | |||||
| * | |||||
| * @param user 用户对象 | |||||
| * @return 操作影响行数 | |||||
| */ | |||||
| public Integer insert(User user) { | |||||
| return super.insert(user, true); | |||||
| } | |||||
| /** | |||||
| * 保存用户 | |||||
| * | |||||
| * @param user 用户对象 | |||||
| * @return 操作影响行数 | |||||
| */ | |||||
| public Integer insert(User user) { | |||||
| return super.insert(user, true); | |||||
| } | |||||
| /** | |||||
| * 根据主键删除用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 操作影响行数 | |||||
| */ | |||||
| public Integer delete(Long id) { | |||||
| return super.deleteById(id); | |||||
| } | |||||
| /** | |||||
| * 根据主键删除用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 操作影响行数 | |||||
| */ | |||||
| public Integer delete(Long id) { | |||||
| return super.deleteById(id); | |||||
| } | |||||
| /** | |||||
| * 更新用户 | |||||
| * | |||||
| * @param user 用户对象 | |||||
| * @param id 主键id | |||||
| * @return 操作影响行数 | |||||
| */ | |||||
| public Integer update(User user, Long id) { | |||||
| return super.updateById(user, id, true); | |||||
| } | |||||
| /** | |||||
| * 更新用户 | |||||
| * | |||||
| * @param user 用户对象 | |||||
| * @param id 主键id | |||||
| * @return 操作影响行数 | |||||
| */ | |||||
| public Integer update(User user, Long id) { | |||||
| return super.updateById(user, id, true); | |||||
| } | |||||
| /** | |||||
| * 根据主键获取用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return id对应的用户 | |||||
| */ | |||||
| public User selectById(Long id) { | |||||
| return super.findOneById(id); | |||||
| } | |||||
| /** | |||||
| * 根据主键获取用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return id对应的用户 | |||||
| */ | |||||
| public User selectById(Long id) { | |||||
| return super.findOneById(id); | |||||
| } | |||||
| /** | |||||
| * 根据查询条件获取用户列表 | |||||
| * | |||||
| * @param user 用户查询条件 | |||||
| * @return 用户列表 | |||||
| */ | |||||
| public List<User> selectUserList(User user) { | |||||
| return super.findByExample(user); | |||||
| } | |||||
| /** | |||||
| * 根据查询条件获取用户列表 | |||||
| * | |||||
| * @param user 用户查询条件 | |||||
| * @return 用户列表 | |||||
| */ | |||||
| public List<User> selectUserList(User user) { | |||||
| return super.findByExample(user); | |||||
| } | |||||
| } | } | ||||
| @@ -35,201 +35,201 @@ import java.util.stream.Stream; | |||||
| */ | */ | ||||
| @Slf4j | @Slf4j | ||||
| public class BaseDao<T, P> { | public class BaseDao<T, P> { | ||||
| private JdbcTemplate jdbcTemplate; | |||||
| private Class<T> clazz; | |||||
| @SuppressWarnings(value = "unchecked") | |||||
| public BaseDao(JdbcTemplate jdbcTemplate) { | |||||
| this.jdbcTemplate = jdbcTemplate; | |||||
| clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; | |||||
| } | |||||
| /** | |||||
| * 通用插入,自增列需要添加 {@link Pk} 注解 | |||||
| * | |||||
| * @param t 对象 | |||||
| * @param ignoreNull 是否忽略 null 值 | |||||
| * @return 操作的行数 | |||||
| */ | |||||
| protected Integer insert(T t, Boolean ignoreNull) { | |||||
| String table = getTableName(t); | |||||
| List<Field> filterField = getField(t, ignoreNull); | |||||
| List<String> columnList = getColumns(filterField); | |||||
| String columns = StrUtil.join(Const.SEPARATOR_COMMA, columnList); | |||||
| // 构造占位符 | |||||
| String params = StrUtil.repeatAndJoin("?", columnList.size(), Const.SEPARATOR_COMMA); | |||||
| // 构造值 | |||||
| Object[] values = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).toArray(); | |||||
| String sql = StrUtil.format("INSERT INTO {table} ({columns}) VALUES ({params})", Dict.create().set("table", table).set("columns", columns).set("params", params)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); | |||||
| return jdbcTemplate.update(sql, values); | |||||
| } | |||||
| /** | |||||
| * 通用根据主键删除 | |||||
| * | |||||
| * @param pk 主键 | |||||
| * @return 影响行数 | |||||
| */ | |||||
| protected Integer deleteById(P pk) { | |||||
| String tableName = getTableName(); | |||||
| String sql = StrUtil.format("DELETE FROM {table} where id = ?", Dict.create().set("table", tableName)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(pk)); | |||||
| return jdbcTemplate.update(sql, pk); | |||||
| } | |||||
| /** | |||||
| * 通用根据主键更新,自增列需要添加 {@link Pk} 注解 | |||||
| * | |||||
| * @param t 对象 | |||||
| * @param pk 主键 | |||||
| * @param ignoreNull 是否忽略 null 值 | |||||
| * @return 操作的行数 | |||||
| */ | |||||
| protected Integer updateById(T t, P pk, Boolean ignoreNull) { | |||||
| String tableName = getTableName(t); | |||||
| List<Field> filterField = getField(t, ignoreNull); | |||||
| List<String> columnList = getColumns(filterField); | |||||
| List<String> columns = columnList.stream().map(s -> StrUtil.appendIfMissing(s, " = ?")).collect(Collectors.toList()); | |||||
| String params = StrUtil.join(Const.SEPARATOR_COMMA, columns); | |||||
| // 构造值 | |||||
| List<Object> valueList = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).collect(Collectors.toList()); | |||||
| valueList.add(pk); | |||||
| Object[] values = ArrayUtil.toArray(valueList, Object.class); | |||||
| String sql = StrUtil.format("UPDATE {table} SET {params} where id = ?", Dict.create().set("table", tableName).set("params", params)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); | |||||
| return jdbcTemplate.update(sql, values); | |||||
| } | |||||
| /** | |||||
| * 通用根据主键查询单条记录 | |||||
| * | |||||
| * @param pk 主键 | |||||
| * @return 单条记录 | |||||
| */ | |||||
| public T findOneById(P pk) { | |||||
| String tableName = getTableName(); | |||||
| String sql = StrUtil.format("SELECT * FROM {table} where id = ?", Dict.create().set("table", tableName)); | |||||
| RowMapper<T> rowMapper = new BeanPropertyRowMapper<>(clazz); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(pk)); | |||||
| return jdbcTemplate.queryForObject(sql, new Object[]{pk}, rowMapper); | |||||
| } | |||||
| /** | |||||
| * 根据对象查询 | |||||
| * | |||||
| * @param t 查询条件 | |||||
| * @return 对象列表 | |||||
| */ | |||||
| public List<T> findByExample(T t) { | |||||
| String tableName = getTableName(t); | |||||
| List<Field> filterField = getField(t, true); | |||||
| List<String> columnList = getColumns(filterField); | |||||
| List<String> columns = columnList.stream().map(s -> " and " + s + " = ? ").collect(Collectors.toList()); | |||||
| String where = StrUtil.join(" ", columns); | |||||
| // 构造值 | |||||
| Object[] values = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).toArray(); | |||||
| String sql = StrUtil.format("SELECT * FROM {table} where 1=1 {where}", Dict.create().set("table", tableName).set("where", StrUtil.isBlank(where) ? "" : where)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); | |||||
| List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, values); | |||||
| List<T> ret = CollUtil.newArrayList(); | |||||
| maps.forEach(map -> ret.add(BeanUtil.fillBeanWithMap(map, ReflectUtil.newInstance(clazz), true, false))); | |||||
| return ret; | |||||
| } | |||||
| /** | |||||
| * 获取表名 | |||||
| * | |||||
| * @param t 对象 | |||||
| * @return 表名 | |||||
| */ | |||||
| private String getTableName(T t) { | |||||
| Table tableAnnotation = t.getClass().getAnnotation(Table.class); | |||||
| if (ObjectUtil.isNotNull(tableAnnotation)) { | |||||
| return StrUtil.format("`{}`", tableAnnotation.name()); | |||||
| } else { | |||||
| return StrUtil.format("`{}`", t.getClass().getName().toLowerCase()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取表名 | |||||
| * | |||||
| * @return 表名 | |||||
| */ | |||||
| private String getTableName() { | |||||
| Table tableAnnotation = clazz.getAnnotation(Table.class); | |||||
| if (ObjectUtil.isNotNull(tableAnnotation)) { | |||||
| return StrUtil.format("`{}`", tableAnnotation.name()); | |||||
| } else { | |||||
| return StrUtil.format("`{}`", clazz.getName().toLowerCase()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取列 | |||||
| * | |||||
| * @param fieldList 字段列表 | |||||
| * @return 列信息列表 | |||||
| */ | |||||
| private List<String> getColumns(List<Field> fieldList) { | |||||
| // 构造列 | |||||
| List<String> columnList = CollUtil.newArrayList(); | |||||
| for (Field field : fieldList) { | |||||
| Column columnAnnotation = field.getAnnotation(Column.class); | |||||
| String columnName; | |||||
| if (ObjectUtil.isNotNull(columnAnnotation)) { | |||||
| columnName = columnAnnotation.name(); | |||||
| } else { | |||||
| columnName = field.getName(); | |||||
| } | |||||
| columnList.add(StrUtil.format("`{}`", columnName)); | |||||
| } | |||||
| return columnList; | |||||
| } | |||||
| /** | |||||
| * 获取字段列表 {@code 过滤数据库中不存在的字段,以及自增列} | |||||
| * | |||||
| * @param t 对象 | |||||
| * @param ignoreNull 是否忽略空值 | |||||
| * @return 字段列表 | |||||
| */ | |||||
| private List<Field> getField(T t, Boolean ignoreNull) { | |||||
| // 获取所有字段,包含父类中的字段 | |||||
| Field[] fields = ReflectUtil.getFields(t.getClass()); | |||||
| // 过滤数据库中不存在的字段,以及自增列 | |||||
| List<Field> filterField; | |||||
| Stream<Field> fieldStream = CollUtil.toList(fields).stream().filter(field -> ObjectUtil.isNull(field.getAnnotation(Ignore.class)) || ObjectUtil.isNull(field.getAnnotation(Pk.class))); | |||||
| // 是否过滤字段值为null的字段 | |||||
| if (ignoreNull) { | |||||
| filterField = fieldStream.filter(field -> ObjectUtil.isNotNull(ReflectUtil.getFieldValue(t, field))).collect(Collectors.toList()); | |||||
| } else { | |||||
| filterField = fieldStream.collect(Collectors.toList()); | |||||
| } | |||||
| return filterField; | |||||
| } | |||||
| private JdbcTemplate jdbcTemplate; | |||||
| private Class<T> clazz; | |||||
| @SuppressWarnings(value = "unchecked") | |||||
| public BaseDao(JdbcTemplate jdbcTemplate) { | |||||
| this.jdbcTemplate = jdbcTemplate; | |||||
| clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; | |||||
| } | |||||
| /** | |||||
| * 通用插入,自增列需要添加 {@link Pk} 注解 | |||||
| * | |||||
| * @param t 对象 | |||||
| * @param ignoreNull 是否忽略 null 值 | |||||
| * @return 操作的行数 | |||||
| */ | |||||
| protected Integer insert(T t, Boolean ignoreNull) { | |||||
| String table = getTableName(t); | |||||
| List<Field> filterField = getField(t, ignoreNull); | |||||
| List<String> columnList = getColumns(filterField); | |||||
| String columns = StrUtil.join(Const.SEPARATOR_COMMA, columnList); | |||||
| // 构造占位符 | |||||
| String params = StrUtil.repeatAndJoin("?", columnList.size(), Const.SEPARATOR_COMMA); | |||||
| // 构造值 | |||||
| Object[] values = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).toArray(); | |||||
| String sql = StrUtil.format("INSERT INTO {table} ({columns}) VALUES ({params})", Dict.create().set("table", table).set("columns", columns).set("params", params)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); | |||||
| return jdbcTemplate.update(sql, values); | |||||
| } | |||||
| /** | |||||
| * 通用根据主键删除 | |||||
| * | |||||
| * @param pk 主键 | |||||
| * @return 影响行数 | |||||
| */ | |||||
| protected Integer deleteById(P pk) { | |||||
| String tableName = getTableName(); | |||||
| String sql = StrUtil.format("DELETE FROM {table} where id = ?", Dict.create().set("table", tableName)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(pk)); | |||||
| return jdbcTemplate.update(sql, pk); | |||||
| } | |||||
| /** | |||||
| * 通用根据主键更新,自增列需要添加 {@link Pk} 注解 | |||||
| * | |||||
| * @param t 对象 | |||||
| * @param pk 主键 | |||||
| * @param ignoreNull 是否忽略 null 值 | |||||
| * @return 操作的行数 | |||||
| */ | |||||
| protected Integer updateById(T t, P pk, Boolean ignoreNull) { | |||||
| String tableName = getTableName(t); | |||||
| List<Field> filterField = getField(t, ignoreNull); | |||||
| List<String> columnList = getColumns(filterField); | |||||
| List<String> columns = columnList.stream().map(s -> StrUtil.appendIfMissing(s, " = ?")).collect(Collectors.toList()); | |||||
| String params = StrUtil.join(Const.SEPARATOR_COMMA, columns); | |||||
| // 构造值 | |||||
| List<Object> valueList = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).collect(Collectors.toList()); | |||||
| valueList.add(pk); | |||||
| Object[] values = ArrayUtil.toArray(valueList, Object.class); | |||||
| String sql = StrUtil.format("UPDATE {table} SET {params} where id = ?", Dict.create().set("table", tableName).set("params", params)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); | |||||
| return jdbcTemplate.update(sql, values); | |||||
| } | |||||
| /** | |||||
| * 通用根据主键查询单条记录 | |||||
| * | |||||
| * @param pk 主键 | |||||
| * @return 单条记录 | |||||
| */ | |||||
| public T findOneById(P pk) { | |||||
| String tableName = getTableName(); | |||||
| String sql = StrUtil.format("SELECT * FROM {table} where id = ?", Dict.create().set("table", tableName)); | |||||
| RowMapper<T> rowMapper = new BeanPropertyRowMapper<>(clazz); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(pk)); | |||||
| return jdbcTemplate.queryForObject(sql, new Object[]{pk}, rowMapper); | |||||
| } | |||||
| /** | |||||
| * 根据对象查询 | |||||
| * | |||||
| * @param t 查询条件 | |||||
| * @return 对象列表 | |||||
| */ | |||||
| public List<T> findByExample(T t) { | |||||
| String tableName = getTableName(t); | |||||
| List<Field> filterField = getField(t, true); | |||||
| List<String> columnList = getColumns(filterField); | |||||
| List<String> columns = columnList.stream().map(s -> " and " + s + " = ? ").collect(Collectors.toList()); | |||||
| String where = StrUtil.join(" ", columns); | |||||
| // 构造值 | |||||
| Object[] values = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).toArray(); | |||||
| String sql = StrUtil.format("SELECT * FROM {table} where 1=1 {where}", Dict.create().set("table", tableName).set("where", StrUtil.isBlank(where) ? "" : where)); | |||||
| log.debug("【执行SQL】SQL:{}", sql); | |||||
| log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); | |||||
| List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, values); | |||||
| List<T> ret = CollUtil.newArrayList(); | |||||
| maps.forEach(map -> ret.add(BeanUtil.fillBeanWithMap(map, ReflectUtil.newInstance(clazz), true, false))); | |||||
| return ret; | |||||
| } | |||||
| /** | |||||
| * 获取表名 | |||||
| * | |||||
| * @param t 对象 | |||||
| * @return 表名 | |||||
| */ | |||||
| private String getTableName(T t) { | |||||
| Table tableAnnotation = t.getClass().getAnnotation(Table.class); | |||||
| if (ObjectUtil.isNotNull(tableAnnotation)) { | |||||
| return StrUtil.format("`{}`", tableAnnotation.name()); | |||||
| } else { | |||||
| return StrUtil.format("`{}`", t.getClass().getName().toLowerCase()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取表名 | |||||
| * | |||||
| * @return 表名 | |||||
| */ | |||||
| private String getTableName() { | |||||
| Table tableAnnotation = clazz.getAnnotation(Table.class); | |||||
| if (ObjectUtil.isNotNull(tableAnnotation)) { | |||||
| return StrUtil.format("`{}`", tableAnnotation.name()); | |||||
| } else { | |||||
| return StrUtil.format("`{}`", clazz.getName().toLowerCase()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 获取列 | |||||
| * | |||||
| * @param fieldList 字段列表 | |||||
| * @return 列信息列表 | |||||
| */ | |||||
| private List<String> getColumns(List<Field> fieldList) { | |||||
| // 构造列 | |||||
| List<String> columnList = CollUtil.newArrayList(); | |||||
| for (Field field : fieldList) { | |||||
| Column columnAnnotation = field.getAnnotation(Column.class); | |||||
| String columnName; | |||||
| if (ObjectUtil.isNotNull(columnAnnotation)) { | |||||
| columnName = columnAnnotation.name(); | |||||
| } else { | |||||
| columnName = field.getName(); | |||||
| } | |||||
| columnList.add(StrUtil.format("`{}`", columnName)); | |||||
| } | |||||
| return columnList; | |||||
| } | |||||
| /** | |||||
| * 获取字段列表 {@code 过滤数据库中不存在的字段,以及自增列} | |||||
| * | |||||
| * @param t 对象 | |||||
| * @param ignoreNull 是否忽略空值 | |||||
| * @return 字段列表 | |||||
| */ | |||||
| private List<Field> getField(T t, Boolean ignoreNull) { | |||||
| // 获取所有字段,包含父类中的字段 | |||||
| Field[] fields = ReflectUtil.getFields(t.getClass()); | |||||
| // 过滤数据库中不存在的字段,以及自增列 | |||||
| List<Field> filterField; | |||||
| Stream<Field> fieldStream = CollUtil.toList(fields).stream().filter(field -> ObjectUtil.isNull(field.getAnnotation(Ignore.class)) || ObjectUtil.isNull(field.getAnnotation(Pk.class))); | |||||
| // 是否过滤字段值为null的字段 | |||||
| if (ignoreNull) { | |||||
| filterField = fieldStream.filter(field -> ObjectUtil.isNotNull(ReflectUtil.getFieldValue(t, field))).collect(Collectors.toList()); | |||||
| } else { | |||||
| filterField = fieldStream.collect(Collectors.toList()); | |||||
| } | |||||
| return filterField; | |||||
| } | |||||
| } | } | ||||
| @@ -1,7 +1,7 @@ | |||||
| package com.xkcoding.orm.jdbctemplate.entity; | package com.xkcoding.orm.jdbctemplate.entity; | ||||
| import com.xkcoding.orm.jdbctemplate.annotation.Pk; | |||||
| import com.xkcoding.orm.jdbctemplate.annotation.Column; | import com.xkcoding.orm.jdbctemplate.annotation.Column; | ||||
| import com.xkcoding.orm.jdbctemplate.annotation.Pk; | |||||
| import com.xkcoding.orm.jdbctemplate.annotation.Table; | import com.xkcoding.orm.jdbctemplate.annotation.Table; | ||||
| import lombok.Data; | import lombok.Data; | ||||
| @@ -19,58 +19,58 @@ import java.util.Date; | |||||
| @Data | @Data | ||||
| @Table(name = "orm_user") | @Table(name = "orm_user") | ||||
| public class User implements Serializable { | public class User implements Serializable { | ||||
| /** | |||||
| * 主键 | |||||
| */ | |||||
| @Pk | |||||
| private Long id; | |||||
| /** | |||||
| * 主键 | |||||
| */ | |||||
| @Pk | |||||
| private Long id; | |||||
| /** | |||||
| * 用户名 | |||||
| */ | |||||
| private String name; | |||||
| /** | |||||
| * 用户名 | |||||
| */ | |||||
| private String name; | |||||
| /** | |||||
| * 加密后的密码 | |||||
| */ | |||||
| private String password; | |||||
| /** | |||||
| * 加密后的密码 | |||||
| */ | |||||
| private String password; | |||||
| /** | |||||
| * 加密使用的盐 | |||||
| */ | |||||
| private String salt; | |||||
| /** | |||||
| * 加密使用的盐 | |||||
| */ | |||||
| private String salt; | |||||
| /** | |||||
| * 邮箱 | |||||
| */ | |||||
| private String email; | |||||
| /** | |||||
| * 邮箱 | |||||
| */ | |||||
| private String email; | |||||
| /** | |||||
| * 手机号码 | |||||
| */ | |||||
| @Column(name = "phone_number") | |||||
| private String phoneNumber; | |||||
| /** | |||||
| * 手机号码 | |||||
| */ | |||||
| @Column(name = "phone_number") | |||||
| private String phoneNumber; | |||||
| /** | |||||
| * 状态,-1:逻辑删除,0:禁用,1:启用 | |||||
| */ | |||||
| private Integer status; | |||||
| /** | |||||
| * 状态,-1:逻辑删除,0:禁用,1:启用 | |||||
| */ | |||||
| private Integer status; | |||||
| /** | |||||
| * 创建时间 | |||||
| */ | |||||
| @Column(name = "create_time") | |||||
| private Date createTime; | |||||
| /** | |||||
| * 创建时间 | |||||
| */ | |||||
| @Column(name = "create_time") | |||||
| private Date createTime; | |||||
| /** | |||||
| * 上次登录时间 | |||||
| */ | |||||
| @Column(name = "last_login_time") | |||||
| private Date lastLoginTime; | |||||
| /** | |||||
| * 上次登录时间 | |||||
| */ | |||||
| @Column(name = "last_login_time") | |||||
| private Date lastLoginTime; | |||||
| /** | |||||
| * 上次更新时间 | |||||
| */ | |||||
| @Column(name = "last_update_time") | |||||
| private Date lastUpdateTime; | |||||
| /** | |||||
| * 上次更新时间 | |||||
| */ | |||||
| @Column(name = "last_update_time") | |||||
| private Date lastUpdateTime; | |||||
| } | } | ||||
| @@ -13,45 +13,45 @@ import java.util.List; | |||||
| * @date Created in 2018-10-15 13:51 | * @date Created in 2018-10-15 13:51 | ||||
| */ | */ | ||||
| public interface IUserService { | public interface IUserService { | ||||
| /** | |||||
| * 保存用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 保存成功 {@code true} 保存失败 {@code false} | |||||
| */ | |||||
| Boolean save(User user); | |||||
| /** | |||||
| * 删除用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 删除成功 {@code true} 删除失败 {@code false} | |||||
| */ | |||||
| Boolean delete(Long id); | |||||
| /** | |||||
| * 更新用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @param id 主键id | |||||
| * @return 更新成功 {@code true} 更新失败 {@code false} | |||||
| */ | |||||
| Boolean update(User user, Long id); | |||||
| /** | |||||
| * 获取单个用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 单个用户对象 | |||||
| */ | |||||
| User getUser(Long id); | |||||
| /** | |||||
| * 获取用户列表 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 用户列表 | |||||
| */ | |||||
| List<User> getUser(User user); | |||||
| /** | |||||
| * 保存用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 保存成功 {@code true} 保存失败 {@code false} | |||||
| */ | |||||
| Boolean save(User user); | |||||
| /** | |||||
| * 删除用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 删除成功 {@code true} 删除失败 {@code false} | |||||
| */ | |||||
| Boolean delete(Long id); | |||||
| /** | |||||
| * 更新用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @param id 主键id | |||||
| * @return 更新成功 {@code true} 更新失败 {@code false} | |||||
| */ | |||||
| Boolean update(User user, Long id); | |||||
| /** | |||||
| * 获取单个用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 单个用户对象 | |||||
| */ | |||||
| User getUser(Long id); | |||||
| /** | |||||
| * 获取用户列表 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 用户列表 | |||||
| */ | |||||
| List<User> getUser(User user); | |||||
| } | } | ||||
| @@ -25,81 +25,81 @@ import java.util.List; | |||||
| */ | */ | ||||
| @Service | @Service | ||||
| public class UserServiceImpl implements IUserService { | public class UserServiceImpl implements IUserService { | ||||
| private final UserDao userDao; | |||||
| private final UserDao userDao; | |||||
| @Autowired | |||||
| public UserServiceImpl(UserDao userDao) { | |||||
| this.userDao = userDao; | |||||
| } | |||||
| @Autowired | |||||
| public UserServiceImpl(UserDao userDao) { | |||||
| this.userDao = userDao; | |||||
| } | |||||
| /** | |||||
| * 保存用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 保存成功 {@code true} 保存失败 {@code false} | |||||
| */ | |||||
| @Override | |||||
| public Boolean save(User user) { | |||||
| String rawPass = user.getPassword(); | |||||
| String salt = IdUtil.simpleUUID(); | |||||
| String pass = SecureUtil.md5(rawPass + Const.SALT_PREFIX + salt); | |||||
| user.setPassword(pass); | |||||
| user.setSalt(salt); | |||||
| return userDao.insert(user) > 0; | |||||
| } | |||||
| /** | |||||
| * 保存用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 保存成功 {@code true} 保存失败 {@code false} | |||||
| */ | |||||
| @Override | |||||
| public Boolean save(User user) { | |||||
| String rawPass = user.getPassword(); | |||||
| String salt = IdUtil.simpleUUID(); | |||||
| String pass = SecureUtil.md5(rawPass + Const.SALT_PREFIX + salt); | |||||
| user.setPassword(pass); | |||||
| user.setSalt(salt); | |||||
| return userDao.insert(user) > 0; | |||||
| } | |||||
| /** | |||||
| * 删除用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 删除成功 {@code true} 删除失败 {@code false} | |||||
| */ | |||||
| @Override | |||||
| public Boolean delete(Long id) { | |||||
| return userDao.delete(id) > 0; | |||||
| } | |||||
| /** | |||||
| * 删除用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 删除成功 {@code true} 删除失败 {@code false} | |||||
| */ | |||||
| @Override | |||||
| public Boolean delete(Long id) { | |||||
| return userDao.delete(id) > 0; | |||||
| } | |||||
| /** | |||||
| * 更新用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @param id 主键id | |||||
| * @return 更新成功 {@code true} 更新失败 {@code false} | |||||
| */ | |||||
| @Override | |||||
| public Boolean update(User user, Long id) { | |||||
| User exist = getUser(id); | |||||
| if (StrUtil.isNotBlank(user.getPassword())) { | |||||
| String rawPass = user.getPassword(); | |||||
| String salt = IdUtil.simpleUUID(); | |||||
| String pass = SecureUtil.md5(rawPass + Const.SALT_PREFIX + salt); | |||||
| user.setPassword(pass); | |||||
| user.setSalt(salt); | |||||
| } | |||||
| BeanUtil.copyProperties(user, exist, CopyOptions.create().setIgnoreNullValue(true)); | |||||
| exist.setLastUpdateTime(new DateTime()); | |||||
| return userDao.update(exist, id) > 0; | |||||
| } | |||||
| /** | |||||
| * 更新用户 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @param id 主键id | |||||
| * @return 更新成功 {@code true} 更新失败 {@code false} | |||||
| */ | |||||
| @Override | |||||
| public Boolean update(User user, Long id) { | |||||
| User exist = getUser(id); | |||||
| if (StrUtil.isNotBlank(user.getPassword())) { | |||||
| String rawPass = user.getPassword(); | |||||
| String salt = IdUtil.simpleUUID(); | |||||
| String pass = SecureUtil.md5(rawPass + Const.SALT_PREFIX + salt); | |||||
| user.setPassword(pass); | |||||
| user.setSalt(salt); | |||||
| } | |||||
| BeanUtil.copyProperties(user, exist, CopyOptions.create().setIgnoreNullValue(true)); | |||||
| exist.setLastUpdateTime(new DateTime()); | |||||
| return userDao.update(exist, id) > 0; | |||||
| } | |||||
| /** | |||||
| * 获取单个用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 单个用户对象 | |||||
| */ | |||||
| @Override | |||||
| public User getUser(Long id) { | |||||
| return userDao.findOneById(id); | |||||
| } | |||||
| /** | |||||
| * 获取单个用户 | |||||
| * | |||||
| * @param id 主键id | |||||
| * @return 单个用户对象 | |||||
| */ | |||||
| @Override | |||||
| public User getUser(Long id) { | |||||
| return userDao.findOneById(id); | |||||
| } | |||||
| /** | |||||
| * 获取用户列表 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 用户列表 | |||||
| */ | |||||
| @Override | |||||
| public List<User> getUser(User user) { | |||||
| return userDao.findByExample(user); | |||||
| } | |||||
| /** | |||||
| * 获取用户列表 | |||||
| * | |||||
| * @param user 用户实体 | |||||
| * @return 用户列表 | |||||
| */ | |||||
| @Override | |||||
| public List<User> getUser(User user) { | |||||
| return userDao.findByExample(user); | |||||
| } | |||||
| } | } | ||||
| @@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoOrmJpaApplication { | public class SpringBootDemoOrmJpaApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoOrmJpaApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoOrmJpaApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -93,7 +93,7 @@ public class UserMapperTest extends SpringBootDemoOrmMybatisMapperPageApplicatio | |||||
| * 测试通用Mapper - 查询单个 | * 测试通用Mapper - 查询单个 | ||||
| */ | */ | ||||
| @Test | @Test | ||||
| public void testQueryOne(){ | |||||
| public void testQueryOne() { | |||||
| User user = userMapper.selectByPrimaryKey(1L); | User user = userMapper.selectByPrimaryKey(1L); | ||||
| Assert.assertNotNull(user); | Assert.assertNotNull(user); | ||||
| log.debug("【user】= {}", user); | log.debug("【user】= {}", user); | ||||
| @@ -23,7 +23,7 @@ public class MybatisPlusConfig { | |||||
| * 性能分析拦截器,不建议生产使用 | * 性能分析拦截器,不建议生产使用 | ||||
| */ | */ | ||||
| @Bean | @Bean | ||||
| public PerformanceInterceptor performanceInterceptor(){ | |||||
| public PerformanceInterceptor performanceInterceptor() { | |||||
| return new PerformanceInterceptor(); | return new PerformanceInterceptor(); | ||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoOrmMybatisPlusApplicationTests { | public class SpringBootDemoOrmMybatisPlusApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| public class SpringBootDemoPropertiesApplication { | public class SpringBootDemoPropertiesApplication { | ||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoPropertiesApplication.class, args); | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(SpringBootDemoPropertiesApplication.class, args); | |||||
| } | |||||
| } | } | ||||
| @@ -17,17 +17,17 @@ import org.springframework.web.bind.annotation.RestController; | |||||
| */ | */ | ||||
| @RestController | @RestController | ||||
| public class PropertyController { | public class PropertyController { | ||||
| private final ApplicationProperty applicationProperty; | |||||
| private final DeveloperProperty developerProperty; | |||||
| private final ApplicationProperty applicationProperty; | |||||
| private final DeveloperProperty developerProperty; | |||||
| @Autowired | |||||
| public PropertyController(ApplicationProperty applicationProperty, DeveloperProperty developerProperty) { | |||||
| this.applicationProperty = applicationProperty; | |||||
| this.developerProperty = developerProperty; | |||||
| } | |||||
| @Autowired | |||||
| public PropertyController(ApplicationProperty applicationProperty, DeveloperProperty developerProperty) { | |||||
| this.applicationProperty = applicationProperty; | |||||
| this.developerProperty = developerProperty; | |||||
| } | |||||
| @GetMapping("/property") | |||||
| public Dict index() { | |||||
| return Dict.create().set("applicationProperty", applicationProperty).set("developerProperty", developerProperty); | |||||
| } | |||||
| @GetMapping("/property") | |||||
| public Dict index() { | |||||
| return Dict.create().set("applicationProperty", applicationProperty).set("developerProperty", developerProperty); | |||||
| } | |||||
| } | } | ||||
| @@ -15,8 +15,8 @@ import org.springframework.stereotype.Component; | |||||
| @Data | @Data | ||||
| @Component | @Component | ||||
| public class ApplicationProperty { | public class ApplicationProperty { | ||||
| @Value("${application.name}") | |||||
| private String name; | |||||
| @Value("${application.version}") | |||||
| private String version; | |||||
| @Value("${application.name}") | |||||
| private String name; | |||||
| @Value("${application.version}") | |||||
| private String version; | |||||
| } | } | ||||
| @@ -16,8 +16,8 @@ import org.springframework.stereotype.Component; | |||||
| @ConfigurationProperties(prefix = "developer") | @ConfigurationProperties(prefix = "developer") | ||||
| @Component | @Component | ||||
| public class DeveloperProperty { | public class DeveloperProperty { | ||||
| private String name; | |||||
| private String website; | |||||
| private String qq; | |||||
| private String phoneNumber; | |||||
| private String name; | |||||
| private String website; | |||||
| private String qq; | |||||
| private String phoneNumber; | |||||
| } | } | ||||
| @@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||||
| @SpringBootTest | @SpringBootTest | ||||
| public class SpringBootDemoPropertiesApplicationTests { | public class SpringBootDemoPropertiesApplicationTests { | ||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| @Test | |||||
| public void contextLoads() { | |||||
| } | |||||
| } | } | ||||
| @@ -54,7 +54,7 @@ public class RateLimiterAspect { | |||||
| String key = rateLimiter.key(); | String key = rateLimiter.key(); | ||||
| // 默认用类名+方法名做限流的 key 前缀 | // 默认用类名+方法名做限流的 key 前缀 | ||||
| if (StrUtil.isBlank(key)) { | if (StrUtil.isBlank(key)) { | ||||
| key = method.getDeclaringClass().getName()+StrUtil.DOT+method.getName(); | |||||
| key = method.getDeclaringClass().getName() + StrUtil.DOT + method.getName(); | |||||
| } | } | ||||
| // 最终限流的 key 为 前缀 + IP地址 | // 最终限流的 key 为 前缀 + IP地址 | ||||
| // TODO: 此时需要考虑局域网多用户访问的情况,因此 key 后续需要加上方法参数更加合理 | // TODO: 此时需要考虑局域网多用户访问的情况,因此 key 后续需要加上方法参数更加合理 | ||||
| @@ -14,29 +14,29 @@ import lombok.EqualsAndHashCode; | |||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||
| @Data | @Data | ||||
| public class BaseException extends RuntimeException { | public class BaseException extends RuntimeException { | ||||
| private Integer code; | |||||
| private String message; | |||||
| private Object data; | |||||
| private Integer code; | |||||
| private String message; | |||||
| private Object data; | |||||
| public BaseException(Status status) { | |||||
| super(status.getMessage()); | |||||
| this.code = status.getCode(); | |||||
| this.message = status.getMessage(); | |||||
| } | |||||
| public BaseException(Status status) { | |||||
| super(status.getMessage()); | |||||
| this.code = status.getCode(); | |||||
| this.message = status.getMessage(); | |||||
| } | |||||
| public BaseException(Status status, Object data) { | |||||
| this(status); | |||||
| this.data = data; | |||||
| } | |||||
| public BaseException(Status status, Object data) { | |||||
| this(status); | |||||
| this.data = data; | |||||
| } | |||||
| public BaseException(Integer code, String message) { | |||||
| super(message); | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public BaseException(Integer code, String message) { | |||||
| super(message); | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public BaseException(Integer code, String message, Object data) { | |||||
| this(code, message); | |||||
| this.data = data; | |||||
| } | |||||
| public BaseException(Integer code, String message, Object data) { | |||||
| this(code, message); | |||||
| this.data = data; | |||||
| } | |||||
| } | } | ||||
| @@ -110,8 +110,7 @@ public enum Status implements IStatus { | |||||
| public static Status fromCode(Integer code) { | public static Status fromCode(Integer code) { | ||||
| Status[] statuses = Status.values(); | Status[] statuses = Status.values(); | ||||
| for (Status status : statuses) { | for (Status status : statuses) { | ||||
| if (status.getCode() | |||||
| .equals(code)) { | |||||
| if (status.getCode().equals(code)) { | |||||
| return status; | return status; | ||||
| } | } | ||||
| } | } | ||||
| @@ -65,8 +65,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | |||||
| UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | ||||
| authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | ||||
| SecurityContextHolder.getContext() | |||||
| .setAuthentication(authentication); | |||||
| SecurityContextHolder.getContext().setAuthentication(authentication); | |||||
| filterChain.doFilter(request, response); | filterChain.doFilter(request, response); | ||||
| } catch (SecurityException e) { | } catch (SecurityException e) { | ||||
| ResponseUtil.renderJson(response, e); | ResponseUtil.renderJson(response, e); | ||||
| @@ -95,43 +94,34 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | |||||
| switch (httpMethod) { | switch (httpMethod) { | ||||
| case GET: | case GET: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getGet()); | |||||
| ignores.addAll(customConfig.getIgnores().getGet()); | |||||
| break; | break; | ||||
| case PUT: | case PUT: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getPut()); | |||||
| ignores.addAll(customConfig.getIgnores().getPut()); | |||||
| break; | break; | ||||
| case HEAD: | case HEAD: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getHead()); | |||||
| ignores.addAll(customConfig.getIgnores().getHead()); | |||||
| break; | break; | ||||
| case POST: | case POST: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getPost()); | |||||
| ignores.addAll(customConfig.getIgnores().getPost()); | |||||
| break; | break; | ||||
| case PATCH: | case PATCH: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getPatch()); | |||||
| ignores.addAll(customConfig.getIgnores().getPatch()); | |||||
| break; | break; | ||||
| case TRACE: | case TRACE: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getTrace()); | |||||
| ignores.addAll(customConfig.getIgnores().getTrace()); | |||||
| break; | break; | ||||
| case DELETE: | case DELETE: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getDelete()); | |||||
| ignores.addAll(customConfig.getIgnores().getDelete()); | |||||
| break; | break; | ||||
| case OPTIONS: | case OPTIONS: | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getOptions()); | |||||
| ignores.addAll(customConfig.getIgnores().getOptions()); | |||||
| break; | break; | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| ignores.addAll(customConfig.getIgnores() | |||||
| .getPattern()); | |||||
| ignores.addAll(customConfig.getIgnores().getPattern()); | |||||
| if (CollUtil.isNotEmpty(ignores)) { | if (CollUtil.isNotEmpty(ignores)) { | ||||
| for (String ignore : ignores) { | for (String ignore : ignores) { | ||||
| @@ -58,20 +58,17 @@ public class RbacAuthorityService { | |||||
| Long userId = principal.getId(); | Long userId = principal.getId(); | ||||
| List<Role> roles = roleDao.selectByUserId(userId); | List<Role> roles = roleDao.selectByUserId(userId); | ||||
| List<Long> roleIds = roles.stream() | |||||
| .map(Role::getId) | |||||
| .collect(Collectors.toList()); | |||||
| List<Long> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList()); | |||||
| List<Permission> permissions = permissionDao.selectByRoleIdList(roleIds); | List<Permission> permissions = permissionDao.selectByRoleIdList(roleIds); | ||||
| //获取资源,前后端分离,所以过滤页面权限,只保留按钮权限 | //获取资源,前后端分离,所以过滤页面权限,只保留按钮权限 | ||||
| List<Permission> btnPerms = permissions.stream() | List<Permission> btnPerms = permissions.stream() | ||||
| // 过滤页面权限 | |||||
| .filter(permission -> Objects.equals(permission.getType(), Consts.BUTTON)) | |||||
| // 过滤 URL 为空 | |||||
| .filter(permission -> StrUtil.isNotBlank(permission.getUrl())) | |||||
| // 过滤 METHOD 为空 | |||||
| .filter(permission -> StrUtil.isNotBlank(permission.getMethod())) | |||||
| .collect(Collectors.toList()); | |||||
| // 过滤页面权限 | |||||
| .filter(permission -> Objects.equals(permission.getType(), Consts.BUTTON)) | |||||
| // 过滤 URL 为空 | |||||
| .filter(permission -> StrUtil.isNotBlank(permission.getUrl())) | |||||
| // 过滤 METHOD 为空 | |||||
| .filter(permission -> StrUtil.isNotBlank(permission.getMethod())).collect(Collectors.toList()); | |||||
| for (Permission btnPerm : btnPerms) { | for (Permission btnPerm : btnPerms) { | ||||
| AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(btnPerm.getUrl(), btnPerm.getMethod()); | AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(btnPerm.getUrl(), btnPerm.getMethod()); | ||||
| @@ -104,8 +101,7 @@ public class RbacAuthorityService { | |||||
| // 2:new AntPathRequestMatcher(uri) 这种方式不校验请求方法,只校验请求路径 | // 2:new AntPathRequestMatcher(uri) 这种方式不校验请求方法,只校验请求路径 | ||||
| AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(uri); | AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(uri); | ||||
| if (antPathMatcher.matches(request)) { | if (antPathMatcher.matches(request)) { | ||||
| if (!urlMapping.get(uri) | |||||
| .contains(currentMethod)) { | |||||
| if (!urlMapping.get(uri).contains(currentMethod)) { | |||||
| throw new SecurityException(Status.HTTP_BAD_METHOD); | throw new SecurityException(Status.HTTP_BAD_METHOD); | ||||
| } else { | } else { | ||||
| return; | return; | ||||
| @@ -129,15 +125,11 @@ public class RbacAuthorityService { | |||||
| handlerMethods.forEach((k, v) -> { | handlerMethods.forEach((k, v) -> { | ||||
| // 获取当前 key 下的获取所有URL | // 获取当前 key 下的获取所有URL | ||||
| Set<String> url = k.getPatternsCondition() | |||||
| .getPatterns(); | |||||
| Set<String> url = k.getPatternsCondition().getPatterns(); | |||||
| RequestMethodsRequestCondition method = k.getMethodsCondition(); | RequestMethodsRequestCondition method = k.getMethodsCondition(); | ||||
| // 为每个URL添加所有的请求方法 | // 为每个URL添加所有的请求方法 | ||||
| url.forEach(s -> urlMapping.putAll(s, method.getMethods() | |||||
| .stream() | |||||
| .map(Enum::toString) | |||||
| .collect(Collectors.toList()))); | |||||
| url.forEach(s -> urlMapping.putAll(s, method.getMethods().stream().map(Enum::toString).collect(Collectors.toList()))); | |||||
| }); | }); | ||||
| return urlMapping; | return urlMapping; | ||||
| @@ -19,9 +19,6 @@ public class WebMvcConfig implements WebMvcConfigurer { | |||||
| @Override | @Override | ||||
| public void addCorsMappings(CorsRegistry registry) { | public void addCorsMappings(CorsRegistry registry) { | ||||
| registry.addMapping("/**") | |||||
| .allowedOrigins("*") | |||||
| .allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE") | |||||
| .maxAge(MAX_AGE_SECS); | |||||
| registry.addMapping("/**").allowedOrigins("*").allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE").maxAge(MAX_AGE_SECS); | |||||
| } | } | ||||
| } | } | ||||
| @@ -46,10 +46,9 @@ public class AuthController { | |||||
| public ApiResponse login(@Valid @RequestBody LoginRequest loginRequest) { | public ApiResponse login(@Valid @RequestBody LoginRequest loginRequest) { | ||||
| Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsernameOrEmailOrPhone(), loginRequest.getPassword())); | Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsernameOrEmailOrPhone(), loginRequest.getPassword())); | ||||
| SecurityContextHolder.getContext() | |||||
| .setAuthentication(authentication); | |||||
| SecurityContextHolder.getContext().setAuthentication(authentication); | |||||
| String jwt = jwtUtil.createJWT(authentication,loginRequest.getRememberMe()); | |||||
| String jwt = jwtUtil.createJWT(authentication, loginRequest.getRememberMe()); | |||||
| return ApiResponse.ofSuccess(new JwtResponse(jwt)); | return ApiResponse.ofSuccess(new JwtResponse(jwt)); | ||||
| } | } | ||||
| @@ -53,7 +53,7 @@ public class MonitorController { | |||||
| if (CollUtil.isEmpty(names)) { | if (CollUtil.isEmpty(names)) { | ||||
| throw new SecurityException(Status.PARAM_NOT_NULL); | throw new SecurityException(Status.PARAM_NOT_NULL); | ||||
| } | } | ||||
| if (names.contains(SecurityUtil.getCurrentUsername())){ | |||||
| if (names.contains(SecurityUtil.getCurrentUsername())) { | |||||
| throw new SecurityException(Status.KICKOUT_SELF); | throw new SecurityException(Status.KICKOUT_SELF); | ||||
| } | } | ||||
| monitorService.kickout(names); | monitorService.kickout(names); | ||||
| @@ -42,14 +42,10 @@ public class GlobalExceptionHandler { | |||||
| return ApiResponse.ofStatus(Status.HTTP_BAD_METHOD); | return ApiResponse.ofStatus(Status.HTTP_BAD_METHOD); | ||||
| } else if (e instanceof MethodArgumentNotValidException) { | } else if (e instanceof MethodArgumentNotValidException) { | ||||
| log.error("【全局异常拦截】MethodArgumentNotValidException", e); | log.error("【全局异常拦截】MethodArgumentNotValidException", e); | ||||
| return ApiResponse.of(Status.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult() | |||||
| .getAllErrors() | |||||
| .get(0) | |||||
| .getDefaultMessage(), null); | |||||
| return ApiResponse.of(Status.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors().get(0).getDefaultMessage(), null); | |||||
| } else if (e instanceof ConstraintViolationException) { | } else if (e instanceof ConstraintViolationException) { | ||||
| log.error("【全局异常拦截】ConstraintViolationException", e); | log.error("【全局异常拦截】ConstraintViolationException", e); | ||||
| return ApiResponse.of(Status.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations()) | |||||
| .getMessage(), null); | |||||
| return ApiResponse.of(Status.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations()).getMessage(), null); | |||||
| } else if (e instanceof MethodArgumentTypeMismatchException) { | } else if (e instanceof MethodArgumentTypeMismatchException) { | ||||
| log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage()); | log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage()); | ||||
| return ApiResponse.ofStatus(Status.PARAM_NOT_MATCH); | return ApiResponse.ofStatus(Status.PARAM_NOT_MATCH); | ||||
| @@ -37,12 +37,9 @@ public class CustomUserDetailsService implements UserDetailsService { | |||||
| @Override | @Override | ||||
| public UserDetails loadUserByUsername(String usernameOrEmailOrPhone) throws UsernameNotFoundException { | public UserDetails loadUserByUsername(String usernameOrEmailOrPhone) throws UsernameNotFoundException { | ||||
| User user = userDao.findByUsernameOrEmailOrPhone(usernameOrEmailOrPhone, usernameOrEmailOrPhone, usernameOrEmailOrPhone) | |||||
| .orElseThrow(() -> new UsernameNotFoundException("未找到用户信息 : " + usernameOrEmailOrPhone)); | |||||
| User user = userDao.findByUsernameOrEmailOrPhone(usernameOrEmailOrPhone, usernameOrEmailOrPhone, usernameOrEmailOrPhone).orElseThrow(() -> new UsernameNotFoundException("未找到用户信息 : " + usernameOrEmailOrPhone)); | |||||
| List<Role> roles = roleDao.selectByUserId(user.getId()); | List<Role> roles = roleDao.selectByUserId(user.getId()); | ||||
| List<Long> roleIds = roles.stream() | |||||
| .map(Role::getId) | |||||
| .collect(Collectors.toList()); | |||||
| List<Long> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList()); | |||||
| List<Permission> permissions = permissionDao.selectByRoleIdList(roleIds); | List<Permission> permissions = permissionDao.selectByRoleIdList(roleIds); | ||||
| return UserPrincipal.create(user, roles, permissions); | return UserPrincipal.create(user, roles, permissions); | ||||
| } | } | ||||
| @@ -46,9 +46,7 @@ public class MonitorService { | |||||
| Long total = keys.getTotal(); | Long total = keys.getTotal(); | ||||
| // 根据 redis 中键获取用户名列表 | // 根据 redis 中键获取用户名列表 | ||||
| List<String> usernameList = rows.stream() | |||||
| .map(s -> StrUtil.subAfter(s, Consts.REDIS_JWT_KEY_PREFIX, true)) | |||||
| .collect(Collectors.toList()); | |||||
| List<String> usernameList = rows.stream().map(s -> StrUtil.subAfter(s, Consts.REDIS_JWT_KEY_PREFIX, true)).collect(Collectors.toList()); | |||||
| // 根据用户名查询用户信息 | // 根据用户名查询用户信息 | ||||
| List<User> userList = userDao.findByUsernameIn(usernameList); | List<User> userList = userDao.findByUsernameIn(usernameList); | ||||
| @@ -66,19 +64,16 @@ public class MonitorService { | |||||
| */ | */ | ||||
| public void kickout(List<String> names) { | public void kickout(List<String> names) { | ||||
| // 清除 Redis 中的 JWT 信息 | // 清除 Redis 中的 JWT 信息 | ||||
| List<String> redisKeys = names.parallelStream() | |||||
| .map(s -> Consts.REDIS_JWT_KEY_PREFIX + s) | |||||
| .collect(Collectors.toList()); | |||||
| List<String> redisKeys = names.parallelStream().map(s -> Consts.REDIS_JWT_KEY_PREFIX + s).collect(Collectors.toList()); | |||||
| redisUtil.delete(redisKeys); | redisUtil.delete(redisKeys); | ||||
| // 获取当前用户名 | // 获取当前用户名 | ||||
| String currentUsername = SecurityUtil.getCurrentUsername(); | String currentUsername = SecurityUtil.getCurrentUsername(); | ||||
| names.parallelStream() | |||||
| .forEach(name -> { | |||||
| // TODO: 通知被踢出的用户已被当前登录用户踢出, | |||||
| // 后期考虑使用 websocket 实现,具体伪代码实现如下。 | |||||
| // String message = "您已被用户【" + currentUsername + "】手动下线!"; | |||||
| log.debug("用户【{}】被用户【{}】手动下线!", name, currentUsername); | |||||
| }); | |||||
| names.parallelStream().forEach(name -> { | |||||
| // TODO: 通知被踢出的用户已被当前登录用户踢出, | |||||
| // 后期考虑使用 websocket 实现,具体伪代码实现如下。 | |||||
| // String message = "您已被用户【" + currentUsername + "】手动下线!"; | |||||
| log.debug("用户【{}】被用户【{}】手动下线!", name, currentUsername); | |||||
| }); | |||||
| } | } | ||||
| } | } | ||||
| @@ -53,13 +53,7 @@ public class JwtUtil { | |||||
| */ | */ | ||||
| public String createJWT(Boolean rememberMe, Long id, String subject, List<String> roles, Collection<? extends GrantedAuthority> authorities) { | public String createJWT(Boolean rememberMe, Long id, String subject, List<String> roles, Collection<? extends GrantedAuthority> authorities) { | ||||
| Date now = new Date(); | Date now = new Date(); | ||||
| JwtBuilder builder = Jwts.builder() | |||||
| .setId(id.toString()) | |||||
| .setSubject(subject) | |||||
| .setIssuedAt(now) | |||||
| .signWith(SignatureAlgorithm.HS256, jwtConfig.getKey()) | |||||
| .claim("roles", roles) | |||||
| .claim("authorities", authorities); | |||||
| JwtBuilder builder = Jwts.builder().setId(id.toString()).setSubject(subject).setIssuedAt(now).signWith(SignatureAlgorithm.HS256, jwtConfig.getKey()).claim("roles", roles).claim("authorities", authorities); | |||||
| // 设置过期时间 | // 设置过期时间 | ||||
| Long ttl = rememberMe ? jwtConfig.getRemember() : jwtConfig.getTtl(); | Long ttl = rememberMe ? jwtConfig.getRemember() : jwtConfig.getTtl(); | ||||
| @@ -69,8 +63,7 @@ public class JwtUtil { | |||||
| String jwt = builder.compact(); | String jwt = builder.compact(); | ||||
| // 将生成的JWT保存至Redis | // 将生成的JWT保存至Redis | ||||
| stringRedisTemplate.opsForValue() | |||||
| .set(Consts.REDIS_JWT_KEY_PREFIX + subject, jwt, ttl, TimeUnit.MILLISECONDS); | |||||
| stringRedisTemplate.opsForValue().set(Consts.REDIS_JWT_KEY_PREFIX + subject, jwt, ttl, TimeUnit.MILLISECONDS); | |||||
| return jwt; | return jwt; | ||||
| } | } | ||||
| @@ -94,10 +87,7 @@ public class JwtUtil { | |||||
| */ | */ | ||||
| public Claims parseJWT(String jwt) { | public Claims parseJWT(String jwt) { | ||||
| try { | try { | ||||
| Claims claims = Jwts.parser() | |||||
| .setSigningKey(jwtConfig.getKey()) | |||||
| .parseClaimsJws(jwt) | |||||
| .getBody(); | |||||
| Claims claims = Jwts.parser().setSigningKey(jwtConfig.getKey()).parseClaimsJws(jwt).getBody(); | |||||
| String username = claims.getSubject(); | String username = claims.getSubject(); | ||||
| String redisKey = Consts.REDIS_JWT_KEY_PREFIX + username; | String redisKey = Consts.REDIS_JWT_KEY_PREFIX + username; | ||||
| @@ -109,8 +99,7 @@ public class JwtUtil { | |||||
| } | } | ||||
| // 校验redis中的JWT是否与当前的一致,不一致则代表用户已注销/用户在不同设备登录,均代表JWT已过期 | // 校验redis中的JWT是否与当前的一致,不一致则代表用户已注销/用户在不同设备登录,均代表JWT已过期 | ||||
| String redisToken = stringRedisTemplate.opsForValue() | |||||
| .get(redisKey); | |||||
| String redisToken = stringRedisTemplate.opsForValue().get(redisKey); | |||||
| if (!StrUtil.equals(jwt, redisToken)) { | if (!StrUtil.equals(jwt, redisToken)) { | ||||
| throw new SecurityException(Status.TOKEN_OUT_OF_CTRL); | throw new SecurityException(Status.TOKEN_OUT_OF_CTRL); | ||||
| } | } | ||||
| @@ -38,9 +38,7 @@ public class RedisUtil { | |||||
| * @return 分页获取指定格式key | * @return 分页获取指定格式key | ||||
| */ | */ | ||||
| public PageResult<String> findKeysForPage(String patternKey, int currentPage, int pageSize) { | public PageResult<String> findKeysForPage(String patternKey, int currentPage, int pageSize) { | ||||
| ScanOptions options = ScanOptions.scanOptions() | |||||
| .match(patternKey) | |||||
| .build(); | |||||
| ScanOptions options = ScanOptions.scanOptions().match(patternKey).build(); | |||||
| RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory(); | RedisConnectionFactory factory = stringRedisTemplate.getConnectionFactory(); | ||||
| RedisConnection rc = factory.getConnection(); | RedisConnection rc = factory.getConnection(); | ||||
| Cursor<byte[]> cursor = rc.scan(options); | Cursor<byte[]> cursor = rc.scan(options); | ||||
| @@ -37,8 +37,7 @@ public class ResponseUtil { | |||||
| // FIXME: hutool 的 BUG:JSONUtil.toJsonStr() | // FIXME: hutool 的 BUG:JSONUtil.toJsonStr() | ||||
| // 将JSON转为String的时候,忽略null值的时候转成的String存在错误 | // 将JSON转为String的时候,忽略null值的时候转成的String存在错误 | ||||
| response.getWriter() | |||||
| .write(JSONUtil.toJsonStr(new JSONObject(ApiResponse.ofStatus(status, data), false))); | |||||
| response.getWriter().write(JSONUtil.toJsonStr(new JSONObject(ApiResponse.ofStatus(status, data), false))); | |||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| log.error("Response写出JSON异常,", e); | log.error("Response写出JSON异常,", e); | ||||
| } | } | ||||
| @@ -59,8 +58,7 @@ public class ResponseUtil { | |||||
| // FIXME: hutool 的 BUG:JSONUtil.toJsonStr() | // FIXME: hutool 的 BUG:JSONUtil.toJsonStr() | ||||
| // 将JSON转为String的时候,忽略null值的时候转成的String存在错误 | // 将JSON转为String的时候,忽略null值的时候转成的String存在错误 | ||||
| response.getWriter() | |||||
| .write(JSONUtil.toJsonStr(new JSONObject(ApiResponse.ofException(exception), false))); | |||||
| response.getWriter().write(JSONUtil.toJsonStr(new JSONObject(ApiResponse.ofException(exception), false))); | |||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| log.error("Response写出JSON异常,", e); | log.error("Response写出JSON异常,", e); | ||||
| } | } | ||||
| @@ -31,9 +31,7 @@ public class SecurityUtil { | |||||
| * @return 当前登录用户信息,匿名登录时,为null | * @return 当前登录用户信息,匿名登录时,为null | ||||
| */ | */ | ||||
| public static UserPrincipal getCurrentUser() { | public static UserPrincipal getCurrentUser() { | ||||
| Object userInfo = SecurityContextHolder.getContext() | |||||
| .getAuthentication() | |||||
| .getPrincipal(); | |||||
| Object userInfo = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); | |||||
| if (userInfo instanceof UserDetails) { | if (userInfo instanceof UserDetails) { | ||||
| return (UserPrincipal) userInfo; | return (UserPrincipal) userInfo; | ||||
| } | } | ||||