# nut **Repository Path**: yeskery/nut ## Basic Information - **Project Name**: nut - **Description**: Java编写自带MVC框架的HTTP服务器,支持多种方式启动,支持HTTPS,并实现类类Spring MVC的部分注解,提供了IOC注解、AOP注解、事务注解、异步注解等,用来学习HTTP及Web框架相关知识,未强制使用第三方依赖,自定义Request、Response、Cookie、Session及ServerContext,基于JDK1.8开发。 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2019-03-13 - **Last Updated**: 2025-10-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Nut Java编写自带MVC框架的HTTP服务器,支持Sun、Netty、Jetty、Tomcat方式启动,支持HTTP和HTTPS协议及Websocket,并实现了类Spring MVC的部分注解,提供IOC注解(Component、Autowired、Qualifier),提供AOP注解(Before、After、Throwing),提供条件装配注解(Conditional),提供异步注解(Async),提供事务注解(Transactional),提供事件注解(EventListener),用来学习HTTP及Web框架相关知识,未强制使用第三方依赖,未实现标准的Servlet规范,自定义Request、Response、Cookie、Session及ServerContext,基于JDK1.8开发。 # 特性 1. 支持Sun(无需其他依赖)、Netty、Jetty、Tomcat方式启动服务; 2. 支持HTTP与HTTPS(支持pem和jks格式证书,Tomcat仅支持JKS证书); 3. 支持WebSocket(Netty、Jetty、Tomcat方式); 4. 支持SSE(Netty、Jetty、Tomcat方式); 5. 以插件形式支持MyBatis、MyBatis-Plus、MyBatisFlex; 6. 以插件方式支持Redis(Jedis、Lettuce); 7. 以插件方式支持Junit5单元测试(`@NutBootTest`注解); 8. 已实现MVC注解(如`@Controller`、`@RestController`、`@RequestParam`、`@ResuestBody`、`@ResponseBody`、`@RequestMapping`等注解); 9. 已实现IOC注解(如`@Component`、`@Service`、`@Repository`、`@Autowired`、`@Qualifier`、`@Lazy`、`@Primary`等注解); 10. 已实现条件装备注解(如`@Conditional`、`@ConditionalOnClass`、`@ConditionalOnBean`、`@ConditionalOnApplicationType`等注解); 11. 已实现AOP注解(如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@Throwing`、`@Around`、`@Compose`); 12. 已实现环境注解(`@ConfigurationProperties`、`@Value`); 13. 已实现异步注解(`@Async`); 14. 已实现定时调度注解(`@Scheduled`); 15. 已实现事务注解(`@Transactional`); 16. 已实现事件注解(`@EventListener`、`@TransactionalEventListener`); 17. 已实现WebSocket注解(`@Websocket`、`@PathParam`、`@OnOpen`、`@OnClose`、`@OnMessage`、`@OnError`); 18. 已实现类Feign注解(`@EnableFeignClients`、`@FeignClient`); 19. 已实现注解中心注解(`@EnableInlayServerRegistry`、`@EnableNacosServerRegistry`、`@EnableRedisServerRegistry`); 20. 提供多个扩展点(如`BeanPostProcessor`、`BeanDefinitionPostProcessor`等); 21. 提供OpenApi3格式的文档功能(`@ApiGroup`、`@Api`等注解); 22. 可作为简单的静态文件服务器使用; 23. 可开启脚本接口支持,通过编写配置文件快速搭建测试接口; 24. 支持多种视图表达式(可自行扩展); 25. 支持多种函数表达式(可自行扩展); 26. 支持表达式嵌套使用; 27. 支持脚本文件监听,脚本文件修改后自动刷新接口。 # 使用 可直接使用`java -jar nut-1.x.x-SNAPSHOT.jar`进行启动,也可以配置启动参数,目前如下参数可以配置: | 参数名 | 默认值 | 说明 | |:------------------|:-----------------------------------------|----------------| | env | 无 | 环境变量 | | port | 8080 | 端口号 | | maxRequestSize | 无 | HTTP请求体最大字节数限制 | | secure | false | 是否以HTTPS启动 | | secureKeyType | 无 | 安全证书类型:jks、pem | | jksPath | 无 | jks证书库路径 | | jkPassword | 无 | jks证书库密码 | | pemPublicKeyPath | 无 | pem证书公钥路径 | | pemPrivateKeyPath | 无 | pem证书私钥路径 | | staticDir | 无 | 静态资源的磁盘目录 | | staticPath | 无 | 静态资源的访问路径 | | staticDirPreview | false | 是否开启静态资源目录预览 | | enableScript | false | 是否开启脚本 | | scriptPath | 无 | 脚本资源的磁盘路径 | | scriptEncoding | UTF-8 | 脚本的字符编码集 | | enableScriptWatch | false | 是否开启脚本文件监听 | | logHandlers | ..NutLoggingConsoleHandler,..FileHandler | 日志处理器 | | logFormatter | ..NutLoggingFormatter | 日志格式化器 | | logLevel | INFO | 日志级别 | | logDir | ./logs | 日志存储目录 | 目前支持如下参数配置方式: 1. 调用`Nut#run(NutConfiguration, String[])`方式启动Nut,该方式只支持部分参数; 2. 使用操作系统的环境变量形式进行配置,该方式支持全部参数; 3. 使用JVM参数形式,例如:`java -Dserver.port=80 -jar nut-1.0.1-SNAPSHOT.jar`,该方式支持全部参数; 4. 使用程序参数形式,例如:`java -jar nut-1.0.1-SNAPSHOT.jar server.port=80`,该方式支持全部参数; > 配置优先级(从低到高):`Nut#run(NutConfiguration, String[])` -> 操作系统的环境变量形式 -> JVM参数形式 -> 程序参数形式。 > 如开启 enableScriptWatch 后,将会自动监听脚本文件,脚本文件更新后无需重启服务即可重新加载脚本文件。如修改访问路径,自动加载配置后,旧访问路径仅仅保留之前的接口信息,但仍然可以访问,新接口将保持修改后的最新信息。 jks服务启动参数示例: `java -Dserver.env=dev -Dserver.port=443 -Dserver.secure=true -Dserver.secureKeyType=jks -Dserver.jksPath=/root/cert/keystore.jks -Dserver.jksPassword=a51DGpI6 -Dserver.enableScript=true -Dserver.scriptPath=/root/request.txt -Dserver.enableScriptWatch=true -jar nut-1.0.1-SNAPSHOT.jar` pem服务启动参数示例: `java -Dserver.env=dev -Dserver.port=443 -Dserver.secure=true -Dserver.secureKeyType=pem -Dserver.pemPublicKeyPath=/root/cert/fullchain.pem -Dserver.pemPrivateKeyPath=/root/cert/privkey.pem -Dserver.enableScript=true -Dserver.scriptPath=/root/request.txt -Dserver.enableScriptWatch=true -jar nut-1.0.1-SNAPSHOT.jar` ## Maven依赖 Nut 已上传到Maven中仓仓库,可通过以下方式进行使用: ### 使用Nut ```xml com.yeskery.nut nut 1.0.36 ``` ### 使用Nut-Standard ```xml com.yeskery.nut nut-standard 1.0.36 pom ``` ### 使用Nut-Netty ```xml com.yeskery.nut nut-netty 1.0.36 pom ``` ### 使用Nut-Jetty ```xml com.yeskery.nut nut-jetty 1.0.36 pom ``` ### 使用Nut-Tomcat ```xml com.yeskery.nut nut-tomcat 1.0.36 pom ``` ## 静态文件web服务 作为静态文件web服务使用时,可通过命令行参数进行配置: `java -Dserver.staticDir={静态资源的磁盘目录} -Dserver.staticPath={静态资源的访问路径} -jar nut-1.0.1-SNAPSHOT.jar` 例如: `java -Dserver.staticDir=/root/static -Dserver.staticPath=/static -Dserver.staticDirPreview=true -jar nut-1.0.1-SNAPSHOT.jar` 启动成功后可通过`http://localhost:8080/static/` 进行访问(默认提供一个简易的无密码保护的目录浏览页面),也可通过直接访问`http://localhost:8080/static/*` 对文件进行下载(*为staticDir下的静态文件) ## 自动接口脚本 通过该功能可以在本地以编写配置文件的方式对外提供HTTP服务,而无需进行代码开发,用于测试或临时接口提供时使用。可通过命令行参数进行配置: `java -Dserver.enableScript=true -Dserver.scriptPath={脚本资源的磁盘路径(多个脚本可以使用逗号(,)进行分割)} -jar nut-1.0.1-SNAPSHOT.jar` 例如: `java -Dserver.enableScript=true -Dserver.scriptPath=/root/script.txt -jar nut-1.0.1-SNAPSHOT.jar` ### 脚本编写方式 脚本以`[`开始,以`]`结束,在中括号包裹的范围内需要配置`path`、`method`、`response_header`、`response_cookie`、`body`五个参数,其中`path`、`method`、`body`是必填项目,`response_header`、`response_cookie`是非必填项目。 | 参数名 | 参数说明 | 备注 | |:--------------------|:---------|--------------------------------------------------| | path | 访问路径 | 如:`/path` 多个路径可以用逗号(,)拼接,如:`/path1,/path2` | | method | 访问方法 | 可选值为HTTP规范中支持的方法如:`get`、`post`等,如需要配置所有方法可设置为`*` | | response_header(可选) | 响应头 | 向请求方的响应中加入指定的响应头 | | response_cookie(可选) | 响应cookie | 向请求方的响应中加入指定的cookie | | body | 响应体 | 向请求方响应指定内容 | 接口可配置成单行,如:`[path=/path1;method=get;response_header=[name=value];response_cookie=[name=value];body=hello world;]` 也可配置多行,在多行中分号(;)可选,如: ``` [ path=/path2 method=get response_header=[name=value] response_cookie=[name=value] body=hello world ] ``` 在`body`参数中,如果响应的内容过多可以采用多行文本方式进行配置,以```开始和结束,和markdown语法一致。 ``` [ path=/path3 method=get response_header=[name=value] response_cookie=[name=value] body=%text(```hello world ```) ] ``` > 脚本只处理`[表达式]`之间的内容,其他格式的内容均不会影响脚本的解析,所以非`[表达式]`的内容均会被忽略,这些内容都可以作为注释存在在脚本文件中,例如: ``` # 单行脚本注释 [path=/path1;method=get;response_header=[name=value];response_cookie=[name=value];body=hello world;] // 多行脚本注释 [ path=/path2 method=get response_header=[name=value] response_cookie=[name=value] body=hello world ] ``` ### 视图表达式 在`body`中,支持视图表达式以响应不同的媒体类型,视图表达式以`%`开始,后接视图名称,后以`()`包裹的内容为视图表达式参数,如:`%text(hello wolrd)`,目前支持的视图表达式如下: | 视图表达式名称 | 表达式说明 | |:--------|:-------| | text | 纯文本视图 | | html | html视图 | | xml | xml视图 | | json | json视图 | | file | 文件视图 | | image | 图片视图 | 如: `[path=/path4;method=get;body=%html(

