2020-12-28

博客园Logo
首页
新闻
博问
专区
闪存
班级

代码改变世界
搜索
注册
登录
返回主页
刘西东
博客园 首页 新随笔 联系 订阅 管理随笔 - 40 文章 - 0 评论 - 5
Solon 特性简集,相较于 Springboot 有什么区别?
Solon 是一个类似Springboot的微型开发框架,也是一个不基于Servlet的开发框架。项目从2018年启动以来,参考过大量前人作品;历时两年,3500多次的commit;内核保持0.1m的身材,超高的Web跑分,良好的使用体验。

Solon 强调:克制 + 简洁 + 开放的原则;力求:更小、更快、更自由的体验。

所谓更小:

内核0.1m,最小Web开发单位0.2m(相比Springboot项目包,小到可以乎略不计了)。

具用户反映,某些项目切换到Solon后,可以缩减到原来10%的包大小。

所谓更快:

本机helloworld测试,启动最快可达0.09s,Qps可达12万之多。可参考:《helloworld_wrk_test》。

所谓更自由:

代码操控自由:
// 除了注入模式之外,还可以按需手动
//
//手动获取配置
String userName = Solon.cfg().get(“user.name”);
Properties dbcfg = Solon.cfg().getProp(“db”);
//手动获取容器里的Bean
UserService userService = Aop.get(UserService.class);
//手动监听http post请求
Solon.global().post("/user/update", x-> userService.updateById(x.paramMap()));
框架选择自由:
可以用solon-web这样的快速开发集成包。也可以按项目需要选择不同的插件组装,比如:为非Solon项目添加solon.boot.jlhttp,0.2m即可让项目实现http+rpc开发;还可以用MVC开发Socket应用。

特性简集:

1、与Springboot的常用注解比较

Solon 1.2.12 Springboot 2.3.3 说明
@Inject * @Autowired 注入Bean(by type)
@Inject(“name”) @Qualifier+@Autowired 注入Bean(by name)
@Inject(" n a m e " ) @ V a l u e ( " {name}") @Value(" name")@Value("{name}") 注入配置
@Component @Component 托管组件
@Singleton @Scope(“singleton”) 单例(Solon 默认是单例)
@Singleton(false) @Scope(“prototype”) 非单例
@Init * @PostConstruct 构造完成并注入后的初始化
@Configuration @Configuration 配置类
@Bean @Bean 配置组件
@Mapping @RequestMapping,@GetMapping… 映射
@Param @RequestParam 请求参数
@Controller @Controller,@RestController 控制器类
@Service @Service 服务类
@Dao @Dao 数据访问类
Solon 的 @Inject 算是: Spring 的@Value、@Autowired、@Qualifier 三者的结合,但又不完全等价
Solon 托管的 Bean 初始化顺序:new() - > @Inject - > @Init
注1:@Inject 的参数注入,只在Method@Bean上有效
注2:@Inject 的类型注入,只在@Configuration类上有效
2、重要的区别,Solon不是基于Servlet的开发框架

与Springboot相似的体验,但使用Context包装请求上下文。Helloworld效果如下:
@Controller
public class App{
public static void main(String[] args){
Solon.start(App.class, args);
}

@Inject("${app.name}")
String appName;

@Mapping("/")
public Object home(Context c, @Param(defaultValue="noear") String name){
    return  appName + ": Hello " + name;  
}

}
3、与Springboot相似的事务支持@Tran

采用Springboot相同的事件传播机制及隔离级别
@Controller
public class DemoController{
@Db
BaseMapper userService;

@Tran
@Mapping("/user/update")
public void udpUser(long user_id, UserModel user){
    userService.updateById(user);
}

}
4、与Springboot不同的较验方案@Valid

Solon 的方案更侧重较验参数(及批量较验),且强调可见性(即与处理函数在一起)
@Valid
@Controller
public class DemoController {

@NoRepeatSubmit
@NotNull({"name", "icon", "mobile"})
@Mapping("/valid")
public String test(String name, String icon, @Pattern("13\\d{9}") String mobile) {
    return "OK";
}

@Whitelist
@Mapping("/valid/test2")
public String test2() {
    return "OK";
}

}
5、基于标签管理的缓存支持@Cache,与Springboot略有不同

基于标签管理,避免不必要的KEY冲突
@Controller
public class DemoController{
@Db
BaseMapper userService;

@CacheRemove(tags = "user_${user_id}")
@Mapping("/user/update")
public void udpUser(int user_id, UserModel user){
    userService.updateById(user);
}

@Cache(tags = "user_${user_id}")
public UserModel getUser(int user_id){
    return userService.selectById(user_id);
}

}
6、具备语义特性的Bean定义,实现更多可能性

