@@ -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; | ||||
} | } | ||||