2 Star 2 Fork 1

Yeskery / nut

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

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. 以插件形式支持MyBatis、MyBatis-Plus、MyBatisFlex;
  5. 以插件方式支持Redis(Jedis、Lettuce);
  6. 以插件方式支持Junit5单元测试(@NutBootTest注解);
  7. 已实现MVC注解(如@Controller@RestController@RequestParam@ResuestBody@ResponseBody@RequestMapping等注解);
  8. 已实现IOC注解(如@Component@Service@Repository@Autowired@Qualifier@Lazy@Primary等注解);
  9. 已实现条件装备注解(如@Conditional@ConditionalOnClass@ConditionalOnBean@ConditionalOnApplicationType等注解);
  10. 已实现AOP注解(如@Aspect@Pointcut@Before@After@Throwing@Around@Compose);
  11. 已实现环境注解(@ConfigurationProperties@Value);
  12. 已实现异步注解(@Async);
  13. 已实现事务注解(@Transactional);
  14. 已实现事件注解(@EventListener@TransactionalEventListener);
  15. 已实现WebSocket注解(@Websocket@PathParam@OnOpen@OnClose@OnMessage@OnError);
  16. 提供多个扩展点(如BeanPostProcessorBeanDefinitionPostProcessor等);
  17. 提供OpenApi3格式的文档功能(@ApiGroup@Api等注解);
  18. 可作为简单的静态文件服务器使用;
  19. 可开启脚本接口支持,通过编写配置文件快速搭建测试接口;
  20. 支持多种视图表达式(可自行扩展);
  21. 支持多种函数表达式(可自行扩展);
  22. 支持表达式嵌套使用;
  23. 支持脚本文件监听,脚本文件修改后自动刷新接口。

使用

可直接使用java -jar nut-1.x.x-SNAPSHOT.jar进行启动,也可以配置启动参数,目前如下参数可以配置:

参数名 默认值 说明
env 环境变量
port 8080 端口号
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

<dependency>
    <groupId>com.yeskery.nut</groupId>
    <artifactId>nut</artifactId>
    <version>1.0.14</version>
</dependency>

使用Nut-Netty

<dependency>
    <groupId>com.yeskery.nut</groupId>
    <artifactId>nut-netty</artifactId>
    <version>1.0.14</version>
    <type>pom</type>
</dependency>

使用Nut-Jetty

<dependency>
    <groupId>com.yeskery.nut</groupId>
    <artifactId>nut-jetty</artifactId>
    <version>1.0.14</version>
    <type>pom</type>
</dependency>

使用Nut-Tomcat

<dependency>
    <groupId>com.yeskery.nut</groupId>
    <artifactId>nut-tomcat</artifactId>
    <version>1.0.14</version>
    <type>pom</type>
</dependency>

静态文件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

脚本编写方式

脚本以[开始,以]结束,在中括号包裹的范围内需要配置pathmethodresponse_headerresponse_cookiebody五个参数,其中pathmethodbody是必填项目,response_headerresponse_cookie是非必填项目。

参数名 参数说明 备注
path 访问路径 如:/path 多个路径可以用逗号(,)拼接,如:/path1,/path2
method 访问方法 可选值为HTTP规范中支持的方法如:getpost等,如需要配置所有方法可设置为*
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(<h1>hello,world</h1>);],则可以提供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_headerresponse_cookiebody 中支持使用函数表达式,函数表达式以$开始,后接函数名称,后以()包裹的内容为函数参数,如:$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 已完整实现自定义的RequestResponseCookieSessionServerContext,可依赖Nut开发web服务。

Controller

Nut 使用Controller来处理请求,可以自定义Controller来处理请求,Controller提供了doGetdoPostdoPutdoDeletedoOptionsdoTrace来处理Http请求,如果没有对应请求的方法,可以重写doRequest方法,该方法是请求处理的主方法。

Controller 的方法均包含三个参数:requestresponseexecutionrequest是用来封装请对象信息,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 提供了ServerEventPluginControllerPluginInterceptorPluginExceptionHandlePlugin四种类型的插件。

  1. ServerEventPlugin用来处理服务启动与关闭时的事件监听;
  2. ControllerPlugin用来处理查找controller时的扩展操作;
  3. InterceptorPlugin用来在controller处理业务前后执行扩展操作,该插件有一个简短名称的接口Interceptor
  4. ExceptionHandlePlugin用来controller处理业务异常时进行异常扩展处理。

Nut还提供了两种注入NutApplicationApplicationContext的插件基类:

  1. NutApplicationSupportBasePlugin:该插件已注入NutApplication对象,可通过getNutApplication()方法调用获取;
  2. ApplicationContextSupportBasePlugin:该插件已注入ApplicationContext对象,可通过getApplicationContext()方法调用获取。

Nut 内置插件

  1. ActuatorPlugin:用来获取服务运行信息及服务远程关闭支持;
  2. AuthPlugin:用来控制服务权限的插件;
  3. LoginPlugin:用来限制用户登录后才能访问资源的插件;
  4. I18nPlugin:用来支持国际化的插件;
  5. MemoryPlugin:用来支持基于内存存储数据的插件,支持数据持久化(需要保证服务正常关闭);
  6. JdbcPlugin:用来支持JDBC访问数据库的插件;
  7. ResponsivePlugin:用来支持响应式输出的插件;
  8. DruidPlugin:Druid连接池插件;
  9. XmlMyBatisPlugin:基于XML配置的MyBatis插件;
  10. AnnotationMyBatisPlugin:基于注解配置的MyBatis插件;
  11. MyBatisPlusPlugin:基于MyBatis-Plus实现的数据库操作插件;
  12. MyBatisFlexPlugin:基于MyBatisFlex实现的数据库操作插件;
  13. JedisPlugin:Jedis实现的Redis插件;
  14. LettucePlugin:Lettuce实现的Redis插件;
  15. AsyptPlugin:用来加解密配置文件(例如:application.properties、application-dev.properties)中的敏感信息;
  16. OpenApi3Plugin:根据项目中注册的基于注解实现的controller信息,生成对应的OpenApi3格式的json文件。

模板引擎

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中是否存在指定的服务依赖,并按照NETTYJETTYTOMCATSUN的顺序自动配置;
  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:

<dependency>
   <groupId>io.netty</groupId>
   <artifactId>netty-all</artifactId>
   <version>4.1.77.Final</version>
</dependency>

Jetty:

<dependency>
   <groupId>org.eclipse.jetty</groupId>
   <artifactId>jetty-server</artifactId>
   <version>9.4.48.v20220622</version>
</dependency>

Tomcat:

<dependency>
   <groupId>org.apache.tomcat.embed</groupId>
   <artifactId>tomcat-embed-core</artifactId>
   <version>9.0.54</version>
</dependency>
MIT License Copyright (c) 2019 Yeskery Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

Java编写自带MVC框架的HTTP服务器,支持多种方式启动,支持HTTPS,并实现类类Spring MVC的部分注解,提供了IOC注解、AOP注解、事务注解、异步注解等,用来学习HTTP及Web框架相关知识,未强制使用第三方依赖,自定义Request、Response、Cookie、Session及ServerContext,基于JDK1.8开发。 展开 收起
Java
MIT
取消

发行版 (7)

全部

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/yeskery/nut.git
git@gitee.com:yeskery/nut.git
yeskery
nut
nut
master

搜索帮助