Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/openingo/spring-boot-x
spring-boot extensions
https://github.com/openingo/spring-boot-x
spring-boot spring-boot-extensions
Last synced: 10 days ago
JSON representation
spring-boot extensions
- Host: GitHub
- URL: https://github.com/openingo/spring-boot-x
- Owner: openingo
- License: other
- Created: 2020-07-08T03:24:53.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2022-07-01T10:05:35.000Z (over 2 years ago)
- Last Synced: 2023-08-06T09:02:11.893Z (over 1 year ago)
- Topics: spring-boot, spring-boot-extensions
- Language: Java
- Homepage:
- Size: 534 KB
- Stars: 7
- Watchers: 3
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## spring-boot-x
> spring-boot-extensions
![maven](https://img.shields.io/maven-central/v/org.openingo.boot/spring-boot-x.svg)
[spring-boot-x specification(cn)](https://izcqi.com/posts/2021/01/09/spring-boot-x-specify/)
### [Release Notes](RELEASENOTES.md)
### Features
- Manual transaction
- `ManualTransactionManager`
- GeDid: Distributed id generator.
- `RedisIdEngine`
- `ZookeeperIdEngine`
- `UuidEngine`
```java
@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");
}
}
```
[Read More About GeDid](https://izcqi.com/posts/2021/07/01/gedid/)- Elasticsearch supports
- the `RestHighLevelClientX` extension for `RestHighLevelClient`, simplification for doc operations:`saveOrUpdate`,`deleteById(s)`,`findById(s)`,`search`.
- the `ElasticsearchTemplateLite` extension for `ElasticsearchTemplate`
- base on ElasticsearchTemplate `7.2.0` and dependency jars(rest client & rest high level client)
- request log:```bash
****************************************************************
:: 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
```json
{
"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?
```java
@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));
}
``````java
/**
* 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]
### How to use?
- Dependency:
```xml
org.openingo.boot
spring-boot-x
new_version
```- Add `@EnableExtension` in your main application class:
- Configuration:
```yml
openingo:
redis:
enable: true
http:
request:
cors:
allowed-header: "*"
enable: true
allowed-all: true
log:
enable: true
error:
enable: true
```- `RespData.Config`
```java
/**
* 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
```java
@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
```json
{
"em": "IndexOutOfBoundsException message",
"ec": 123
}
```- `/ex1`output with friendly message, `RespData.Config.FRIENDLY_FAILURE_MESSAGE = "friendly message";`
```json
{
"em": "friendly message",
"ec": 123
}
```- log.error information
```bash
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
```json
{
"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";`
```json
{
"em": "friendly message",
"ec": 345
}
```- log.error information
```bash
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:
```java
/**
* BusinessErrorAttributes
*
* @author Qicz
*/
@Component
public class BusinessErrorAttributes extends DefaultServiceErrorAttributes {
/**
* Decorate exception error code, custom for your business logic.
*
*
* public Object decorateExceptionCode(Exception exception) {
* if (exception instanceof IndexOutOfBoundsException) {
* return 123;
* }
* return super.decorateExceptionCode(exception);
* }
*
*
*
* @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);
}
}
```
- [Demo](./spring-boot-x-demo)