Solon2 与 Spring Boot 的区别
1、与 Springboot 的常用注解比较
| Solon 2.2.0 | Springboot 2.7.8 | 说明 |
|---|---|---|
| @Inject * | @Autowired | 注入Bean(by type) |
| @Inject("name") | @Qualifier+@Autowired | 注入Bean(by name) |
| @Inject("${name}") | @Value("${name}") | 注入配置 |
| @Singleton | @Scope(“singleton”) | 单例(Solon 默认是单例) |
| @Singleton(false) | @Scope(“prototype”) | 非单例 |
| @Import | @Import + @ComponentScan | 配置组件导入或扫描(一般加在启动类上) |
| @PropertySource | @PropertySource | 配置属性源(一般加在启动类上) |
| @Configuration | @Configuration | 配置类 |
| @Bean | @Bean | 配置Bean |
| @Condition | @ConditionalOnClass + @ConditionalOnProperty | 配置条件 |
| @Controller | @Controller,@RestController | 控制器类 |
| @Remoting | 远程控制器类(即 Rpc 服务端) | |
| @Mapping ... | @RequestMapping,@GetMapping... | 映射 |
| @Param | @RequestParam | 请求参数 |
| @Header | @RequestHeader | 请求头 |
| @Body | @RequestBody | 请求体 |
| @Cookie | @CookieValue | 请求Cookie |
| @Component | @Component | 普通托管组件 |
| @ProxyComponent | @Service,@Dao,@Repository | 代理托管组件 |
| @Init * | @PostConstruct | 组件构造完成并注入后的初始化 |
| @TestPropertySource | @TestPropertySource | 配置测试属性源 |
| @TestRollback | @TestRollback | 执行测试回滚 |
- Solon 的 @Inject 算是: Spring 的@Value、@Autowired、@Qualifier 三者的结合,但又不完全等价
- Solon 的 @Import 同时有导入和扫描的功能
- Solon 的 Bean 生命周期:new() - > @Inject -> afterInjection()- > start() -> stop()
- 注1:Method@Bean,只执行一次(只在 @Configuration 里有效)
- 注2:@Inject 的参数注入,只在 Method@Bean 上有效
- 注3:@Inject 的类注入,只在 @Configuration类 上有效
- 注4:@Import 只在 主类上 或者 @Configuration类 上有效
2、重要的区别,Solon 不是基于 Servlet 的开发框架
- 与 Springboot 相似的体验,但使用 Context 包装请求上下文(底层为:Context + Handler 架构)。Helloworld 效果:
@SolonMain
public class App{
public static void main(String[] args){
Solon.start(App.class, args);
}
}
@Controller
public class Demo{
@Inject("${app.name}")
String appName;
@Mapping("/")
public Object home(String name){
return appName + ": Hello " + name;
}
}
- 与 Servlet 常见类比较
| Solon 2.2.0 | Springboot 2.7.8 | 说明 |
|---|---|---|
| Context | HttpServletRequest + HttpServletResponse | 请求上下文 |
| SessionState | HttpSession | 请求会话状态类 |
| UploadedFile | MultipartFile | 文件上传接收类 |
| DownloadedFile | 文件下载输出类 | |
| ModelAndView | ModelAndView | 模型视图输出类 |
- Solon 适配有:jdkhttp、jlhttp、smarthttp、jetty、undertow、netty、websocket 等各种通讯容器。
3、Solon 不支持构造函数注入与属性设置注入
- 不支持的:
@Component
public class Demo{
private A a;
private B b;
public Demo(@Inject A a){
this.a = a;
}
public void setB(@Inject B b){
this.b = b;
}
}
- 支持的:
@Component
public class Demo{
@Inject
private A a;
@Inject
private B b;
//@Init
//public void initDo(){
// //Solon 的注入是异步的。想要对注入的 bean 进行实始化,需要借用 @Init 函数
//}
}
或者,可以用 @Configuration + @Bean 进行构建。
4、Solon 可以更自由获取配置
@Component
public class Demo{
//注入配置
@Inject("${user.name}")
private String userName;
//手动获取配置
private String userName = Solon.cfg().get("user.name");
}
5、Solon 的 @Component 与 @ProxyComponent 是有区别的
- @Component 注解的组件,不会被动态代理
- 不支持拦截处理
- 支持函数被注解提取
- 支持形态提取
- @ProxyComponent 注解的组件,会被动态代理。由 solon.proxy 提供能力实现
- 支持拦截处理
各有分工,算有是“克制”的体现。
6、与 Springboot 相似的事务支持 @Tran
- 采用 Springboot 相同的事件传播机制及隔离级别。但回滚时,不需要指定异常类型
@Controller
public class DemoController{
@Db
BaseMapper<UserModel> userService;
@Tran
@Mapping("/user/update")
public void udpUser(long user_id, UserModel user){
userService.updateById(user);
}
}
7、与 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";
}
@Mapping("/valid/test3")
public String test3(@Validated UserModel user) {
return "OK";
}
}
8、基于标签管理的缓存支持 @Cache,与 Springboot 略有不同
- 支持Key的缓存管理。同时增加了基于标签的缓存管理,避免不必要的Key冲突
@Controller
public class DemoController{
@Db
BaseMapper<UserModel> 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);
}
}
9、相似的 @Bean 设计
- 相似的特性。且,需与 @Configuration 协同使用
//
// 一个数据主从库的示例
//
@Configuration
public class Config {
@Bean(name = "db1", typed = true)
public DataSource db1(@Inject("${test.db1}") HikariDataSource dataSource) {
return dataSource;
}
@Bean("db2")
public DataSource db2(@Inject("${test.db2}") HikariDataSource dataSource) {
return dataSource;
}
}
- 使用 @Bean(typed=true) 做为某种类型的默认Bean
10、支持数据渲染(或输出格式化)的自我控制支持
- 定制特定场景的控制器基类,负责统一格式化输出
//示例:定制统一输出控制基类,并统一开启验证
//
@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));
}
}
}
}
11、不基于 Servlet,却很有 Servlet 亲和度。当使用 servlet 相关的组件时(也支持jsp + tld)
- 支持 Servlet 请求与响应对象注入
@Mapping("/demo/")
@Controller
public class DemoController {
@Mapping("hello")
public void hello(HttpServletRequest req, HttpServletResponse res){
}
}
- 支持 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,我把你过滤了");
}
}
12、为服务开发而生的 SockeD 组件,实现 http, socket, websocket 相同的信号处理。
- 支持 MVC+RPC 开发模式
//[服务端]
@Socket
@Mapping("/demoe/rpc")
@Remoting
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 开发模式(基于上例扩展)
//[服务端]
@Socket
@Mapping("/demoe/rpc")
@Remoting
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);
}
}
13、专属 Rpc 客户端组件:Nami
- 类似于 Springboot + Feign 的关系,但 Nami 更简洁且支持 socket 通道( Solon 也可以用 Feign )
//[定义接口],一般情况下不需要加任何注解
//
public interface UserService {
UserModel getUser(Integer userId);
}
//[服务端] @Remoting,即为远程组件
//
@Mappin("user")
@Remoting
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(name="local", path="/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";
}
}
14、Solon 的加强版 Spi 扩展机制 - 具备可编程性
- 新建模块,并实现Plugin接口(以增加 @ProxyComponent 注解支持为例)
public class XPluginImp implements Plugin {
@Override
public void start(AopContext context) {
context.beanBuilderAdd(ProxyComponent.class, (clz, bw, anno) -> {
BeanProxy.binding(bw);
});
}
}
- 增加配置文件
src/main/resources/META-INF/solon/solon.aspect.properties
- 增加配置内容,打包发布即可
solon.plugin=org.noear.solon.aspect.XPluginImp
15、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<Throwable> {
@Override
public void onEvent(Throwable err) {
err.printStackTrace();
}
}
- 通过事件总线扩展配置对象
//
// 插件开发时,较常见
//
SqlManagerBuilder builder = new SqlManagerBuilder(ds);
EventBus.push(builder);
16、Aop 扩展,扫描一次 + 注册处理(也是启动快的原因之一)
- 注册‘构建器’处理。以注册 @Controller 构建器为例:
Solon.context().beanBuilderAdd(Controller.class, (clz, bw, anno) -> {
//内部实现,可参考项目源码 //构建器,可以获取类型并进行加工
new HandlerLoader(bw).load(Solon.global());
});
//效果
@Controller
public class DemoController{
}
- 注册'注入器'处理。以注册 @Inject 注入器为例:
Solon.context().beanInjectorAdd(Inject.class, ((fwT, anno) -> {
//内部实现,可参考项目源码 //注入器,可以根据目标生成需要的数据并赋值
beanInject(fwT, anno.value(), anno.autoRefreshed());
}));
//效果
@Controller
public class DemoController{
@Inject
UserService userService;
}
- 注册'拦截器'处理。以注册 @Tran 拦截器为例:
//拦截器,可以获取执行动作链
Solon.context().beanAroundAdd(Tran.class, new TranInterceptor(), 120);
//效果
@ProxyComponent
public class UserService{
@Tran
public void addUser(User user){
}
}
- 注册'提取器'处理。以注册 @CloudJob 提取器为例:
//内部实现,可参考项目源码 //提取器,可以提取被注解的函数
Solon.context().beanExtractorAdd(CloudJob.class, CloudJobExtractor.instance);
//效果 //提取器只对组件有效
@Component
public class Job{
@CloudJob
public void statUserJob(){
}
}
Solon2 与 Spring Boot 的区别的更多相关文章
- Spring Cloud和Spring Boot的区别
Spring MVC: Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 MVC ...
- Spring/Spring MVC/Spring Boot的区别
1.spring boot更简单,容易上手: 2.spring boot对第三方技术进行了很好的封装,提供了大量的第三方接口: 3.通过依赖配置,不需要XML等配置文件: 4.提供了安全性等特性. S ...
- 阿里面试官:小伙子,给我说一下Spring 和 Spring Boot 的区别吧
前言 对于 Spring和 SpringBoot到底有什么区别,我听到了很多答案,刚开始迈入学习 SpringBoot的我当时也是一头雾水,随着经验的积累.我慢慢理解了这两个框架到底有什么区别,相信对 ...
- spring 和 spring boot 的区别
最近越来越多的开发者都开始选择 spring-boot,与传统的 spring 相比,spring-boot又有哪些优势呢? 1.追求开箱即用的效果,只需要很少的配置就可以直接开始运行项目. 例如各种 ...
- spring mvc和spring boot的区别
spring boot只是一个配置工具,整合工具,辅助工具. springmvc是框架,项目中实际运行的代码 Spring 框架就像一个家族,有众多衍生产品例如 boot.security.jpa等等 ...
- Spring Boot学习笔记:传统maven项目与采用spring boot项目区别
项目结构区别 传统的maven构建的项目结构如下: 用maven构建的采用springboot项目结构如下: 二者结构一致,区别如下:传统项目如果需要打成war包,需要在WEB-INF目录结构配置we ...
- Spring MVC和Spring Boot的理解以及比较
Spring MVC是什么?(1)Spring MVC是Spring提供的一个强大而灵活的模块式web框架.通过Dispatcher Servlet, ModelAndView 和 View Reso ...
- Spring boot --- 自动配置
spring boot 自动配置 指的是针对很多spring 应用程序常见的应用功能,spring boot 能自动提供相关配置. spring boot 自动配置加载 Spring boot ...
- Spring Boot项目微信云托管入门部署
微信云托管本身是一个服务器,里面的软件都已经配置好了,直接使用即可,适用于一些简单部署的项目.直接把项目直接上传到服务器即可.无需各种繁琐的软件配置和打包,微信云托管统统给你搞定.而且系统会根据使用量 ...
- Spring Boot与Spring的区别
转自:https://blog.csdn.net/sinat_36246371/article/details/72902406 Spring Boot是最近这几年才火起来的,那么它到底与Spring ...
随机推荐
- Python requests 上传文件(以上传图片为例)
from requests_toolbelt import MultipartEncoderimport requests encoderl = MultipartEncoder( fields = ...
- MongoDB安全加固,防止数据库攻击删除勒索威胁
前言: 今天发现前段时间自己搭建的一个系统的MongoDB数据找不到了,觉得很奇妙,然后登上MongoDB数据库发现多了一个名为READ__ME_TO_RECOVER_YOUR_DATA的数据库,里面 ...
- Spring面试点汇总
Spring面试点汇总 我们会在这里介绍我所涉及到的Spring相关的面试点内容,本篇内容持续更新 我们会介绍下述Spring的相关面试点: Spring refresh Spring bean Sp ...
- TS学习笔记
类型 类型 例子 描述 number 1,2,-2 任意数字 string 'hi',"hi" 任意字符串 boolean true,false 布尔值或者true false 字 ...
- [常用工具] git基础学习笔记
git基础学习笔记,参考视频:1小时玩转 Git/Github 添加推送信息,-m= message git commit -m "添加注释" 查看状态 git status 显示 ...
- 推荐给Amy的书单
目录 皮囊 推荐等级 ※ ※ ※ ※ ※ 白夜行 推荐等级 ※ ※ ※ ※ ※ 人生 推荐等级 ※ ※ ※ ※ 活着 推荐等级 ※ ※ ※ ※ 许三观卖血记 推荐等级 ※ ※ ※ ※ 皮囊 推荐等级 ...
- 升级csproj文件为vs2017工程格式(SDK样式)
csproj文件在VS2017后格式变更为SDK样式.framework项目如果需要源链接等等功能,需要进行手动升级. 升级过程 升级需要Project2015To2017Nuget包. > d ...
- BOM、DOM、两者查找标签的方式和操作标签的方式、操作class和css的方法、事件、jQuery类库
今日内容 BOM操作 BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏览器进行"对话". windows对象 windo ...
- Axure 列表左右滑动交互-删除、置顶
Axure 列表左右滑动交互 左滑:删除.标记 右滑:置顶.回复 拖一个动态面板,命名为[滑动面板],添加三个状态,并分别命名为:正常状态.向左状态.向右状态 添加元件 正常状态 向左状态 将[正常状 ...
- 除了Navicat和DBeaver,还有没有免费又好用的数据库管理/SQL工具推荐
很多国内SQL学习者和开发者对Navicat.DBeaver等国外数据库管理工具已经很熟悉了.但是,有没有比他们更适合SQL开发者的数据库管理/SQL工具呢?这里,笔者结合自己的调研来聊一下. 笔者做 ...