Solon 1.6.10 重要發布,現在有官網嘍!

關於官網

千呼萬喚始出來: //solon.noear.org 。整了一個月多了,總體樣子有了。。。還得不斷接著整!

關於 Solon

Solon 是一個輕量級應用開發框架。支援 Web、Data、Job、Remoting、Cloud 等任何開發場景。短小而精悍!

  • 強調,克制 + 簡潔 + 開放的原則
  • 力求,更小、更快、更自由的體驗

關於 Solon Cloud

Solon Cloud 定義了一系列分散式開發的介面標準和配置規範,相當於DDD模式里的防腐層概念。是 Solon 的微服務架構模式開發解決方案。

關於本次更新

1、增加了第三方日誌框架的適配。以往是直接使用日誌框架,親合度差了一些

  • 新增 log4j2-solon-plugin 插件
  • 新增 logback-solon-plugin 插件

之前只適配了分散式日誌服務。現在也有本地的了。且,統一的配置方式(默認可以0配置):

solon.app:
  name: demoapp

# 以下為默認值,可以都不加,或者想改哪行加哪行(支援"雲端配置服務"進行配置,支援寫到"雲端日誌服務")
solon.logging.appender:
  console:
    level: TRACE
    pattern: "%highlight(%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [-%t][*%X{traceId}]%tags[%logger{20}]:) %n%msg%n"
  file:
    name: "logs/${solon.app.name}"
    level: INFO
    pattern: "%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [-%t][*%X{traceId}]%tags[%logger{20}]: %n%msg%n"
  cloud:
    level: INFO
    
# 記錄器級別的配置示例
solon.logging.logger:
  "features.*":
    level: WARN
  "org.jetty.demo.*":
    level: WARN    

並以 slf4j 做為統一的記錄介面

@Slf4j
@Service
public class DemoService{
    public void hello(){
        log.info("Hello world!");
    }
}

2、增加了一些便利介面和使用方式

  • 增加 Context::sessionAsInt, Context::sessionAsLong, Context::sessionAsDouble 介面
  • 增加 Context::sessionRemove 介面
  • 修復 solon.extend.stop 用戶ip獲取錯誤
  • 增加 mybatisplus-solon-plugin 為 globalConfig 注入內容的入口
  • 集成包 solon-api 默認添加 solon.extend.cors 插件
  • 增加 主體流注入支援(@Body InputStream body)
  • 取消 solon.cache 插件,由 solon.data 插件集成相關功能,並提供工廠擴展機制
  • 增加 上下文特性,自動做為模板變數
  • 增加 JsonRenderFactory 的事件擴展支援
  • 增加 模板引擎配置 事件擴展機制

綜合一些特性,做個簡單的組合演示

public class DemoApp{
    public static void main(String[] args){
        Solon.start(DemoApp.class, args, app->{
            //增加默認的跨域支援(支援它的插件,現在默認集成到了 solon-api 集成包里)
            app.before(new CrossHandler().exposedHeaders("sign,token"));
        
            //訂製渲染工廠(現在,不管哪個Json 框架都可基於 JsonRenderFactory 進行統一的訂製)
            app.onEvent(JsonRenderFactory.class, f->{
                //json渲染時,將 long 型統一轉為 string
                f.addConvertor(Long.class, v-> String.valueOf(v));
            });
            
            //訂製ftl模板配置
            app.onEvent(freemarker.template.Configuration.class, c -> {
                //增加經典模式支援
                c.setSetting("classic_compatible", "true");
                c.setSetting("number_format", "0.##");
            });
        });
    }
}

@Configuration
public class DemoConfig {
    //通過供應商模式,自動構建不同的快取服務類型(從原來的 solon.cache 轉移到 solon.data 插件)
    @Bean
    public CacheService cache1(@Inject("cache1") CacheServiceSupplier supplier) {
        return supplier.get();
    }
}

