@@ -42,10 +42,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { | |||
for (String[] user : usersGroupsAndRoles) { | |||
List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length)); | |||
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 | |||
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 | |||
public class SpringBootDemoActuatorApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
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 | |||
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 | |||
public class SpringBootDemoAdminClientApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -16,7 +16,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
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 | |||
public class SpringBootDemoAdminServerApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -179,9 +179,7 @@ public class CodeGenUtil { | |||
try { | |||
//添加到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.close(sw); | |||
zip.closeEntry(); | |||
@@ -78,6 +78,7 @@ public enum DatasourceHolder { | |||
/** | |||
* 清除动态数据源 | |||
* | |||
* @param id 数据源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); | |||
} | |||
@@ -35,6 +35,7 @@ public class DynamicDataSource extends HikariDataSource { | |||
/** | |||
* 初始化数据源 | |||
* | |||
* @param id 数据源id | |||
* @return 数据源 | |||
*/ | |||
@@ -54,7 +54,6 @@ public class Result<T> implements Serializable { | |||
} | |||
/** | |||
* 返回成功 | |||
* | |||
@@ -70,7 +69,7 @@ public class Result<T> implements Serializable { | |||
* 返回成功-携带数据 | |||
* | |||
* @param data 响应数据 | |||
* @param <T> 泛型标记 | |||
* @param <T> 泛型标记 | |||
* @return 响应信息 {@code Result} | |||
*/ | |||
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 | |||
* | |||
* @author fxbin | |||
* @param index elasticsearch index name | |||
* @author fxbin | |||
*/ | |||
void createIndex(String index); | |||
/** | |||
* delete Index | |||
* | |||
* @author fxbin | |||
* @param index elasticsearch index name | |||
* @author fxbin | |||
*/ | |||
void deleteIndex(String index); | |||
/** | |||
* insert document source | |||
* | |||
* @author fxbin | |||
* @param index elasticsearch index name | |||
* @param list data source | |||
* @param list data source | |||
* @author fxbin | |||
*/ | |||
void insert(String index, List<Person> list); | |||
/** | |||
* update document source | |||
* | |||
* @author fxbin | |||
* @param index elasticsearch index name | |||
* @param list data source | |||
* @param list data source | |||
* @author fxbin | |||
*/ | |||
void update(String index, List<Person> list); | |||
/** | |||
* delete document source | |||
* | |||
* @author fxbin | |||
* @param person delete data source and allow null object | |||
* @author fxbin | |||
*/ | |||
void delete(String index, @Nullable Person person); | |||
/** | |||
* search all doc records | |||
* | |||
* @author fxbin | |||
* @param index elasticsearch index name | |||
* @return person list | |||
* @author fxbin | |||
*/ | |||
List<Person> searchList(String index); | |||
@@ -2,8 +2,8 @@ package com.xkcoding.elasticsearch.service.impl; | |||
import cn.hutool.core.bean.BeanUtil; | |||
import com.xkcoding.elasticsearch.model.Person; | |||
import com.xkcoding.elasticsearch.service.base.BaseElasticsearchService; | |||
import com.xkcoding.elasticsearch.service.PersonService; | |||
import com.xkcoding.elasticsearch.service.base.BaseElasticsearchService; | |||
import org.elasticsearch.action.index.IndexRequest; | |||
import org.elasticsearch.action.search.SearchResponse; | |||
import org.elasticsearch.search.SearchHit; | |||
@@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||
@SpringBootTest | |||
public class SpringBootDemoElasticsearchApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -92,8 +92,7 @@ public class PersonRepositoryTest extends SpringBootDemoElasticsearchApplication | |||
*/ | |||
@Test | |||
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 | |||
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())); | |||
@@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||
@SpringBootTest | |||
public class SpringBootDemoEmailApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
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 | |||
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 | |||
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 | |||
@EqualsAndHashCode(callSuper = true) | |||
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 | |||
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 | |||
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 | |||
@Slf4j | |||
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 | |||
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 | |||
public class SpringBootDemoExceptionHandlerApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -1,20 +1,18 @@ | |||
package com.xkcoding; | |||
import static org.junit.Assert.assertTrue; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertTrue; | |||
/** | |||
* Unit test for simple App. | |||
*/ | |||
public class AppTest | |||
{ | |||
public class AppTest { | |||
/** | |||
* Rigorous Test :-) | |||
*/ | |||
@Test | |||
public void shouldAnswerWithTrue() | |||
{ | |||
assertTrue( true ); | |||
public void shouldAnswerWithTrue() { | |||
assertTrue(true); | |||
} | |||
} |
@@ -19,21 +19,21 @@ import org.springframework.web.bind.annotation.RestController; | |||
@RestController | |||
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 | |||
public class SpringBootDemoHelloworldApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
<!DOCTYPE html> | |||
<html lang="en" xmlns:th="http://www.thymeleaf.org"> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<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 <T> 泛型标记 | |||
* @param <T> 泛型标记 | |||
* @return 响应信息 {@code Result} | |||
*/ | |||
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 | |||
*/ | |||
@Data | |||
@Entry( | |||
base = "ou=people", | |||
objectClasses = {"posixAccount", "inetOrgPerson", "top"} | |||
) | |||
@Entry(base = "ou=people", objectClasses = {"posixAccount", "inetOrgPerson", "top"}) | |||
public class Person implements Serializable { | |||
private static final long serialVersionUID = -7946768337975852352L; | |||
@@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
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 | |||
@Slf4j | |||
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 | |||
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 | |||
public class SpringBootDemoLogAopApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -17,19 +17,19 @@ import org.springframework.context.ConfigurableApplicationContext; | |||
@Slf4j | |||
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 | |||
public class SpringBootDemoLogbackApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -45,8 +45,7 @@ public class ArticleRepositoryTest extends SpringBootDemoMongodbApplicationTests | |||
*/ | |||
@Test | |||
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); | |||
log.info("【article】= {}", JSONUtil.toJsonStr(article)); | |||
} | |||
@@ -58,14 +57,11 @@ public class ArticleRepositoryTest extends SpringBootDemoMongodbApplicationTests | |||
public void testSaveList() { | |||
List<Article> articles = Lists.newArrayList(); | |||
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); | |||
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); | |||
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); | |||
log.info("【总页数】= {}", all.getTotalPages()); | |||
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 | |||
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); | |||
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); | |||
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); | |||
return message; | |||
}); | |||
@@ -28,12 +28,12 @@ import javax.sql.DataSource; | |||
@Configuration | |||
@EnableTransactionManagement | |||
@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 { | |||
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"; | |||
@@ -63,14 +63,14 @@ public class PrimaryJpaConfig { | |||
@Bean(name = "primaryEntityManagerFactory") | |||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("primaryDataSource") DataSource primaryDataSource, @Qualifier("primaryJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder 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 | |||
@EnableTransactionManagement | |||
@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 { | |||
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"; | |||
@@ -60,14 +60,14 @@ public class SecondJpaConfig { | |||
@Bean(name = "secondEntityManagerFactory") | |||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("secondDataSource") DataSource secondDataSource, @Qualifier("secondJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder 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 | |||
public class SnowflakeConfig { | |||
@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 | |||
public void testInsert() { | |||
PrimaryMultiTable primary = new PrimaryMultiTable(snowflake.nextId(),"测试名称-1"); | |||
PrimaryMultiTable primary = new PrimaryMultiTable(snowflake.nextId(), "测试名称-1"); | |||
primaryRepo.save(primary); | |||
SecondMultiTable second = new SecondMultiTable(); | |||
@@ -39,7 +39,7 @@ public class SpringBootDemoMultiDatasourceJpaApplicationTests { | |||
@Test | |||
public void testUpdate() { | |||
primaryRepo.findAll().forEach(primary -> { | |||
primary.setName("修改后的"+primary.getName()); | |||
primary.setName("修改后的" + primary.getName()); | |||
primaryRepo.save(primary); | |||
SecondMultiTable second = new SecondMultiTable(); | |||
@@ -90,10 +90,8 @@ public class NeoService { | |||
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(sevenClass); | |||
@@ -155,8 +153,7 @@ public class NeoService { | |||
List<ClassmateInfoGroupByLesson> groupByLesson = studentRepo.findByClassmateGroupByLesson(); | |||
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; | |||
} | |||
@@ -171,11 +168,9 @@ public class NeoService { | |||
List<TeacherStudent> teacherStudentByLesson = studentRepo.findTeacherStudentByLesson(); | |||
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; | |||
} | |||
@@ -71,9 +71,7 @@ public class Neo4jTest extends SpringBootDemoNeo4jApplicationTests { | |||
@Test | |||
public void testFindClassmates() { | |||
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 | |||
public void testFindTeacherStudent() { | |||
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 | |||
public class ClientLoginFailureHandler implements AuthenticationFailureHandler { | |||
@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!"); | |||
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 | |||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) { | |||
endpoints.authenticationManager(authenticationManager) | |||
.userDetailsService(sysUserService) | |||
.tokenStore(tokenStore) | |||
.accessTokenConverter(jwtAccessTokenConverter); | |||
endpoints.authenticationManager(authenticationManager).userDetailsService(sysUserService).tokenStore(tokenStore).accessTokenConverter(jwtAccessTokenConverter); | |||
} | |||
@Override | |||
@@ -24,20 +24,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||
@Override | |||
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} | |||
* 授权服务器相关的配置,主要设置授权服务器如何读取客户端、用户信息和一些端点配置 | |||
* 可以在这里配置更多的东西,例如端点映射,token 增强等 | |||
* | |||
* <p> | |||
* {@link com.xkcoding.oauth.config.Oauth2AuthorizationTokenConfig} | |||
* 授权服务器 token 相关的配置,主要设置 jwt、加密方式等信息 | |||
* | |||
* <p> | |||
* {@link com.xkcoding.oauth.config.ClientLogoutSuccessHandler} | |||
* 资源服务器退出以后的处理。在授权码模式中,所有的客户端都需要跳转到授权服务器进行登录 | |||
* 当登录成功以后跳转到回调地址,如果用户需要登出,也要跳转到授权服务器这里进行登出 | |||
@@ -15,7 +15,6 @@ | |||
* 所以自己给登出端点加了一个 redirect_url 参数,表示登出成功以后要跳转的地址 | |||
* 这个处理器就是来完成登出成功以后的跳转操作的。 | |||
* | |||
* | |||
* @author <a href="https://echocow.cn">EchoCow</a> | |||
* @date 2020-01-07 9:16 | |||
*/ | |||
@@ -36,12 +36,11 @@ public class Oauth2Controller { | |||
* 退出登录 | |||
* | |||
* @param redirectUrl 退出完成后的回调地址 | |||
* @param principal 用户信息 | |||
* @param principal 用户信息 | |||
* @return 结果 | |||
*/ | |||
@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)) { | |||
throw new ResourceAccessException("请求错误,用户尚未登录"); | |||
} | |||
@@ -2,7 +2,7 @@ | |||
* 控制器。除了业务逻辑的以外,提供两个控制器来帮助完成自定义: | |||
* {@link com.xkcoding.oauth.controller.AuthorizationController} | |||
* 自定义的授权控制器,重新设置到我们的界面中去,不使用他的默认实现 | |||
* | |||
* <p> | |||
* {@link com.xkcoding.oauth.controller.Oauth2Controller} | |||
* 页面跳转的控制器,这里拿出来是因为真的可以做很多事。比如登录的时候携带点什么 | |||
* 或者退出的时候携带什么标识,都可以。 | |||
@@ -47,9 +47,6 @@ public class SysUser { | |||
* 当前用户所有角色. | |||
*/ | |||
@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; | |||
} |
@@ -5,7 +5,10 @@ import com.xkcoding.oauth.repostiory.SysClientDetailsRepository; | |||
import com.xkcoding.oauth.service.SysClientDetailsService; | |||
import lombok.RequiredArgsConstructor; | |||
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 java.util.List; | |||
@@ -25,14 +28,12 @@ public class SysClientDetailsServiceImpl implements SysClientDetailsService { | |||
@Override | |||
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 | |||
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 | |||
@@ -46,16 +47,14 @@ public class SysClientDetailsServiceImpl implements SysClientDetailsService { | |||
@Override | |||
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()); | |||
sysClientDetailsRepository.save(clientDetails); | |||
} | |||
@Override | |||
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)); | |||
sysClientDetailsRepository.save(exist); | |||
} | |||
@@ -29,11 +29,8 @@ public class SysUserServiceImpl implements SysUserService { | |||
@Override | |||
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 的默认实现 | |||
return new User(sysUser.getUsername(), sysUser.getPassword(), roles); | |||
} | |||
@@ -45,8 +42,7 @@ public class SysUserServiceImpl implements SysUserService { | |||
@Override | |||
public SysUser findById(Long id) { | |||
return sysUserRepository.findById(id) | |||
.orElseThrow(() -> new RuntimeException("找不到用户")); | |||
return sysUserRepository.findById(id).orElseThrow(() -> new RuntimeException("找不到用户")); | |||
} | |||
@Override | |||
@@ -46,15 +46,13 @@ public class AuthorizationCodeGrantTests { | |||
@Test | |||
void testCannotConnectWithoutToken() { | |||
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 | |||
void testAttemptedTokenAcquisitionWithNoRedirect() { | |||
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)); | |||
// 3. 登录授权并获取登录成功的 cookie | |||
ResponseEntity<Void> response = authorizationServerInfo | |||
.postForStatus("/authorization/form", headers, form); | |||
ResponseEntity<Void> response = authorizationServerInfo.postForStatus("/authorization/form", headers, form); | |||
assertNotNull(response); | |||
cookie = response.getHeaders().getFirst("Set-Cookie"); | |||
headers = new HttpHeaders(); | |||
@@ -89,8 +86,7 @@ public class AuthorizationCodeGrantTests { | |||
headers.setAccept(Collections.singletonList(MediaType.ALL)); | |||
// 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(); | |||
// 确认过一次后,后面都会自动确认了,这里判断下是不是重定向请求 | |||
@@ -55,8 +55,7 @@ public class AuthorizationServerInfo { | |||
HttpHeaders actualHeaders = new HttpHeaders(); | |||
actualHeaders.putAll(headers); | |||
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); | |||
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 { | |||
@@ -8,7 +8,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; | |||
import java.util.Arrays; | |||
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> | |||
* @date 2020-01-09 11:38 | |||
* @version V1.0 | |||
* @date 2020-01-09 11:38 | |||
*/ | |||
@EnableResourceServer | |||
@SpringBootApplication | |||
@@ -28,9 +28,7 @@ public class OauthResourceServerConfig extends ResourceServerConfigurerAdapter { | |||
@Override | |||
public void configure(ResourceServerSecurityConfigurer resources) { | |||
resources | |||
.tokenStore(tokenStore) | |||
.resourceId(resourceServerProperties.getResourceId()); | |||
resources.tokenStore(tokenStore).resourceId(resourceServerProperties.getResourceId()); | |||
} | |||
@Override | |||
@@ -62,9 +62,7 @@ public class OauthResourceTokenConfig { | |||
*/ | |||
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.add(HttpHeaders.AUTHORIZATION, encodeClient()); | |||
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 { | |||
JSONObject body = objectMapper.readValue(pubKey, JSONObject.class); | |||
log.info("Get Key From Authorization Server."); | |||
@@ -96,7 +93,6 @@ public class OauthResourceTokenConfig { | |||
* @return basic | |||
*/ | |||
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 | |||
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); | |||
assertEquals(HttpStatus.OK, response.getStatusCode()); | |||
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 | |||
@@ -43,8 +42,7 @@ public class TestControllerTest extends AuthorizationTest { | |||
ResponseEntity<String> response = template.exchange(URL + "/test", GET, null, String.class); | |||
assertEquals(HttpStatus.OK, response.getStatusCode()); | |||
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 | |||
@@ -54,8 +52,7 @@ public class TestControllerTest extends AuthorizationTest { | |||
ResponseEntity<String> response = template.exchange(URL + "/read", GET, null, String.class); | |||
assertEquals(HttpStatus.OK, response.getStatusCode()); | |||
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 | |||
@@ -65,8 +62,7 @@ public class TestControllerTest extends AuthorizationTest { | |||
ResponseEntity<String> response = template.exchange(URL + "/write", GET, null, String.class); | |||
assertEquals(HttpStatus.OK, response.getStatusCode()); | |||
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 | |||
@@ -22,7 +22,7 @@ public class BeetlConfig { | |||
* Beetl需要显示的配置数据源,方可启动项目,大坑,切记! | |||
*/ | |||
@Bean(name = "datasource") | |||
public DataSource getDataSource(Environment env){ | |||
public DataSource getDataSource(Environment env) { | |||
HikariDataSource dataSource = new HikariDataSource(); | |||
dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name")); | |||
dataSource.setJdbcUrl(env.getProperty("spring.datasource.url")); | |||
@@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
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) | |||
@Target({ElementType.FIELD}) | |||
public @interface Column { | |||
/** | |||
* 列名 | |||
* | |||
* @return 列名 | |||
*/ | |||
String name(); | |||
/** | |||
* 列名 | |||
* | |||
* @return 列名 | |||
*/ | |||
String name(); | |||
} |
@@ -16,10 +16,10 @@ import java.lang.annotation.Target; | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target({ElementType.FIELD}) | |||
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) | |||
@Target({ElementType.TYPE}) | |||
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 | |||
*/ | |||
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 | |||
@Slf4j | |||
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 | |||
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 | |||
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; | |||
import com.xkcoding.orm.jdbctemplate.annotation.Pk; | |||
import com.xkcoding.orm.jdbctemplate.annotation.Column; | |||
import com.xkcoding.orm.jdbctemplate.annotation.Pk; | |||
import com.xkcoding.orm.jdbctemplate.annotation.Table; | |||
import lombok.Data; | |||
@@ -19,58 +19,58 @@ import java.util.Date; | |||
@Data | |||
@Table(name = "orm_user") | |||
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 | |||
*/ | |||
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 | |||
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 | |||
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 - 查询单个 | |||
*/ | |||
@Test | |||
public void testQueryOne(){ | |||
public void testQueryOne() { | |||
User user = userMapper.selectByPrimaryKey(1L); | |||
Assert.assertNotNull(user); | |||
log.debug("【user】= {}", user); | |||
@@ -23,7 +23,7 @@ public class MybatisPlusConfig { | |||
* 性能分析拦截器,不建议生产使用 | |||
*/ | |||
@Bean | |||
public PerformanceInterceptor performanceInterceptor(){ | |||
public PerformanceInterceptor performanceInterceptor() { | |||
return new PerformanceInterceptor(); | |||
} | |||
@@ -9,8 +9,8 @@ import org.springframework.test.context.junit4.SpringRunner; | |||
@SpringBootTest | |||
public class SpringBootDemoOrmMybatisPlusApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -14,7 +14,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
@SpringBootApplication | |||
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 | |||
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 | |||
@Component | |||
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") | |||
@Component | |||
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 | |||
public class SpringBootDemoPropertiesApplicationTests { | |||
@Test | |||
public void contextLoads() { | |||
} | |||
@Test | |||
public void contextLoads() { | |||
} | |||
} |
@@ -54,7 +54,7 @@ public class RateLimiterAspect { | |||
String key = rateLimiter.key(); | |||
// 默认用类名+方法名做限流的 key 前缀 | |||
if (StrUtil.isBlank(key)) { | |||
key = method.getDeclaringClass().getName()+StrUtil.DOT+method.getName(); | |||
key = method.getDeclaringClass().getName() + StrUtil.DOT + method.getName(); | |||
} | |||
// 最终限流的 key 为 前缀 + IP地址 | |||
// TODO: 此时需要考虑局域网多用户访问的情况,因此 key 后续需要加上方法参数更加合理 | |||
@@ -14,29 +14,29 @@ import lombok.EqualsAndHashCode; | |||
@EqualsAndHashCode(callSuper = true) | |||
@Data | |||
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) { | |||
Status[] statuses = Status.values(); | |||
for (Status status : statuses) { | |||
if (status.getCode() | |||
.equals(code)) { | |||
if (status.getCode().equals(code)) { | |||
return status; | |||
} | |||
} | |||
@@ -65,8 +65,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | |||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | |||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); | |||
SecurityContextHolder.getContext() | |||
.setAuthentication(authentication); | |||
SecurityContextHolder.getContext().setAuthentication(authentication); | |||
filterChain.doFilter(request, response); | |||
} catch (SecurityException e) { | |||
ResponseUtil.renderJson(response, e); | |||
@@ -95,43 +94,34 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { | |||
switch (httpMethod) { | |||
case GET: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getGet()); | |||
ignores.addAll(customConfig.getIgnores().getGet()); | |||
break; | |||
case PUT: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getPut()); | |||
ignores.addAll(customConfig.getIgnores().getPut()); | |||
break; | |||
case HEAD: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getHead()); | |||
ignores.addAll(customConfig.getIgnores().getHead()); | |||
break; | |||
case POST: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getPost()); | |||
ignores.addAll(customConfig.getIgnores().getPost()); | |||
break; | |||
case PATCH: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getPatch()); | |||
ignores.addAll(customConfig.getIgnores().getPatch()); | |||
break; | |||
case TRACE: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getTrace()); | |||
ignores.addAll(customConfig.getIgnores().getTrace()); | |||
break; | |||
case DELETE: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getDelete()); | |||
ignores.addAll(customConfig.getIgnores().getDelete()); | |||
break; | |||
case OPTIONS: | |||
ignores.addAll(customConfig.getIgnores() | |||
.getOptions()); | |||
ignores.addAll(customConfig.getIgnores().getOptions()); | |||
break; | |||
default: | |||
break; | |||
} | |||
ignores.addAll(customConfig.getIgnores() | |||
.getPattern()); | |||
ignores.addAll(customConfig.getIgnores().getPattern()); | |||
if (CollUtil.isNotEmpty(ignores)) { | |||
for (String ignore : ignores) { | |||
@@ -58,20 +58,17 @@ public class RbacAuthorityService { | |||
Long userId = principal.getId(); | |||
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> 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) { | |||
AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(btnPerm.getUrl(), btnPerm.getMethod()); | |||
@@ -104,8 +101,7 @@ public class RbacAuthorityService { | |||
// 2:new AntPathRequestMatcher(uri) 这种方式不校验请求方法,只校验请求路径 | |||
AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(uri); | |||
if (antPathMatcher.matches(request)) { | |||
if (!urlMapping.get(uri) | |||
.contains(currentMethod)) { | |||
if (!urlMapping.get(uri).contains(currentMethod)) { | |||
throw new SecurityException(Status.HTTP_BAD_METHOD); | |||
} else { | |||
return; | |||
@@ -129,15 +125,11 @@ public class RbacAuthorityService { | |||
handlerMethods.forEach((k, v) -> { | |||
// 获取当前 key 下的获取所有URL | |||
Set<String> url = k.getPatternsCondition() | |||
.getPatterns(); | |||
Set<String> url = k.getPatternsCondition().getPatterns(); | |||
RequestMethodsRequestCondition method = k.getMethodsCondition(); | |||
// 为每个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; | |||
@@ -19,9 +19,6 @@ public class WebMvcConfig implements WebMvcConfigurer { | |||
@Override | |||
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) { | |||
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)); | |||
} | |||
@@ -53,7 +53,7 @@ public class MonitorController { | |||
if (CollUtil.isEmpty(names)) { | |||
throw new SecurityException(Status.PARAM_NOT_NULL); | |||
} | |||
if (names.contains(SecurityUtil.getCurrentUsername())){ | |||
if (names.contains(SecurityUtil.getCurrentUsername())) { | |||
throw new SecurityException(Status.KICKOUT_SELF); | |||
} | |||
monitorService.kickout(names); | |||
@@ -42,14 +42,10 @@ public class GlobalExceptionHandler { | |||
return ApiResponse.ofStatus(Status.HTTP_BAD_METHOD); | |||
} else if (e instanceof MethodArgumentNotValidException) { | |||
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) { | |||
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) { | |||
log.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage()); | |||
return ApiResponse.ofStatus(Status.PARAM_NOT_MATCH); | |||
@@ -37,12 +37,9 @@ public class CustomUserDetailsService implements UserDetailsService { | |||
@Override | |||
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<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); | |||
return UserPrincipal.create(user, roles, permissions); | |||
} | |||
@@ -46,9 +46,7 @@ public class MonitorService { | |||
Long total = keys.getTotal(); | |||
// 根据 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); | |||
@@ -66,19 +64,16 @@ public class MonitorService { | |||
*/ | |||
public void kickout(List<String> names) { | |||
// 清除 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); | |||
// 获取当前用户名 | |||
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) { | |||
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(); | |||
@@ -69,8 +63,7 @@ public class JwtUtil { | |||
String jwt = builder.compact(); | |||
// 将生成的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; | |||
} | |||
@@ -94,10 +87,7 @@ public class JwtUtil { | |||
*/ | |||
public Claims parseJWT(String jwt) { | |||
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 redisKey = Consts.REDIS_JWT_KEY_PREFIX + username; | |||
@@ -109,8 +99,7 @@ public class JwtUtil { | |||
} | |||
// 校验redis中的JWT是否与当前的一致,不一致则代表用户已注销/用户在不同设备登录,均代表JWT已过期 | |||
String redisToken = stringRedisTemplate.opsForValue() | |||
.get(redisKey); | |||
String redisToken = stringRedisTemplate.opsForValue().get(redisKey); | |||
if (!StrUtil.equals(jwt, redisToken)) { | |||
throw new SecurityException(Status.TOKEN_OUT_OF_CTRL); | |||
} | |||
@@ -38,9 +38,7 @@ public class RedisUtil { | |||
* @return 分页获取指定格式key | |||
*/ | |||
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(); | |||
RedisConnection rc = factory.getConnection(); | |||
Cursor<byte[]> cursor = rc.scan(options); | |||
@@ -37,8 +37,7 @@ public class ResponseUtil { | |||
// FIXME: hutool 的 BUG:JSONUtil.toJsonStr() | |||
// 将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) { | |||
log.error("Response写出JSON异常,", e); | |||
} | |||
@@ -59,8 +58,7 @@ public class ResponseUtil { | |||
// FIXME: hutool 的 BUG:JSONUtil.toJsonStr() | |||
// 将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) { | |||
log.error("Response写出JSON异常,", e); | |||
} | |||
@@ -31,9 +31,7 @@ public class SecurityUtil { | |||
* @return 当前登录用户信息,匿名登录时,为null | |||
*/ | |||
public static UserPrincipal getCurrentUser() { | |||
Object userInfo = SecurityContextHolder.getContext() | |||
.getAuthentication() | |||
.getPrincipal(); | |||
Object userInfo = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); | |||
if (userInfo instanceof UserDetails) { | |||
return (UserPrincipal) userInfo; | |||
} | |||