通过语义特性,为Bean增加特性描述;从而实现一些附加的能力
//
// 一个数据主从库的示例
//
@Configuration
public class Config {
//申明 db2 是 db1 为的从库
@Bean(value = “db1”, attrs = { “slaves=db2” })
public DataSource db1(@Inject("${test.db1}") HikariDataSource dataSource) {
return dataSource;
}

@Bean("db2")
public DataSource db2(@Inject("${test.db2}") HikariDataSource dataSource) {
    return dataSource;
}

}
7、支持数据渲染(或输出格式化)的自我控制支持

定制特定场景的控制器基类,负责统一格式化输出
//示例:定制统一输出控制基类,并统一开启验证
//
@Valid
public class ControllerBase implements Render {
@Override
public void render(Object obj, Context ctx) throws Throwable {
if (obj == null) {
return;
}

    if (obj instanceof String) {
        ctx.output((String) obj);
    } else {
        if (obj instanceof ONode) {
            ctx.outputAsJson(((ONode) obj).toJson());
        } else {
            if (obj instanceof UapiCode) {
                //此处是重点,把一些特别的类型进行标准化转换
                //
                UapiCode err = (UapiCode) obj;
                obj = Result.failure(err.getCode(), UapiCodes.getDescription(err));
            }

            if (obj instanceof Throwable) {
                //此处是重点,把异常进行标准化转换
                //
                Throwable err = (Throwable) obj;
                obj = Result.failure(err.getMessage());
            }

            ctx.outputAsJson(ONode.stringify(obj));
        }
    }
}

}
8、不基于Servlet,却很有 Servlet 亲和度。当使用servlet相关的组件时(也支持jsp + tld)

支持 ServletContainerInitializer 配置
@Configuration
public class DemoConfiguration implements ServletContainerInitializer{
@Override
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
//…
}
}
支持 Servlet api 注解
@WebFilter("/demo/*")
public class DemoFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
res.getWriter().write(“Hello,我把你过滤了”);
}
}
9、为服务开发而生的SockeD组件,实现http,socket,websocket相同的信号处理。

支持MVC+RPC开发模式
//[服务端]
@Mapping(value = “/demoe/rpc”, method = MethodType.SOCKET)
@Component(remoting = true)
public class HelloRpcServiceImpl implements HelloRpcService {
public String hello(String name) {
return “name=” + name;
}
}