@Controller
public class DemoController{
    @Mapping("/login")
    public void login(Context ctx){
        //到登錄頁時,把 user_id 刪掉;確保用戶重新登錄
        ctx.sessionRemove("user_id");
    }
    
    @Mapping("/admin")
    public void admin(Context ctx){
        long userId = ctx.sessionAsLong("user_id");
        if(userId == 0){
            //如果用戶id為0,則302跳轉到登錄面
            ctx.redirect("/login");
        }
    }
    
    @Mapping("/admin/group/edit.save")
    public void admin_group_edit_save(long groupId, String name, @Body String meta){
        //groupId, name 通過 queryString 傳入;meta 是通過 body 傳入的純文本
    }
}

@Component
public class DemoFilter implements Filter{
    @Override
    public void doFilter(Context ctx, FilterChain chain) throws Throwable {
        //給所有模板增加全局變數(或公共變數)
        ctx.attrSet("js", "/_static/js");
        ctx.attrSet("css", "/_static/css");
        
        chain.doFilter(ctx);
    }
}

3、能力或兼容性增強

  • 增加 @Init 私有函數支援
  • 增加 @Bean 私有函數支援
  • 增加 @Inject(“${xxx:}”),默認值為空的支援
  • 增加 StringSerializerRender 對 renderAndReturn 的支援
  • 增加 Context::renderAndReturn 支援非視圖數據
  • 調整 EventListener 充許 onEvent 拋出異常
  • 調整 初始化失敗時,自動停掉所有插件並結束進程
  • 增加 上下文特性,自動做為模板變數
  • 優化 配置注入”${xxx:def}”的兼容性,def有”:”符也沒關係了
  • 增加 Mvc 數組參數注入時,自動以,號分離為數組
  • 增加 @Init::index 屬性
  • 增加 容器掃描去重去處
  • 取消 @Param::format 屬性(自動處理增加17種格式)
@Configuration
public class DemoConfig {
    //以前必須要用 public
    @Bean
    private CacheService cache1(@Inject("cache1") CacheServiceSupplier supplier) {
        return supplier.get();
    }
    
    @Init
    private void init(){
        //...
    }
}

@Controller
public class DemoController{

    //以前是不能在默認值里出現:號的
    @Inject("${user.name:noear:org}")
    String userName;
    
    @Mapping("/test")
    public String test(Context ctx){
        UserModel user = userService.get(1);
        
        //現在可以藉助上下文的渲染函數進行序列化(默認是json,也可指定渲染器)
        ctx.attrSet("@render","@json");
        String json = ctx.renderAndReturn(user);
        
        return Base64Utils.encode(json);
    }
}

快速了解 Solon 的材料:

《Solon 特性簡集,相較於 Springboot 有什麼區別?》

《Solon Cloud 分散式服務開發套件清單,感覺受與 Spring Cloud 的不同》

《Solon 的想法與架構筆記》

所謂更小:

內核0.1m,最小的介面開發單位0.2m(相較於 Dubbo、Springboot 的依賴包,小到可以乎略不計)

所謂更快:

本機http helloworld測試,Qps可達12萬之多。可參考:《helloworld_wrk_test

所謂更自由:(程式碼操控自由)

// 除了註解模式之外,還可以按需手動
//
//手動獲取配置(Props 為 Properties 增強版)
Props db = Solon.cfg().getProp("db");

//手動獲取容器里的Bean
UserService userService = Aop.get(UserService.class);

//手動監聽http post請求
Solon.global().post("/user/update", x-> userService.updateById(x.paramMap()));

//手動添加個RPC服務
Solon.global().add("/rpc/", HelloService.class, true);

//手動獲取一個RPC服務消費端
HelloService helloService = Nami.builder().create(HelloService.class);

//手動為容器添加組件
Aop.wrapAndPut(DemoService.class);

附:項目地址

附:入門示例

更多系統的學習內容,建議參考官網