# 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
```