spring-boot-extensions
spring-boot-x specification(cn)
-
Manual transaction
ManualTransactionManager
-
GeDid: Distributed id generator.
RedisIdEngine
ZookeeperIdEngine
UuidEngine
@Configuration public class IdLoaderConfig implements DidLoaderConfigurer { @Bean public ZookeeperIdEngineMode zookeeperIdEngineMode() { return ZookeeperIdEngineMode.DATA_ZX_MID; } @Override public void configureDidLoader(DidLoader didLoader) { // business abc didLoader.follow("redis://abc"); // business a didLoader.follow("redis", "a"); // business b didLoader.follow("redis", "b"); // business zk didLoader.follow("zookeeper", "zk"); // business uuid didLoader.follow("uuid", "uuid"); } }
-
Elasticsearch supports
- the
RestHighLevelClientX
extension forRestHighLevelClient
, simplification for doc operations:saveOrUpdate
,deleteById(s)
,findById(s)
,search
. - the
ElasticsearchTemplateLite
extension forElasticsearchTemplate
- base on ElasticsearchTemplate
7.2.0
and dependency jars(rest client & rest high level client)
- the
-
request log:
**************************************************************** :: SpringApplicationX :: for current request report information **************************************************************** Client IP : 127.0.0.1 Request Time : 2020-07-12T19:24:40.249 Controller : orgg.openingo.x.controller.UserController.(UserController.java:1) URI : http://localhost:8080/json Handler(Action) : json Method : GET Processing Time : 0.002s Header(s) : [user-agent:"PostmanRuntime/7.25.0", cache-control:"no-cache", postman-token:"b29a0616-7e31-4150-b022-4bf3680bf771", host:"localhost:8080", accept-encoding:"gzip, deflate, br", connection:"keep-alive", content-length:"21", Content-Type:"application/json;charset=UTF-8"] Body : {"name":"qicz"} Response : {"name":"qicz","age":18} ----------------------------------------------------------------
-
redis template extension, add key naming policy.
-
custom
ErrorAttributes
, with handler, include exception information:add current request handler and exception
{ "timestamp": "2020-07-13T05:49:06.071+0000", "status": 500, "error": "Internal Server Error", "exception": "ServiceException", "message": "testing exception", "path": "/ex", "handler": "public java.util.Map org.openingo.x.controller.UserController.ex()", "openingo.error": { "ex": "ServiceException: testing exception", "em": "testing exception", "error": "Internal Server Error", "ec": "ERROR_CODE" } }
-
SpringApplicationX
more extensions -
RoutingDataSource
(dynamic dataSource)-
support Hikaricp & Alibaba Druid
-
how?
@Bean(initMethod = "init", destroyMethod = "close") @ConfigurationProperties("spring.datasource") public DruidDataSource defaultDataSource(){ return new DruidDataSource(); } @Bean public RoutingDataSource routingDataSource(DruidDataSource dataSource) { return new RoutingDataSource(new DruidDataSourceProvider(dataSource)); }
/** * DataSourceService * * @author Qicz */ @Service @Slf4j public class DataSourceService implements IDataSourceService { @Autowired RoutingDataSource routingDataSource; @Autowired DruidDataSource dataSource; @Override public void switchDataSource(String name) throws SQLException { try { System.out.println("======before======"+name); routingDataSource.getConnection(); System.out.println(routingDataSource.getCurrentUsingDataSourceProvider().hashCode()); RoutingDataSourceHolder.setCurrentUsingDataSourceKey(name); routingDataSource.getConnection(); System.out.println("======after======"); System.out.println(routingDataSource.getCurrentUsingDataSourceProvider().hashCode()); } finally { RoutingDataSourceHolder.clearCurrentUsingDataSourceKey(); } } @Override public void add(String name) { //routingDataSource.setAutoCloseSameKeyDataSource(false); DruidDataSourceProvider druidDataSourceProvider = new DruidDataSourceProvider(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword()); druidDataSourceProvider.startProviding(); routingDataSource.addDataSource(name, druidDataSourceProvider); } }
RoutingDataSourceHolder.getCurrentUsingDataSourceKey
will get and remove current using.
-
-
validate groups[TODO]
-
others [TODO]
-
Dependency:
<dependency> <groupId>org.openingo.boot</groupId> <artifactId>spring-boot-x</artifactId> <version>new_version</version> </dependency>
-
Add
@EnableExtension
in your main application class: -
Configuration:
openingo: redis: enable: true http: request: cors: allowed-header: "*" enable: true allowed-all: true log: enable: true error: enable: true
-
RespData.Config
/** * Config * * @author Qicz */ @Configuration public class Config { public Config() { RespData.Config.SC_KEY = "ec"; RespData.Config.SM_KEY = "em"; RespData.Config.FAILURE_SC = 111; //RespData.Config.SM_ONLY = true; // set "true" just output message RespData.Config.FRIENDLY_FAILURE_MESSAGE = null;//"friendly message";// set to "null" will using exception's message } }
-
controller
@GetMapping("/ex1") public RespData ex1(){ throw new IndexOutOfBoundsException("IndexOutOfBoundsException message"); } @GetMapping("/ex2") public RespData ex2() throws IOException { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.readValue("[{asd}]", Map.class); return RespData.success(); }
-
/ex1
output{ "em": "IndexOutOfBoundsException message", "ec": 123 }
-
/ex1
output with friendly message,RespData.Config.FRIENDLY_FAILURE_MESSAGE = "friendly message";
{ "em": "friendly message", "ec": 123 }
-
log.error information
2020-07-13 23:56:00.572 ERROR 35387 --- [nio-8080-exec-2] o.s.b.w.s.error.DefaultErrorAttributesX : **************************************************************** :: SpringApplicationX :: for current request report information **************************************************************** 2020-07-13 23:56:00.587 ERROR 35387 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IndexOutOfBoundsException: IndexOutOfBoundsException message] with root cause java.lang.IndexOutOfBoundsException: IndexOutOfBoundsException message at orgg.openingo.x.controller.UserController.ex1(UserController.java:97) ~[classes/:na]
-
-
/ex2
output{ "em": "Cannot deserialize instance of `java.util.LinkedHashMap` out of START_ARRAY token\n at [Source: (String)\"[{asd}]\"; line: 1, column: 1]", "ec": 345 }
-
/ex2
output with friendly message,RespData.Config.FRIENDLY_FAILURE_MESSAGE = "friendly message";
{ "em": "friendly message", "ec": 345 }
-
log.error information
2020-07-14 00:11:15.424 ERROR 35599 --- [nio-8080-exec-2] o.s.b.w.s.error.DefaultErrorAttributesX : **************************************************************** :: SpringApplicationX :: for current request report information **************************************************************** 2020-07-14 00:11:15.436 ERROR 35599 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.LinkedHashMap` out of START_ARRAY token at [Source: (String)"[{asd}]"; line: 1, column: 1] at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) ~[jackson-databind-2.9.9.3.jar:2.9.9.3]
-
-
-
Custom exception error code in your business:
/** * BusinessErrorAttributes * * @author Qicz */ @Component public class BusinessErrorAttributes extends DefaultServiceErrorAttributes { /** * Decorate exception error code, custom for your business logic. * <code> * <pre> * public Object decorateExceptionCode(Exception exception) { * if (exception instanceof IndexOutOfBoundsException) { * return 123; * } * return super.decorateExceptionCode(exception); * } * </pre> * </code> * * @param exception the exception that got thrown during handler execution */ @Override public Object decorateExceptionCode(Exception exception) { if (exception instanceof IndexOutOfBoundsException) { return 123; } return super.decorateExceptionCode(exception); } }