hello,world

);]`,则可以提供html视图给请求方。 `[path=/path5;method=get;body=%file(/root/record.txt);]`,则可以将本地`/root/record.txt`文件里的内容提供请求方。 `[path=/path6;method=get;body=%image(/root/sun.jpg);]`,则可以将本地`/root/sun.jpg`图片提供给请求方。 **其中视图表达式可以进行嵌套处理**, 例如: `[path=/path7;method=get;body=%html(%file(/root/hello.html));]`,则可以将本地的`/root/hello.html`以HTML媒体类型的方式响应给请求方。 ### 函数表达式 在`response_header`、`response_cookie` 和 `body` 中支持使用函数表达式,函数表达式以`$`开始,后接函数名称,后以`()`包裹的内容为函数参数,如:`$upper(abc)`,目前支持的函数表达式如下: #### WEB函数 | 函数表达式 | 函数表达式名称 | 参数名 | 函数表达式说明 | |:---------------|:---------|:-------------|:--------------------------------------------------| | cookie | cookie函数 | (name) | 获取请求中的cookie值,如$cookie(name)获取请求中的名称为name的cookie值 | | header | 请求头函数 | (name) | 获取请求中的header值,如$header(name)获取请求中的名称为header的请求头值 | | path | 请求路径函数 | 无参数 | 获取请求的路径 | | method | 请求方法函数 | 无参数 | 获取请求的方法 | | param | 请求参数函数 | (name) | 获取请求参数,在url中的参数或以表单方式提交的参数,name:参数名 | | pathVariable | 路径参数函数 | (name) | 获取路径请求参数,在url中的路径参数,如:`/user/{id}`,name:参数名 | | requestBody | 请求体函数 | 无参数 | 以字符串形式获取请求体内容 | | responseStatus | 响应状态码函数 | (code, body) | 返回指定的Http响应状态码,code:状态码,body:响应体内容 | #### 安全函数 | 函数表达式 | 函数表达式名称 | 参数名 | 函数表达式说明 | |:------|:--------|:------|:-------------------------| | md5 | md5函数 | (str) | 将指定的字符串进行md5散列运算并获取计算后的值 | | sha | sha函数 | (str) | 将指定的字符串进行sha散列运算并获取计算后的值 | #### 通用函数 | 函数表达式 | 函数表达式名称 | 参数名 | 函数表达式说明 | |:-----------|:---------|:------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | fupper | 首字母大写函数 | (str) | 将给定的字符串转换为以首字母大写的形式返回,str:字符串 | | upper | 字母大写函数 | (str) | 将给定的字符串转换为大写的形式返回,str:字符串 | | lower | 字母小写函数 | (str) | 将给定的字符串转换为小写的形式返回,str:字符串 | | random | 随机函数 | [a, b] 或 (number, number(可选)) | 获取随机数,直接传入数组,将在数组中随机一个元素返回。
只传入一个`number`则返回`0-number`之间的一个随机数。
传入两个`number`则返回两个`number`之间的随机数
支持整数和小数 | | subString | 字符串截取函数 | (str, separator(可选), int(可选), int) | 字符串截取,str:要截取的字符串,
(str, int)截取从指定的索引开始(包括)的字符串;
(str, int, int)截取从指定索引开始(包括)从指定索引结束(不包括)的字符串;
(str, separator, int, int) 在给定separator标志后指定索引开始(包括)从指定索引结束(不包括)的字符串; | | date | 日期函数 | (pattern(可选), startTime(可选), endTime(可选)) | 无参数时候,获取当前时间戳;
(pattern),格式化当前时间;
(startTime, endTime)从指定范围随机返回一个时间戳;
(pattern, startTime, endTime)格式化指定范围内的时间; | | jsonObject | Json对象函数 | (json, field) | 获取json中的字段值,json:json字符串,field:字段名,可多级嵌套,如:`user.address.code` | #### 扩展函数 | 函数表达式 | 函数表达式名称 | 参数名 | 函数表达式说明 | |:---------------|:---------|:------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------| | nameGenerator | 姓名生成函数 | (surname[可选], boy[可选]) | 中文姓名生成,surname=1为复姓,surname=0或不传为单姓名,boy=1为男性,boy=0或不传为女性 | | ipGenerator | ip生成函数 | 无 | ipv4地址随机生成 | | phoneGenerator | 手机号生成函数 | (op[可选]) | op运营商:0 移动 1 联通 2 电信 | | uuidGenerator | uuid生成函数 | (separator[可选]) | UUID生成,true:包含分隔符,false:不包含分隔符 | | http | Http请求函数 | (url, method[可选], headers[可选], body[可选]) | 以http请求获取指定url的响应结果
method,请求方法,支持以下方法:GET、POST、PUT、DELETE
headers,请求头,以`=`拼接,多个请求头以`&`分割,例如:name1=value1&name2=value2 | | js | JS请求函数 | (js) | 执行JS函数,使用JDK的JS引擎运行,语法参考JDK使用 | | valid | 验证函数 | (expression, success[可选], failure[可选]) | 验证指定的表达式是否为真,真时返回success表达式,默认`success`,假时返回failure表达式,默认`failure`。
表达式支持`&&`和 || 逻辑运算符,支持`==`、`!=`、`>=`、`>`、`<=`、`<`关系运算符 | ##### 内存存储函数 | 函数表达式 | 函数表达式名称 | 参数名 | 函数表达式说明 | |:--------|:--------|:--------------------------|:------------------------------------------------------| | mset | 保存键值函数 | (key, value, success[可选]) | 保存指定键值对,key:键,value:值,success:成功时返回的字符串,默认`success` | | mget | 获取值函数 | (key, failure[可选]) | 获取指定键对应的值,key:键,failure:指定键对应的值不存在时返回的字符串,默认`failure` | | mdelete | 删除键函数 | (key, success[可选]) | 删除指定键对应的值,key:键,success:删除成功时返回的字符串,默认`success` | > 函数表达式之间可以嵌套使用,因为函数表达式中间使用`,`作为参数分隔符,如果参数中也需要使用字符`,`,可以使用符号\`将表达式进行包裹。 例如`$valid`函数,如果返回参数是json格式,其中也包含`,`就可以这样使用:$valid(true, \`{"code": 200, "msg": "success"}\`, \`{"code": 400, "msg": "failure"}\`) 函数表达式示例: ``` # 保存用户信息示例 [ path=/user/{id} method=post body=%json($mset(user:$pathVariable(id), `$requestBody()`,`{"code": 200, "msg": "成功"}`)) ] # 获取用户信息示例 [ path=/user/{id} method=get body=%json($mget(user:$pathVariable(id), `{"code": 404, "msg": "用户信息不存在"}`)) ] # 以Json请求体形式进行用户登录示例 [ path=/user/login method=post body=%json($valid($jsonObject(`$requestBody()`, username) == user && $jsonObject(`$requestBody()`, password) == 123456, `{"code": 200, "msg": "登录成功", "token":"$uuidGenerator(false)"}`, `{"code": 400, "msg": "用户名或密码错误"}`)) ] # 以表单形式进行用户登录示例 [ path=/user/form_login method=post body=%json($valid($param(username) == user && $param(password) == $md5(123456), `{"code": 200, "msg": "登录成功", "token":"$uuidGenerator(false)"}`, `{"code": 400, "msg": "用户名或密码错误"}`)) ] ``` > 自定义函数可通过`NutApplication#getWebConfigure#registerCustomFunction`方法进行注册。也可以将自定义函数对象注册到`ApplicationContext`应用上下文中,将会自动进行注册。 # 开发 Nut 已完整实现自定义的`Request`、`Response`、`Cookie`、`Session`及`ServerContext`,可依赖Nut开发web服务。 ## Controller Nut 使用`Controller`来处理请求,可以自定义`Controller`来处理请求,`Controller`提供了`doGet`、`doPost`、`doPut`、`doDelete`、`doOptions`、`doTrace`来处理Http请求,如果没有对应请求的方法,可以重写`doRequest`方法,该方法是请求处理的主方法。 `Controller` 的方法均包含三个参数:`request`、`response`及`execution`,`request`是用来封装请对象信息,`response`是用来处理客户端的响应,`execution`种包含了系统中的扩展对象,例如:请求转发器(Forward)、绑定上下文(BindContext)、视图处理器(ViewHandler)等等。 ### Controller转发 使用`Controller`接口方法中的`execution`参数获取转发器(`Forward`),使用`forward`方法来从一个`Controller`跳转到另一个`Controller`。 ### 重定向 使用`Controller`接口方法中的`Response`接口参数的`sendRedirect`方法,可以向客户端发送302重定向请求。 ### Controller的注册 Nut 支持两种方式的Controller注册: 1. 实现`Controller`接口,调用`ControllerManager#registerController(Controller, String...)`来注册; 2. 支持Lambda表达式注册,`RequestHandler`为支持注册的函数式接口,调用`ControllerManager#registerController(RequestHandler, Method, String...)`来注册; 也可以使用`@Controller`注解进行注册,使用方式和Spring MVC一致,在调用`Nut#run`方法前通过`Nut#getWebConfigure#addBasePackage`方法来添加要扫描的包路径。 > 因未使用ASM方式来解析参数名,如果在编译阶段也未将方法的参数名编译进去,在使用`@RequestParam`注解时需要手动指定参数名,如不指定参数名获取到的参数为类似`arg0`,将无法正确注入参数。自jdk1.8开始就提供了保留参数编译的功能`-parameters`。 #### 支持的注解 ##### Controller注册 1. `@Controller`; 2. `@RestController`; ##### ControllerAdvice 1. `@ControllerAdvice`; 2. `@RestControllerAdvice`; 3. `@ExceptionHandler`; ##### 路径注册 1. `@RequestMapping`; 2. `@GetMapping`; 3. `@PostMapping`; 4. `@PutMapping`; 5. `@DeleteMapping`; ##### 参数绑定 1. `@CookieValue`; 2. `@RequestAttribute`; 3. `@SessionAttribute`; 4. `@ServerContextAttribute`; 5. `@PathVariable`; 6. `@RequestBody`; 7. `@RequestParam`; ##### 响应式 1. `@ResponseBody`; ##### IOC 1. `@Configuration`; 2. `@Bean`; 3. `@Component`; 4. `@Service`; 5. `@Repository`; 6. `@Autowired`; 7. `@Qualifier`; ##### 环境变量 1. `@Value`; 2. `@ConfigurationProperties` ##### AOP 1. `@Before`; 2. `@After`; 3. `@Throwing`; 4. `@Around`; 5. `@Compose`; 6. `@Aspect`; 7. `@Pointcut`; ##### 事务 1. `@Transactional`; ##### 异步 1. `@Async`; ##### Api 1. `@Api`; 2. `@ApiGroup`; 3. `@ApiIgnore`; 4. `@ApiModel`; 5. `@ApiModelProperty`; 6. `@ApiParam`; > 使用`@RestController`、`@RestControllerAdvice`、`@ResponseBody`注解时,需要调用`Nut#getWebConfigure#getPluginManager#registerPlugin`提前向Nut注册`ResponsivePlugin`插件,或引用支持的序列化框架依赖,通过自动探测器向Nut注册`ResponsivePlugin`插件。 ## 插件 Nut 提供了`ServerEventPlugin`、`ControllerPlugin`、`InterceptorPlugin`、`ExceptionHandlePlugin`四种类型的插件。 1. `ServerEventPlugin`用来处理服务启动与关闭时的事件监听; 2. `ControllerPlugin`用来处理查找controller时的扩展操作; 3. `InterceptorPlugin`用来在controller处理业务前后执行扩展操作,该插件有一个简短名称的接口`Interceptor`; 4. `ExceptionHandlePlugin`用来controller处理业务异常时进行异常扩展处理。 Nut还提供了两种注入`NutApplication`和`ApplicationContext`的插件基类: 1. `NutApplicationSupportBasePlugin`:该插件已注入`NutApplication`对象,可通过`getNutApplication()`方法调用获取; 2. `ApplicationContextSupportBasePlugin`:该插件已注入`ApplicationContext`对象,可通过`getApplicationContext()`方法调用获取。 ### Nut 内置插件 1. `ActuatorPlugin`:用来获取服务运行信息及服务远程关闭支持; 2. `AuthPlugin`:用来控制服务权限的插件; 3. `BasicAuthPlugin`:Basic认证插件; 4. `I18nPlugin`:用来支持国际化的插件; 5. `MemoryPlugin`:用来支持基于内存存储数据的插件,支持数据持久化(需要保证服务正常关闭); 6. `JdbcPlugin`:用来支持JDBC访问数据库的插件; 7. `ElasticSearchPlugin`:用来轻量级支持ElasticSearch访问的插件; 8. `ResponsivePlugin`:用来支持响应式输出的插件; 9. `DruidPlugin`:Druid连接池插件; 10. `XmlMyBatisPlugin`:基于XML配置的MyBatis插件; 11. `AnnotationMyBatisPlugin`:基于注解配置的MyBatis插件; 12. `MyBatisPlusPlugin`:基于MyBatis-Plus实现的数据库操作插件; 13. `MyBatisFlexPlugin`:基于MyBatisFlex实现的数据库操作插件; 14. `JedisPlugin`:Jedis实现的Redis插件; 15. `LettucePlugin`:Lettuce实现的Redis插件; 16. `AsyptPlugin`:用来加解密配置文件(例如:application.properties、application-dev.properties)中的敏感信息; 17. `OpenApi3Plugin`:根据项目中注册的基于注解实现的controller信息,生成对应的OpenApi3格式的json文件; 18. `ElasticSearchPlugin`:用来支持ElasticSearch的插件(基于RestApi的轻量级实现,不依赖ElasticSearch SDK); 19. `McpHttpServerPlugin`:用来支持Http Stream的Mcp服务; 20. `McpSseServerPlugin`:用来支持SSE Stream的Mcp服务; 21. `StdioSseServerPlugin`:用来支持标准输入/输出的Mcp服务; 22. `AwsS3Plugin`:AWS S3存储服务插件; 23. `R2S3Plugin`:Cloudflare R2存储服务插件。 ## 模板引擎 Nut已支持以下模板引擎: 1. Beetl; 2. Freemarker; 3. Thymeleaf; ## 自动探测 在引入指定依赖后,nut启动时会自动探测指定的类型是否存在以自动配置插件或模板引擎。 目前已支持以下自动探测类: 1. `ResponsivePluginAutoDetector`:响应式输出插件自动探测类,将以如下优先级进行探测: 1. `JackSon`; 2. `FastJson2`; 3. `FastJson`; 2. `ViewResolverAutoDetector`:视图解析器自动探测类,将以如下优先级进行探测: 1. `Thymeleaf`; 2. `FreeMarker`; 3. `Beetl`; > 如需要关闭指定的自动探测类,可调用`Nut#getWebConfigure#addIgnoreAutoDetectClass`方法指定要忽略的自动探测类。也可以通过`@NutApplication#ignoreAutoDetectors`方法进行忽略。 ## 启动 开发完毕后,通过`NutApplication#getWebConfigure#addBasePackage`方法或注解`@NutApplication#baseScanPackage`来添加要扫描的包路径,调用`Nut#run`方法启动web服务。 ### 支持特定方式启动服务 Nut支持以下服务启动类型(定义在`ServerType`枚举中): 1. `AUTO`(默认启动类型):判断classpath中是否存在指定的服务依赖,并按照`NETTY`、`JETTY`、`TOMCAT`、`SUN`的顺序自动配置; 2. ~~BIO:同步IO,**已废弃,不推荐使用**;~~ 3. ~~NIO:异步IO,**已废弃,不推荐使用**;~~ 4. `SUN`:以JDK提供的HTTP服务启动; 5. `NETTY`:以Netty方式启动服务; 6. `JETTY`:以Jetty方式启动服务,因nut以JDK1.8开发,所以目前最高支持的Jetty版本为9.x; 7. `TOMCAT`:以Tomcat方式启动服务,因`javax.servlet-api`变更包名为:`jakarta.servlet-api`,默认使用`javax.servlet-api`,所以已经使用`jakarta.servlet-api`的Tomcat版本可能无法运行,开发环境使用9.x版本进行; ### 指定服务启动类型的方式: 1. 调用带有`ServerType`参数的`Nut#run`方法进行启动; 2. 调用带有`NutConfiguration`参数的`Nut#run`方法进行启动,并使用`NutConfiguration#setServerType`方法指定服务启动类型; 3. 调用带有`Class mainClass`参数的`Nut#run`方法进行启动,在指定的启动主类上加`@NutApplication`注解,在注解中使用`@NutApplication#serverType`方法指定服务启动类型; ### 服务启动类型的maven依赖 Netty: ```xml io.netty netty-all 4.1.77.Final ``` Jetty: ```xml org.eclipse.jetty jetty-server 9.4.48.v20220622 ``` Tomcat: ```xml org.apache.tomcat.embed tomcat-embed-core 9.0.54 ```