//[客户端]
var rpc = SocketD.create(“tcp://localhost:28080”, HelloRpcService.class);
System.out.println("RPC result: " + rpc.hello(“noear”));
支持单链接双向RPC开发模式(基于上例扩展)
//[服务端]
@Mapping(value = “/demoe/rpc”, method = MethodType.SOCKET)
@Component(remoting = true)
public class HelloRpcServiceImpl implements HelloRpcService {
public String hello(String name) {
//
//[服务端] 调用 [客户端] 的 rpc,从而形成单链接双向RPC
//
NameRpcService rpc = SocketD.create(Context.current(), NameRpcService.class);
name = rpc.name(name);

    return "name=" + name;
}

}
支持消息发送+监听开发模式
//[服务端]
@ServerEndpoint
public class ServerListener implements Listener {
@Override
public void onMessage(Session session, Message message) {
if(message.flag() == MessageFlag.heartbeat){
System.out.println(“服务端:我收到心跳”);
}else {
System.out.println(“服务端:我收到:” + message);
//session.send(Message.wrapResponse(message, “我收到了”));
}
}
}

//[客户端]
var session = SocketD.createSession(“tcp://localhost:28080”);
session.send(“noear”);
//session.sendAndCallback(“noear”, (rst)->{}); //发送并异常回调
//var rst = session.sendAndResponse(“noear”); //发送并等待响应

System.out.println(rst);
支持消息订阅开发模式
//[客户端]
@ClientEndpoint(uri = “tcp://localhost:28080”)
public class ClientListener implements Listener {
@Override
public void onMessage(Session session, Message message) {
//之后,就等着收消息
System.out.println(“客户端2:我收到了:” + message);
}
}
10、专属RPC客户端组件:Nami

类似于Springboot + Feign的关系,但Nami更简洁(Solon 也可以用Feign)
//[定义接口],一般情况下不需要加任何注解
//
public interface UserService {
UserModel getUser(Integer userId);
}

//[服务端] Component.remoting = true,即为组件开启远程服务
//
@Mappin(“user”)
@Component(remoting = true)
public class UserServiceImpl implements UserService{
public UserModel getUser(Integer userId){
return …;
}
}

//[消费端]
//
@Mapping(“demo”)
@Controller
public class DemoController {

//直接指定服务端地址
@NamiClient("http://localhost:8080/user/")
UserService userService;

//使用负载
@NamiClient("local:/user/")
UserService userService2;

@Mapping("test")
public void test() {
    UserModel user = userService.getUser(12);
    System.out.println(user);

    user = userService2.getUser(23);
    System.out.println(user);
}

}

/**

  • 定义一个负载器(可以对接发现服务)
  • */
    @Component(“local”)
    public class RpcUpstream implements LoadBalance {
    @Override
    public String getServer() {
    return “http://localhost:8080”;
    }
    }
    11、Solon的加强版SPI扩展机制 - 以增加注解为例

1.新建个模块,实现Plugin接口(以增加@Service注解支持为例)
public class XPluginImp implements Plugin {
@Override
public void start(SolonApp app) {
Aop.context().beanBuilderAdd(Service.class, (clz, bw, anno) -> {
bw.proxySet(BeanProxyImp.global());

        Aop.context().beanRegister(bw, "", true);
    });
}

}
2.增加配置文件
src/main/resources/META-INF/solon/solon.extend.aspect.properties
3.增加配置内容,打包发布即可
solon.plugin=org.noear.solon.extend.aspect.XPluginImp
12、Solon内部的事件总线EventBus的妙用

通过事件总线收集异常
//[收集异常]
EventBus.push(err);

//[订阅异常]
EventBus.subscribe(Throwable.class,(event)->{
event.printStackTrace();
});
//或通过SolonApp订阅
app.onEvent(Throwable.class, (err)->{
err.printStackTrace();
});
//或通过组件订阅
@Component
public class ErrorListener implements EventListener {
@Override
public void onEvent(Throwable err) {
err.printStackTrace();
}
}

通过事件总线扩展配置对象
//
// 插件开发时,较常见
//
SqlManagerBuilder builder = new SqlManagerBuilder(ds);
EventBus.push(builder);
附:Solon项目地址

gitee: https://gitee.com/noear/solon
github: https://github.com/noear/solon
标签: springboot, solon, mvc, java, aop
好文要顶 关注我 收藏该文
刘之西东
关注 - 0
粉丝 - 5
+加关注
0 0
« 上一篇: Solon 1.2.12 发布,新的惊喜
posted @ 2020-12-28 11:58 刘之西东 阅读(83) 评论(1) 编辑 收藏

评论列表
#1楼 2020-12-28 13:04 pingko
Pingkoweb Your article really helps me in growing my business. Thank you
支持(0) 反对(0)
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【福利】AWS携手博客园为开发者送免费套餐+50元京东E卡
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· SpringBoot
· SpringBoot
· SpringBoot
· Springboot
· 【SpringBoot】SpringBoot国际化(七)
» 更多推荐…

最新 IT 新闻:
· 相互宝2020年账单出炉:大病互助全年分摊91元 最高发五种重疾公布
· 微信直播,直奔带货?
· 阿里、上汽等投资成立汽车科技公司 注册资本100亿元
· 阿里达摩院2021十大科技趋势:第三代半导体材料将大规模应用
· 银行的羊毛不能薅
» 更多新闻…
公告

昵称: 刘之西东
园龄: 1年
粉丝: 5
关注: 0
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索

找找看

谷歌搜索
常用链接

我的随笔
我的评论
我的参与
最新评论
我的标签
我的标签

java(21)
solon(20)
springboot(12)
snack3(8)
mini(8)
jsonpath(7)
spring(6)
json(5)
web(4)
weed3(4)
更多
随笔档案

2020年12月(12)
2020年9月(2)
2020年8月(9)
2020年7月(2)
2020年6月(1)
2019年12月(12)
2019年11月(2)
最新评论

  1. Re:Solon 特性简集,相较于 Springboot 有什么区别?
    Pingkoweb Your article really helps me in growing my business. Thank you
    –pingko

  2. Re:关于一个简单接口的高并发测试与优化记录
    @努力成为测试大神 当然可以哦:)…
    –刘之西东

  3. Re:关于一个简单接口的并发测试与优化记录
    您好!我是51testing软件测试网编辑,您的这篇文章写得很好,我们想要转载让更多人看到,希望您能够同意,非常感谢!
    –努力成为测试大神

  4. Re:Weed3 for java 新的微型ORM框架
    悲据,这个QQ群。。。怎么就是查不到:(
    –刘之西东

  5. Re:Weed3 for java 新的微型ORM框架
    @ 威尔Q做了些调整,可以再试着加一下。…
    –刘之西东
    阅读排行榜

  6. 关于一个简单接口的高并发测试与优化记录(849)

  7. 更强的 JsonPath 兼容性及性能测试(606)

  8. Weed3 for java 新的微型ORM框架(509)

  9. Java 中 Snack3的使用(358)

  10. Snack3 一个新的微型JSON框架(293)
    评论排行榜

  11. Weed3 for java 新的微型ORM框架(3)

  12. 关于一个简单接口的高并发测试与优化记录(2)
    推荐排行榜

  13. Weed3 for java 新的微型ORM框架(3)

  14. Springboot mini - Solon详解(一)- 快速入门(2)

  15. Springboot mini - Solon详解(六)- Solon的校验框架使用、定制与扩展(1)

  16. Springboot mini - Solon详解(五)- Solon扩展机制之Solon Plugin(1)

  17. Springboot mini - Solon详解(二)- Solon的核心(1)
    Copyright © 2020 刘之西东
    Powered by .NET 5.0 on Kubernetes

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值