diff --git a/README.md b/README.md
index 8a644d483760664ec326e3e4cba5cab45cc7fc4d..f6d8e45b15a92dab0bf7f3ed3a0983841985c834 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
io.jboot
jboot
- 3.1.4
+ 3.1.5
```
@@ -53,7 +53,7 @@ public class HelloworldController extends JbootController {
- [事件机制](./doc/docs/event.md)
- [SPI扩展机制](./doc/docs/spi.md)
- [代码生成器](./doc/docs/codegen.md)
-- [项目构建](./doc/docs/build.md)
+- [项目打包](./doc/docs/build.md)
- [项目部署](./doc/docs/deploy.md)
- [Jboot与Docker](./doc/docs/docker.md)
- [1.x 升级到 2.x 教程](./doc/docs/upgrade.md)
diff --git a/changes.txt b/changes.txt
index 37e45638931d3e30af18d757fdc41b50d4b08238..577f3c8c1c4b11b7c49aa75b487a0dcc92c6bfba 100644
--- a/changes.txt
+++ b/changes.txt
@@ -1,3 +1,18 @@
+jboot v3.1.5:
+新增:新增 Motan RPC 的 export 和 host 的相关配置以及test代码
+新增:JbootJson 支持驼峰式 JsonKey 输出,感谢Gitee的 @herowjun
+新增:新增 Controller 对返回值自动渲染的功能
+新增:JbootRPCConfig 新增默认 version 和 group 配置的支持
+优化:ClassScanner 添加无需扫码的 jar 排除,速度更快
+修复:ClassScanner 在 Windows 平台下可能存在重复扫码而拖慢启动速度的问题
+修复:门户网关 GatewayHttpProxy 在 POST 时的某些情况下会出现无法正确代理的问题
+文档:完善 RPC 配置的相关文档
+文档:完善 Gateway 配置的相关文档
+文档:添加 fatjar 打包的相关文档
+文档:完善 fatjar 部署运行的相关文档
+
+
+
jboot v3.1.4:
优化:重构 ClassScanner ,提高在 fatjar 模式的扫描性能
优化:重构 ConfigManager ,以便更好的支持 fatjar 模式下的配置文件读取
diff --git a/doc/docs/build.md b/doc/docs/build.md
index 840323c013bf6e3249b9a2cceeadee3311c05377..afd0cecbf74b75d0a67163f4c3912107373ba714 100644
--- a/doc/docs/build.md
+++ b/doc/docs/build.md
@@ -1,11 +1,12 @@
-# 项目构建
+# 项目打包
## 目录
-- 单模块 maven 项目构建
-- 多模块 maven 项目构建
+- 单模块 maven 项目打包
+- 多模块 maven 项目打包
+- fatjar 打包(全部打包到一个jar里)
-## 单模块 maven 项目构建
+## 单模块 maven 项目打包
在单一模块的maven项目开发中,我们通常在 `src/main/resources` 编写我们的配置文件,因此,在 maven 构建的时候,我们需要添加如下配置:
@@ -175,7 +176,7 @@ fi
复制该文件夹到服务器,然后执行里面的 `jboot.sh start` 命令即可上线。
-## 多模块 maven 项目构建
+## 多模块 maven 项目打包
多模块项目在以上配置的基础上,添加 `maven-resources-plugin` maven 插件,用于拷贝其他maven模块的资源文件和html等内容到此运行模块。
@@ -210,4 +211,102 @@ maven 配置如下:
```
-这部分可以参考 jpress 项目,网址:https://gitee.com/fuhai/jpress/blob/v2.0/starter/pom.xml
\ No newline at end of file
+这部分可以参考 jpress 项目,网址:https://gitee.com/fuhai/jpress/blob/v2.0/starter/pom.xml
+
+## fatjar 打包(全部打包到一个jar里)
+
+fatjar 打包指的是,把所有资源(html、css、js)以及项目依赖全部打包到一个 jar 包里,这样我们可以通过
+命令 `java -jar xxx.jar` 启动,更加方便部署,特别是方便在微服务下的多模块部署。
+
+fatjar 打包第一步,在 pom.xml 添加如下配置
+
+```xml
+
+
+
+ src/main/resources
+
+ **/*.*
+
+ false
+
+
+
+ src/main/webapp
+
+ **/*.*
+
+ false
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+ UTF-8
+ -parameters
+
+
+
+
+
+ maven-resources-plugin
+
+
+ copy-resources
+ validate
+
+ copy-resources
+
+
+ ${basedir}/target/classes/webapp
+
+
+ ${basedir}/src/main/webapp
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.1.0
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+ io.jboot.app.JbootApplication
+
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+```
+
+第二步:通过 Maven 打包
+
+执行命令 `mvn clean package` 进行打包,在 pom.xml 对应的模块下会生成一个 xxx-with-dependencies.jar 的 jar 包,复制该 jar
+到服务器上,执行 `java -jar xxx-with-dependencies.jar` 即可启动项目。
\ No newline at end of file
diff --git a/doc/docs/deploy.md b/doc/docs/deploy.md
index 6486679fcdfb59d1f45040b72a0ac510c9fd8daf..21a2448c8f2f1b615ed75cbee6cf636e280c8be1 100644
--- a/doc/docs/deploy.md
+++ b/doc/docs/deploy.md
@@ -2,15 +2,101 @@
## 目录
- 描述
+- 通过 脚本 运行
- 通过 Jar 运行
- 通过 Tomcat 运行
## 描述
+本文档提供了 3 种部署方式,对应 Jboot 里的 3 种[打包方式](./build.md)。
+
+## 通过 脚本 运行
+
+在 [打包方式](./build.md) 文档中,我们可以把项目打包成一个 .zip 的压缩包项目,里面带有 jboot.sh (和 jboot.bat) 执行脚本,
+只需要我们解压 .zip 压缩文件,通过如下命令就可以对 jboot 项目进行启动和停止。
+
+```shell script
+# 启动
+./jboot.sh start
+
+# 停止
+./jboot.sh stop
+
+# 重启
+./jboot.sh restart
+```
+
+在 Windows 系统中,通过如下命令执行
+
+```shell script
+# 启动
+jboot.bat start
+
+# 停止
+jboot.bat stop
+
+# 重启
+jboot.bat restart
+```
## 通过 Jar 运行
-Jboot 通过依赖 `JFinal-Undertow` 内置了 Undertow 服务器,可以直接通过 Jar 的方式进行运行,这部分直接参考文档:https://www.jfinal.com/doc/1-3 即可。
+在 [打包方式](./build.md) 文档中,我们可以把所有的资源文件(html、css、js、配置文件 等)以及项目的所有依赖打包到一个 jar 包
+里去,打包成功后,可以通过如下命令运行。
+
+启动(前台启动,命令窗口不能关闭)
+```shell script
+java -jar xxx.jar
+```
+> 当前ssh窗口(命令窗口)被锁定,可按 `CTRL + C` 打断程序运行,或直接关闭窗口,程序退出。
+
+启动(后台启动,命令窗口不能关闭)
+```shell script
+java -jar xxx.jar &
+```
+> & 代表在后台运行。当前ssh窗口不被锁定,但是当窗口关闭时,程序中止运行。
+
+
+启动(后台启动)
+```shell script
+nohup java -jar xxx.jar &
+```
+>nohup 意思是不挂断运行命令,当账户退出或终端关闭时,程序仍然运行,当用 nohup 命令执行作业时,缺省情况下该作业的所有输出被重定向到nohup.out的文件中,除非另外指定了输出文件。
+
+启动(后台启动)
+```shell script
+nohup java -jar xxx.jar>temp.txt &
+```
+>command >out.file 是将 command 的输出重定向到 out.file 文件,即输出内容不打印到屏幕上,而是输出到 out.file 文件中。
+>以上命令,就是把 java 启动的输出,输入到 temp.txt 文件里,而不是在屏幕上。
+
+
+另外:可以通过如下命令实时查看日志:
+
+```shell script
+tail -f temp.text
+```
+
+可通过jobs命令查看后台运行任务
+
+```shell script
+jobs
+```
+
+jobs 命令就会列出所有后台执行的作业,并且每个作业前面都有个编号。如果想将某个作业调回前台控制,只需要 fg + 编号即可。
+
+```shell script
+fg 33
+```
+
+查看程序端口的进程的pid
+
+```shell script
+netstat -nlp | grep:8080
+```
+
+
+
## 通过 Tomcat 运行
diff --git a/doc/docs/gateway.md b/doc/docs/gateway.md
index d5192ec0cef08941fe64623c23f6a1d840141eee..331836e26e96d786ea49a6482e5c7da503981686 100644
--- a/doc/docs/gateway.md
+++ b/doc/docs/gateway.md
@@ -6,6 +6,7 @@
- path路由
- host路由
- query路由
+- 多个 Gateway 配置
- 其他
@@ -187,6 +188,74 @@ jboot.gateway.queryContains = aaa
以上配置中,如果用户访问 `www.xxx.com/controller?aaa=bbb` 会自动路由到 `http://youdomain:8080/controller?aaa=bbb` ,或者用户访问 `www.xxx.com/controller?aaa=ccc` 也会路由到 `http://youdomain:8080/controller?aaa=ccc`,因为 query 都包含了 `aaa=**` 的请求,但是如果用户访问 `www.xxx.com/controller?other=aaa`不会路由。
+
+
+## 多个 Gateway 配置
+
+```
+jboot.gateway.aaa.name = name
+jboot.gateway.aaa.uri = http://youdomain:8080
+jboot.gateway.aaa.enable = true
+jboot.gateway.aaa.sentinelEnable = false
+jboot.gateway.aaa.sentinelBlockPage = /block
+jboot.gateway.aaa.proxyReadTimeout = 10000
+jboot.gateway.aaa.proxyConnectTimeout = 5000
+jboot.gateway.aaa.proxyContentType = text/html;charset=utf-8
+jboot.gateway.aaa.interceptors = com.xxx.Interceptor1,com.xxx.Interceptor2
+jboot.gateway.aaa.pathEquals = /path
+jboot.gateway.aaa.pathContains = /path
+jboot.gateway.aaa.pathStartsWith = /path
+jboot.gateway.aaa.pathEndswith = /path
+jboot.gateway.aaa.hostEquals = xxx.com
+jboot.gateway.aaa.hostContains = xxx.com
+jboot.gateway.aaa.hostStartsWith = xxx.com
+jboot.gateway.aaa.hostEndswith = xxx.com
+jboot.gateway.aaa.queryEquals = aa:bb,cc:dd
+jboot.gateway.aaa.queryContains = aa,bb
+
+
+jboot.gateway.bbb.name = name
+jboot.gateway.bbb.uri = http://youdomain:8080
+jboot.gateway.bbb.enable = true
+jboot.gateway.bbb.sentinelEnable = false
+jboot.gateway.bbb.sentinelBlockPage = /block
+jboot.gateway.bbb.proxyReadTimeout = 10000
+jboot.gateway.bbb.proxyConnectTimeout = 5000
+jboot.gateway.bbb.proxyContentType = text/html;charset=utf-8
+jboot.gateway.bbb.interceptors = com.xxx.Interceptor1,com.xxx.Interceptor2
+jboot.gateway.bbb.pathEquals = /path
+jboot.gateway.bbb.pathContains = /path
+jboot.gateway.bbb.pathStartsWith = /path
+jboot.gateway.bbb.pathEndswith = /path
+jboot.gateway.bbb.hostEquals = xxx.com
+jboot.gateway.bbb.hostContains = xxx.com
+jboot.gateway.bbb.hostStartsWith = xxx.com
+jboot.gateway.bbb.hostEndswith = xxx.com
+jboot.gateway.bbb.queryEquals = aa:bb,cc:dd
+jboot.gateway.bbb.queryContains = aa,bb
+
+
+jboot.gateway.xxx.name = name
+jboot.gateway.xxx.uri = http://youdomain:8080
+jboot.gateway.xxx.enable = true
+jboot.gateway.xxx.sentinelEnable = false
+jboot.gateway.xxx.sentinelBlockPage = /block
+jboot.gateway.xxx.proxyReadTimeout = 10000
+jboot.gateway.xxx.proxyConnectTimeout = 5000
+jboot.gateway.xxx.proxyContentType = text/html;charset=utf-8
+jboot.gateway.xxx.interceptors = com.xxx.Interceptor1,com.xxx.Interceptor2
+jboot.gateway.xxx.pathEquals = /path
+jboot.gateway.xxx.pathContains = /path
+jboot.gateway.xxx.pathStartsWith = /path
+jboot.gateway.xxx.pathEndswith = /path
+jboot.gateway.xxx.hostEquals = xxx.com
+jboot.gateway.xxx.hostContains = xxx.com
+jboot.gateway.xxx.hostStartsWith = xxx.com
+jboot.gateway.xxx.hostEndswith = xxx.com
+jboot.gateway.xxx.queryEquals = aa:bb,cc:dd
+jboot.gateway.xxx.queryContains = aa,bb
+```
+
## 其他
当配置中,如果一个内容存在多个值的时候,需要用英文逗号(,)隔开。
@@ -202,4 +271,4 @@ jboot.gateway.pathContains = /user,/article
当 path 中,只要存在 `/user` 或者 存在 `/article` 都会匹配到该路由,比如 `www.xxx.com/user/xxx` 或者 `www.xxx.com/article/xxx` 都会匹配到。
-其他同理。
+其他同理。
\ No newline at end of file
diff --git a/doc/docs/install.md b/doc/docs/install.md
index aa964cedb199954c22a33a57c92ca63364bc2693..04152d49de476d4f0e878b15064ad66be118135e 100644
--- a/doc/docs/install.md
+++ b/doc/docs/install.md
@@ -9,7 +9,7 @@
io.jboot
jboot
- 3.1.4
+ 3.1.5
```
diff --git a/doc/docs/quickstart.md b/doc/docs/quickstart.md
index 82fb65b7273d61cc3dde6afbda0eec817503d35b..603ec0456dc2201feff2e04fd689d90cf9420b12 100644
--- a/doc/docs/quickstart.md
+++ b/doc/docs/quickstart.md
@@ -28,7 +28,7 @@
io.jboot
jboot
- 3.1.4
+ 3.1.5
```
diff --git a/doc/docs/rpc.md b/doc/docs/rpc.md
index 1d0f327585e67e01271dc2d5aa173978d13e0b4b..677456d1751032d4cac975395a70ed3460d0eb4d 100644
--- a/doc/docs/rpc.md
+++ b/doc/docs/rpc.md
@@ -79,6 +79,10 @@ jboot.rpc.type = dubbo
jboot.rpc.urls = com.yourdomain.AAAService:127.0.0.1:8080,com.yourdomain.XXXService:127.0.0.1:8080
jboot.rpc.providers = com.yourdomain.AAAService:providerName,com.yourdomain.XXXService:providerName
jboot.rpc.consumers = com.yourdomain.AAAService:consumerName,com.yourdomain.XXXService:consumerName
+jboot.rpc.defaultVersion = 1.0.0
+jboot.rpc.versions = com.yourdomain.AAAService:1.0.0,com.yourdomain.XXXService:1.0.1
+jboot.rpc.defaultGroup =
+jboot.rpc.groups = com.yourdomain.AAAService:group1,com.yourdomain.XXXService:group2
jboot.rpc.autoExportEnable = true
```
@@ -86,6 +90,10 @@ jboot.rpc.autoExportEnable = true
- jboot.rpc.urls : 一般不用配置,只有直连模式下才会去配置,此处是配置 Service接口和URL地址的映射关系。
- jboot.rpc.providers : 配置 Service 和 Provider 的映射关系( Motan下配置的是 Service 和 BasicService 的映射关系)。
- jboot.rpc.consumers : 配置 Reference 和 consumer 的映射关系( Motan下配置的是 Referer 和 BaseReferer 的映射关系)。
+- jboot.rpc.defaultVersion : 当service不配置版本时,默认的版本号,默认值为 1.0.0
+- jboot.rpc.versions : 每个服务对应的版本号
+- jboot.rpc.defaultGroup : 当服务不配置 group 时,默认的 gourp
+- jboot.rpc.groups : 每个服务对应的 group
- jboot.rpc.autoExportEnable : 当 Jboot 启动的时候,是否自动暴露 @RPCBean 注解的接口。
diff --git a/pom.xml b/pom.xml
index 176a2ff2feacc07071c16a20960e7f3381525b5b..b72cb4c1b0117cdf189b024c1186f0d17269bfb0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
io.jboot
jboot
- 3.1.5-SNAPSHOT
+ 3.1.6-SNAPSHOT
jar
jboot
diff --git a/src/main/java/io/jboot/JbootConsts.java b/src/main/java/io/jboot/JbootConsts.java
index 28a9284b5211674d880b47b757dd979176e4de03..7d120266cd24bcfd4fc7235b9c75e5249130cdbf 100644
--- a/src/main/java/io/jboot/JbootConsts.java
+++ b/src/main/java/io/jboot/JbootConsts.java
@@ -22,7 +22,7 @@ package io.jboot;
*/
public class JbootConsts {
- public static String VERSION = "3.1.4";
+ public static String VERSION = "3.1.5";
public static final String ATTR_REQUEST = "REQUEST";
diff --git a/src/main/java/io/jboot/components/gateway/GatewayHttpProxy.java b/src/main/java/io/jboot/components/gateway/GatewayHttpProxy.java
index 5c4c53f25af63154a3fcd7f29dbfaafa32b8dd51..eabd9f87849b1c0bf476f00b82d9cc6f168b1ea0 100644
--- a/src/main/java/io/jboot/components/gateway/GatewayHttpProxy.java
+++ b/src/main/java/io/jboot/components/gateway/GatewayHttpProxy.java
@@ -81,12 +81,17 @@ public class GatewayHttpProxy {
*/
configConnection(conn, req);
- conn.connect();
- /**
- * 复制 post 请求内容到目标服务器
- */
- copyRequestStreamToConnection(req, conn);
+ // get 请求
+ if ("get".equalsIgnoreCase(req.getMethod())) {
+ conn.connect();
+ }
+ // post 请求
+ else {
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ copyRequestStreamToConnection(req, conn);
+ }
/**
@@ -95,7 +100,7 @@ public class GatewayHttpProxy {
configResponse(resp, conn);
/**
- * 复制目标流到 Response
+ * 复制目标相应流到 Response
*/
copyStreamToResponse(conn, resp);
@@ -111,19 +116,12 @@ public class GatewayHttpProxy {
OutputStream outStream = null;
InputStream inStream = null;
try {
-
- // 如果不是 post 请求,不需要复制
- if ("get".equalsIgnoreCase(req.getMethod())) {
- return;
- }
-
- conn.setDoOutput(true);
outStream = conn.getOutputStream();
inStream = req.getInputStream();
- int n;
+ int len;
byte[] buffer = new byte[1024];
- while (-1 != (n = inStream.read(buffer))) {
- outStream.write(buffer, 0, n);
+ while ((len = inStream.read(buffer)) != -1) {
+ outStream.write(buffer, 0, len);
}
} finally {
@@ -149,7 +147,6 @@ public class GatewayHttpProxy {
} finally {
quetlyClose(inStream, reader);
}
-
}
@@ -174,15 +171,22 @@ public class GatewayHttpProxy {
Set headerNames = headerFields.keySet();
for (String headerName : headerNames) {
//需要排除 Content-Encoding,因为 Server 可能已经使用 gzip 压缩,但是此代理已经对 gzip 内容进行解压了
- if (StrUtil.isNotBlank(headerName) && !"Content-Encoding".equalsIgnoreCase(headerName)) {
- resp.setHeader(headerName, conn.getHeaderField(headerName));
+ //需要排除 Content-Type,因为会可能会进行多次设置
+ if (StrUtil.isBlank(headerName)
+ || "Content-Encoding".equalsIgnoreCase(headerName)
+ || "Content-Type".equalsIgnoreCase(headerName)) {
+ continue;
+ } else {
+ String headerFieldValue = conn.getHeaderField(headerName);
+ if (StrUtil.isNotBlank(headerFieldValue)) {
+ resp.setHeader(headerName, headerFieldValue);
+ }
}
}
}
}
private static InputStream getInputStream(HttpURLConnection conn) throws IOException {
-
InputStream stream = conn.getResponseCode() >= 400
? conn.getErrorStream()
: conn.getInputStream();
@@ -192,7 +196,6 @@ public class GatewayHttpProxy {
} else {
return stream;
}
-
}
@@ -200,16 +203,19 @@ public class GatewayHttpProxy {
conn.setReadTimeout(readTimeOut);
conn.setConnectTimeout(connectTimeOut);
- conn.setInstanceFollowRedirects(true);
+ conn.setInstanceFollowRedirects(false);
conn.setUseCaches(false);
-// conn.setDefaultUseCaches();
conn.setRequestMethod(req.getMethod());
+
Enumeration headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
if (StrUtil.isNotBlank(headerName)) {
- conn.setRequestProperty(headerName, req.getHeader(headerName));
+ String headerFieldValue = req.getHeader(headerName);
+ if (StrUtil.isNotBlank(headerFieldValue)) {
+ conn.setRequestProperty(headerName, headerFieldValue);
+ }
}
}
}
diff --git a/src/main/java/io/jboot/components/gateway/GatewaySentinelProcesser.java b/src/main/java/io/jboot/components/gateway/GatewaySentinelProcesser.java
index 7e7de2b8cc4b2fcbf62036e94babac10e5f172fb..5aefb152b55a1f3fef872d69483703846c5041c3 100644
--- a/src/main/java/io/jboot/components/gateway/GatewaySentinelProcesser.java
+++ b/src/main/java/io/jboot/components/gateway/GatewaySentinelProcesser.java
@@ -37,7 +37,7 @@ public class GatewaySentinelProcesser {
Entry entry = null;
String resourceName = GatewayUtil.buildResource(req);
try {
- entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
+ entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY, EntryType.IN);
runnable.run();
} catch (BlockException ex) {
processBlocked(config, req, resp);
diff --git a/src/main/java/io/jboot/components/gateway/JbootGatewayConfig.java b/src/main/java/io/jboot/components/gateway/JbootGatewayConfig.java
index 048dfc7cac019e586609d05a208e692fb756db43..6b89656c43faea9fb90d2cab31d933c4de0d1b97 100644
--- a/src/main/java/io/jboot/components/gateway/JbootGatewayConfig.java
+++ b/src/main/java/io/jboot/components/gateway/JbootGatewayConfig.java
@@ -15,6 +15,7 @@
*/
package io.jboot.components.gateway;
+import io.jboot.exception.JbootIllegalConfigException;
import io.jboot.utils.ClassUtil;
import io.jboot.utils.StrUtil;
@@ -233,6 +234,7 @@ public class JbootGatewayConfig implements Serializable {
private GatewayInterceptor[] inters;
+
public GatewayInterceptor[] getInters() {
if (interceptors == null || interceptors.length == 0) {
return null;
@@ -255,8 +257,28 @@ public class JbootGatewayConfig implements Serializable {
}
+ private Boolean configOk = null;
+
public boolean isConfigOk() {
- return StrUtil.isNotBlank(uri);
+ if (configOk != null) {
+ return configOk;
+ }
+ synchronized (this) {
+ if (configOk == null) {
+ configOk = StrUtil.isNotBlank(uri);
+ if (configOk) {
+ ensureUriPatterCorrect();
+ }
+ }
+ }
+ return configOk;
+ }
+
+ private void ensureUriPatterCorrect() {
+ if (!uri.toLowerCase().startsWith("http://")
+ && !uri.toLowerCase().startsWith("https://")) {
+ throw new JbootIllegalConfigException("gateway uri must start with http:// or https://");
+ }
}
diff --git a/src/main/java/io/jboot/components/restful/DefaultRestfulErrorRender.java b/src/main/java/io/jboot/components/restful/DefaultRestfulErrorRender.java
deleted file mode 100644
index 1ba7e278ce4abd44c979a88f3ed9db64c20d3604..0000000000000000000000000000000000000000
--- a/src/main/java/io/jboot/components/restful/DefaultRestfulErrorRender.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package io.jboot.components.restful;
-
-import com.jfinal.core.ActionException;
-import com.jfinal.log.Log;
-import com.jfinal.render.Render;
-import com.jfinal.render.RenderException;
-import com.jfinal.render.RenderManager;
-import io.jboot.components.restful.exception.ParameterNullErrorException;
-import io.jboot.components.restful.exception.ParameterParseErrorException;
-import io.jboot.components.restful.exception.RequestMethodErrorException;
-import io.jboot.web.handler.JbootActionHandler;
-
-import java.io.Serializable;
-
-/**
- * 默认的restful错误响应处理器
- */
-public class DefaultRestfulErrorRender extends RestfulErrorRender {
-
- private static final Log log = Log.getLog(JbootActionHandler.class);
-
- public static class Error implements Serializable {
- private String errorClass;
- private int code;
- private String message;
-
- public Error(String errorClass, int code, String message) {
- this.errorClass = errorClass;
- this.code = code;
- this.message = message;
- }
-
- public String getErrorClass() {
- return errorClass;
- }
-
- public Error setErrorClass(String errorClass) {
- this.errorClass = errorClass;
- return this;
- }
-
- public int getCode() {
- return code;
- }
-
- public Error setCode(int code) {
- this.code = code;
- return this;
- }
-
- public String getMessage() {
- return message;
- }
-
- public Error setMessage(String message) {
- this.message = message;
- return this;
- }
- }
-
- public void render() {
- log.error("The restful handler intercepted the error", super.getError());
- Error error = null;
- if(super.getError() instanceof ParameterNullErrorException
- || super.getError() instanceof ParameterParseErrorException){
- //400
- error = new Error(super.getError().getClass().getName(),
- HttpStatus.BAD_REQUEST.value(), super.getError().getMessage());
- } else if(super.getError() instanceof RequestMethodErrorException){
- error = new Error(super.getError().getClass().getName(),
- HttpStatus.METHOD_NOT_ALLOWED.value(), super.getError().getMessage());
- } else if(super.getError() instanceof ActionException){
- //解析错误代码
- ActionException actionException = (ActionException)super.getError();
- int errorCode = actionException.getErrorCode();
- String msg = "";
- if (errorCode == 404) {
- msg = HttpStatus.NOT_FOUND.getReasonPhrase();
- } else if (errorCode == 400) {
- msg = HttpStatus.BAD_REQUEST.getReasonPhrase();
- } else if (errorCode == 401) {
- msg = HttpStatus.UNAUTHORIZED.getReasonPhrase();
- } else if (errorCode == 403) {
- msg = HttpStatus.FORBIDDEN.getReasonPhrase();
- } else if(errorCode == 405){
- msg = HttpStatus.METHOD_NOT_ALLOWED.getReasonPhrase();
- } else {
- msg = super.getError().getMessage();
- }
- error = new Error(super.getError().getClass().getName(),
- errorCode, msg);
- } else if(super.getError() instanceof RenderException){
- //500
- error = new Error(super.getError().getClass().getName(),
- HttpStatus.INTERNAL_SERVER_ERROR.value(), super.getError().getMessage());
- } else {
- //500
- error = new Error(super.getError().getClass().getName(),
- HttpStatus.INTERNAL_SERVER_ERROR.value(), super.getError().getMessage());
- }
- Render jsonRender = RenderManager.me().getRenderFactory().getJsonRender(error);
- jsonRender.setContext(super.request, super.response, super.getAction() == null? "" : super.getAction().getViewPath());
- super.response.setStatus(error.getCode());
- jsonRender.render();
- }
-
-
-
-}
diff --git a/src/main/java/io/jboot/components/restful/JbootRestfulManager.java b/src/main/java/io/jboot/components/restful/JbootRestfulManager.java
index 4a2f1ed57760e861e581015c08d7bf74e8bd9b14..e850ec54c3134c640cdceaf14f7b31d6fc729f6e 100644
--- a/src/main/java/io/jboot/components/restful/JbootRestfulManager.java
+++ b/src/main/java/io/jboot/components/restful/JbootRestfulManager.java
@@ -3,13 +3,14 @@ package io.jboot.components.restful;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.InterceptorManager;
import com.jfinal.config.Routes;
+import com.jfinal.core.ActionException;
import com.jfinal.core.Controller;
import com.jfinal.core.NotAction;
+import com.jfinal.render.RenderManager;
import io.jboot.components.restful.annotation.DeleteMapping;
import io.jboot.components.restful.annotation.GetMapping;
import io.jboot.components.restful.annotation.PostMapping;
import io.jboot.components.restful.annotation.PutMapping;
-import io.jboot.components.restful.exception.RequestMethodErrorException;
import io.jboot.utils.StrUtil;
import io.jboot.web.controller.annotation.RequestMapping;
@@ -22,6 +23,7 @@ import java.util.Map;
public class JbootRestfulManager {
public static class Config {
+
private boolean mappingSupperClass;
private String baseViewPath;
private Interceptor[] routeInterceptors;
@@ -81,7 +83,7 @@ public class JbootRestfulManager {
protected static final String SLASH = "/";
- private RestfulErrorRender restfulErrorRender = new DefaultRestfulErrorRender();
+ private RenderManager renderManager = RenderManager.me();
public static JbootRestfulManager me() {
return me;
@@ -177,10 +179,8 @@ public class JbootRestfulManager {
}
}
RestfulAction action = new RestfulAction(baseRequestMapping, actionKey, controllerClass,
- method, method.getName(), actionInters, route.getFinalViewPath(config.getBaseViewPath()));
+ method, method.getName(), actionInters, route.getFinalViewPath(config.getBaseViewPath()), requestMethod);
String key = requestMethod + ":" + actionKey;
-
-// RestfulAction restfulAction = new RestfulAction(action, actionKey, requestMethod);
if (restfulActions.put(key, action) != null) {
//已经存在指定的key
throw new RuntimeException(buildMsg(actionKey, controllerClass, method));
@@ -205,34 +205,25 @@ public class JbootRestfulManager {
//先直接获取
RestfulAction restfulAction = restfulActions.get(actionKey);
if (restfulAction == null) {
- //路径判断
- String[] paths = actionKey.split(":")[1].replace(requestMethod, "").split(SLASH);
- for (String _actionKey : restfulActions.keySet()) {
- String _requestMethod = _actionKey.split(":")[0];
- String _target = _actionKey.split(":")[1];
- System.out.println("---------> target:"+target+",_target:"+_target+",_requestMethod:"+_requestMethod+",requestMethod:" + requestMethod);
- if( target.equals(_target) && !_requestMethod.equals(requestMethod) ){
+ String[] paths = target.split(SLASH);
+ for(Map.Entry entry : restfulActions.entrySet()){
+ String _requestMethod = entry.getValue().getRequestMethod();
+ String _target = entry.getValue().getActionKey();
+ if (target.equals(_target) && !_requestMethod.equals(requestMethod)) {
//请求方法不正确
- throw new RequestMethodErrorException(_actionKey, _requestMethod, target, requestMethod);
+ throw new ActionException(HttpStatus.METHOD_NOT_ALLOWED.value(),
+ renderManager.getRenderFactory().getErrorRender(HttpStatus.METHOD_NOT_ALLOWED.value()),
+ "'" + target + "' is specified as a '" + _requestMethod + "' request. '" + requestMethod + "' requests are not supported");
}
- String[] _paths = _actionKey.split(":")[1].replace(requestMethod, "").split(SLASH);
- if (_actionKey.startsWith(requestMethod) &&
- _actionKey.contains("{") && _actionKey.contains("}")
+ String[] _paths = entry.getValue().getActionKey().split(SLASH);
+ if (entry.getValue().getActionKey().startsWith(requestMethod) &&
+ entry.getValue().getActionKey().contains("{") && entry.getValue().getActionKey().contains("}")
&& paths.length == _paths.length && RestfulUtils.comparePaths(_paths, paths)) {
- restfulAction = restfulActions.get(_actionKey);
+ restfulAction = entry.getValue();
break;
}
}
}
return restfulAction;
}
-
- public RestfulErrorRender getRestfulErrorRender() {
- return restfulErrorRender;
- }
-
- public JbootRestfulManager setRestfulErrorRender(RestfulErrorRender restfulErrorRender) {
- this.restfulErrorRender = restfulErrorRender;
- return this;
- }
}
diff --git a/src/main/java/io/jboot/components/restful/ResponseEntity.java b/src/main/java/io/jboot/components/restful/ResponseEntity.java
index 90aad64467c540f9f4a3c0f682e5ad41c8e432ed..bae89f315534fa76f33ac8b8f344df76abd4d84c 100644
--- a/src/main/java/io/jboot/components/restful/ResponseEntity.java
+++ b/src/main/java/io/jboot/components/restful/ResponseEntity.java
@@ -3,10 +3,10 @@ package io.jboot.components.restful;
import java.util.HashMap;
import java.util.Map;
-public class ResponseEntity {
+public class ResponseEntity {
//响应的数据
- private T data;
+ private Object data;
//自定义响应头部信息
private Map headers = new HashMap<>();
@@ -14,21 +14,21 @@ public class ResponseEntity {
//默认http状态
private HttpStatus httpStatus = HttpStatus.OK;
- public T getData() {
+ public Object getData() {
return data;
}
- public ResponseEntity setData(T data) {
+ public ResponseEntity setData(Object data) {
this.data = data;
return this;
}
- public ResponseEntity addHeaders(Map headers) {
+ public ResponseEntity addHeaders(Map headers) {
this.headers.putAll(headers);
return this;
}
- public ResponseEntity addHeader(String key, String value) {
+ public ResponseEntity addHeader(String key, String value) {
this.headers.put(key, value);
return this;
}
@@ -37,7 +37,7 @@ public class ResponseEntity {
return headers;
}
- public ResponseEntity setHttpStatus(HttpStatus httpStatus) {
+ public ResponseEntity setHttpStatus(HttpStatus httpStatus) {
this.httpStatus = httpStatus;
return this;
}
@@ -49,7 +49,7 @@ public class ResponseEntity {
public ResponseEntity() {
}
- public ResponseEntity(T data, Map headers, HttpStatus httpStatus) {
+ public ResponseEntity(Object data, Map headers, HttpStatus httpStatus) {
this.data = data;
this.headers = headers;
this.httpStatus = httpStatus;
@@ -60,7 +60,7 @@ public class ResponseEntity {
this.httpStatus = httpStatus;
}
- public ResponseEntity(T data) {
+ public ResponseEntity(Object data) {
this.data = data;
}
diff --git a/src/main/java/io/jboot/components/restful/RestfulAction.java b/src/main/java/io/jboot/components/restful/RestfulAction.java
index 7c2ccd4e6576b621142bf1c93797035391b98a64..1178f8c8f4903c5d817cc6cb71256ea320c5c997 100644
--- a/src/main/java/io/jboot/components/restful/RestfulAction.java
+++ b/src/main/java/io/jboot/components/restful/RestfulAction.java
@@ -8,7 +8,17 @@ import java.lang.reflect.Method;
public class RestfulAction extends Action {
- public RestfulAction(String controllerKey, String actionKey, Class extends Controller> controllerClass, Method method, String methodName, Interceptor[] interceptors, String viewPath) {
+ private String requestMethod;
+
+ public String getRequestMethod() {
+ return requestMethod;
+ }
+
+ public RestfulAction(String controllerKey, String actionKey, Class extends Controller> controllerClass,
+ Method method, String methodName, Interceptor[] interceptors, String viewPath, String requestMethod) {
super(controllerKey, actionKey, controllerClass, method, methodName, interceptors, viewPath);
+ this.requestMethod = requestMethod;
}
+
+
}
diff --git a/src/main/java/io/jboot/components/restful/RestfulErrorRender.java b/src/main/java/io/jboot/components/restful/RestfulErrorRender.java
deleted file mode 100644
index d2154da2fc9440b60dd9061ed96e14016f4965dc..0000000000000000000000000000000000000000
--- a/src/main/java/io/jboot/components/restful/RestfulErrorRender.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.jboot.components.restful;
-
-import com.jfinal.core.Action;
-import com.jfinal.render.Render;
-
-
-public abstract class RestfulErrorRender extends Render {
-
- private String target;
-
- private Action action;
-
- private Exception error;
-
- public void init (String target, Action action, Exception error) {
- this.target = target;
- this.action = action;
- this.error = error;
- }
-
- protected RestfulErrorRender() {
- }
-
- protected String getTarget() {
- return target;
- }
-
- protected Action getAction() {
- return action;
- }
-
- protected Exception getError() {
- return error;
- }
-}
diff --git a/src/main/java/io/jboot/components/restful/RestfulHandler.java b/src/main/java/io/jboot/components/restful/RestfulHandler.java
index a763739322469c0d36f5b0fb1a433de590d62c2d..d6b44370953b0c48bb3f4f9ec47753aca885bf33 100644
--- a/src/main/java/io/jboot/components/restful/RestfulHandler.java
+++ b/src/main/java/io/jboot/components/restful/RestfulHandler.java
@@ -20,14 +20,15 @@ public class RestfulHandler extends JbootActionHandler {
@Override
public Action getAction(String target, String[] urlPara, HttpServletRequest request) {
Action action = super.getAction(target, urlPara);
- if (action == null) {
+ if(action != null){
if (action.getActionKey().equals("/") && action.getMethodName().equals("index")
&& StrUtil.isNotBlank(target) && !target.equals(action.getActionKey())) {
action = JbootRestfulManager.me().getRestfulAction(target, request.getMethod());
}
}
-
-
+ if (action == null) {
+ action = JbootRestfulManager.me().getRestfulAction(target, request.getMethod());
+ }
return action;
}
@@ -42,161 +43,6 @@ public class RestfulHandler extends JbootActionHandler {
}
}
-
- // @Override
-// public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
-// if (target.indexOf('.') != -1) {
-// return;
-// }
-//
-// isHandled[0] = true;
-// String[] urlPara = {null};
-// Action action = getAction(target, urlPara);
-// RestfulAction restfulAction = null;
-// if (action != null && action.getActionKey().equals("/") && action.getMethodName().equals("index")
-// && StrUtil.isNotBlank(target) && !target.equals(action.getActionKey())) {
-// //如果被默认的"/"拦截,并且为index方法,但是请求的url又和actionKey不匹配,则有可能是restful请求
-// try {
-// restfulAction = JbootRestfulManager.me().getRestfulAction(target, request.getMethod());
-// } catch (RequestMethodErrorException e) {
-// handleActionException(target, request, response, action, e);
-// return;
-// }
-// if (restfulAction != null) {
-// action = null;
-// }
-// }
-// //如果无法从内置的action中获取action则尝试从restful管理的action中获取
-// if (action == null) {
-// // 尝试从restful 获取action
-// try {
-// if (restfulAction == null) {
-// restfulAction = JbootRestfulManager.me().getRestfulAction(target, request.getMethod());
-// }
-// } catch (RequestMethodErrorException e) {
-// handleActionException(target, request, response, action, e);
-// return;
-// }
-// if (restfulAction != null) {
-// //restful 风格的请求处理
-// restfulRequest(restfulAction, target, request, response, isHandled);
-// return;
-// }
-// if (log.isWarnEnabled()) {
-// String qs = request.getQueryString();
-// log.warn("404 Action Not Found: " + (qs == null ? target : target + "?" + qs));
-// }
-// renderManager.getRenderFactory().getErrorRender(404).setContext(request, response).render();
-// return;
-// }
-// //在获取到了
-// super.handle(target, request, response, isHandled);
-// }
-
-// private void restfulRequest(RestfulAction restfulAction, String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
-// Action action = restfulAction.getAction();
-// Controller controller = null;
-// try {
-// controller = controllerFactory.getController(action.getControllerClass());
-// //注入依赖
-// if (injectDependency) {
-// com.jfinal.aop.Aop.inject(controller);
-// }
-// //绑定controller本身到当前线程
-// JbootControllerContext.hold(controller);
-// //初始化controller
-// CPI._init_(controller, action, request, response, null);
-//
-// //解析参数
-// Object[] args = RestfulUtils.parseActionMethodParameters(target, restfulAction.getActionKey(),
-// action.getMethod(), request, controller.getRawData());
-// RestfulCallback restfulCallback = new RestfulCallback(restfulAction, controller);
-//
-// Invocation invocation = new Invocation(controller, action.getMethod(), action.getInterceptors(),
-// restfulCallback, args);
-//
-// RestfulInvocation fixedInvocation;
-// if (devMode) {
-// if (ActionReporter.isReportAfterInvocation(request)) {
-// fixedInvocation = invokeInvocation(invocation);
-// ActionReporter.report(target, controller, action);
-// } else {
-// ActionReporter.report(target, controller, action);
-// fixedInvocation = invokeInvocation(invocation);
-// }
-// } else {
-// fixedInvocation = invokeInvocation(invocation);
-// }
-//
-// Object returnValue = fixedInvocation.getReturnValue();
-//
-// // 判断是否带有@DownloadResponse
-// DownloadResponse downloadResponse = action.getMethod().getAnnotation(DownloadResponse.class);
-// if (returnValue == null && downloadResponse == null) {
-// //无返回结果的 restful 请求
-// controller.renderNull();
-// }
-// // 如果标记了@DownloadResponse,并且返回值不为空,会被认为自行处理了下载行为
-// if (downloadResponse != null) {
-// return;
-// }
-// if (returnValue != null) {
-// //初始化返回值
-// initRenderValue(returnValue, controller);
-// }
-//
-// Render render = controller.getRender();
-// if (render instanceof ForwardActionRender) {
-// String actionUrl = ((ForwardActionRender) render).getActionUrl();
-// if (target.equals(actionUrl)) {
-// throw new RuntimeException("The forward action url is the same as before.");
-// } else {
-// handle(actionUrl, request, response, isHandled);
-// }
-// return;
-// }
-//
-// if (render == null) {
-// render = renderManager.getRenderFactory().getDefaultRender(action.getViewPath() + action.getMethodName());
-// }
-//
-// //初始化自定义头部
-// initResponseHeaders(response, fixedInvocation.getMethod());
-// //响应开始
-// render.setContext(request, response, action.getViewPath()).render();
-//
-// } catch (RenderException | ParameterNullErrorException | ParameterParseErrorException | ActionException e) {
-// handleActionException(target, request, response, action, e);
-// } catch (Exception e) {
-// String info = ClassUtil.buildMethodString(action.getMethod());
-// if (log.isErrorEnabled()) {
-// String qs = request.getQueryString();
-// String targetInfo = qs == null ? target : target + "?" + qs;
-// log.error(info + " : " + targetInfo, e);
-// }
-// //自定义错误处理
-// handleActionException(target, request, response, action, e);
-// } finally {
-// JbootControllerContext.release();
-// controllerFactory.recycle(controller);
-// }
-// }
-
-// private void handleActionException(String target, HttpServletRequest request, HttpServletResponse response,
-// Action action, Exception e) {
-// RestfulErrorRender restfulErrorRender = JbootRestfulManager.me().getRestfulErrorRender();
-// restfulErrorRender.setContext(request, response, action == null ? "" : action.getViewPath());
-// restfulErrorRender.init(target, action, e);
-// restfulErrorRender.render();
-// }
-
-
-// protected RestfulInvocation invokeInvocation(Invocation inv) {
-// RestfulInvocation fixedInvocation = new RestfulInvocation(inv);
-// fixedInvocation.invoke();
-// return fixedInvocation;
-// }
-
@Override
public void setResponse(HttpServletResponse response, Action action) {
ResponseHeader[] responseHeaders = action.getMethod().getAnnotationsByType(ResponseHeader.class);
@@ -215,33 +61,4 @@ public class RestfulHandler extends JbootActionHandler {
}
}
-// protected void initRenderValue(Object o, Controller controller) {
-// if (o.getClass().equals(String.class)
-// || o.getClass().equals(int.class)
-// || o.getClass().equals(double.class)
-// || o.getClass().equals(byte.class)
-// || o.getClass().equals(long.class)
-// || o.getClass().equals(float.class)
-// || o.getClass().equals(short.class)
-// || o.getClass().equals(char.class)
-// || o.getClass().equals(boolean.class)) {
-// controller.renderText(String.valueOf(o));
-// } else if (o.getClass().equals(File.class)) {
-// controller.renderFile((File) o);
-// } else if (o.getClass().equals(ResponseEntity.class)) {
-// ResponseEntity responseEntity = (ResponseEntity) o;
-// //设置自定义头部信息
-// Map headers = responseEntity.getHeaders();
-//
-// headers.forEach((k, v) -> controller.getResponse().setHeader(k, v));
-// //设置http状态代码
-// controller.getResponse().setStatus(responseEntity.getHttpStatus().value());
-// initRenderValue(responseEntity.getData(), controller);
-// } else if (o instanceof Render) { //如果是render类型直接设置render
-// controller.render((Render) o);
-// } else {
-// controller.renderJson(o);
-// }
-// }
-
}
diff --git a/src/main/java/io/jboot/components/restful/RestfulInvocation.java b/src/main/java/io/jboot/components/restful/RestfulInvocation.java
index fe0df0d6d2c0902259c40e497827a3f8360e54c2..99e16b587c126eb86e8e500b9a255e4f0a81538b 100644
--- a/src/main/java/io/jboot/components/restful/RestfulInvocation.java
+++ b/src/main/java/io/jboot/components/restful/RestfulInvocation.java
@@ -8,7 +8,6 @@ public class RestfulInvocation extends Invocation {
private Action action;
-
public RestfulInvocation(Action action, Controller controller, Object[] args) {
super(controller, action.getMethod(), action.getInterceptors(), new RestfulCallback(action, controller), args);
this.action = action;
diff --git a/src/main/java/io/jboot/components/restful/RestfulUtils.java b/src/main/java/io/jboot/components/restful/RestfulUtils.java
index cbb64f62f50cc53bc5034d4131e376afcbf0cad0..e9190698a8c46b25f20cf31637c07e484f099718 100644
--- a/src/main/java/io/jboot/components/restful/RestfulUtils.java
+++ b/src/main/java/io/jboot/components/restful/RestfulUtils.java
@@ -1,23 +1,27 @@
package io.jboot.components.restful;
+import com.jfinal.core.ActionException;
import com.jfinal.kit.JsonKit;
-import io.jboot.components.restful.annotation.PathVariable;
-import io.jboot.components.restful.annotation.RequestBody;
-import io.jboot.components.restful.annotation.RequestHeader;
-import io.jboot.components.restful.annotation.RequestParam;
-import io.jboot.components.restful.exception.ParameterNullErrorException;
-import io.jboot.components.restful.exception.ParameterParseErrorException;
+import com.jfinal.render.RenderManager;
+import io.jboot.components.restful.annotation.*;
import io.jboot.utils.StrUtil;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+import java.util.TimeZone;
public class RestfulUtils {
+ private static final RenderManager renderManager = RenderManager.me();
+
/**
* 从url中解析路径参数
*
@@ -52,11 +56,10 @@ public class RestfulUtils {
* @param request
* @param rawData
* @return
- * @throws ParameterNullErrorException
- * @throws ParameterParseErrorException
+ * @throws ActionException
*/
public static Object[] parseActionMethodParameters(String target, String actionKey, Method actionMethod, HttpServletRequest request, String rawData)
- throws ParameterNullErrorException, ParameterParseErrorException {
+ throws ActionException {
Object[] args = new Object[actionMethod.getParameters().length];
for (int i = 0; i < actionMethod.getParameters().length; i++) {
Parameter parameter = actionMethod.getParameters()[i];
@@ -72,28 +75,28 @@ public class RestfulUtils {
}
values = request.getParameterValues(parameterName);
parameter.getType();
- args[i] = parseRequestParamToParameter(values, parameterName, parameter.getType());
+ args[i] = parseRequestParamToParameter(values, parameterName, parameter.getType(), parameter);
if (args[i] == null && requestParam.required()) {
- //要求参数为空,但是却并没有提供参数
- throw new ParameterNullErrorException(parameterName);
+ //要求参数不为空,但是却并没有提供参数
+ throw genBindError("Parameter '" + parameterName + "' specifies a forced check, but the value is null");
}
} else if (requestBody != null) {
- args[i] = parseRequestBodyToParameter(rawData, parameterName, parameter.getType());
+ args[i] = parseRequestBodyToParameter(rawData, parameterName, parameter.getType(), parameter);
} else if (requestHeader != null) {
if (StrUtil.isNotBlank(requestHeader.value())) {
parameterName = requestHeader.value();
}
String value = request.getHeader(parameterName);
- args[i] = parseRequestHeaderToParameter(value, parameterName, parameter.getType());
+ args[i] = parseRequestHeaderToParameter(value, parameterName, parameter.getType(), parameter);
if (args[i] == null && requestHeader.required()) {
- //要求参数为空,但是却并没有提供参数
- throw new ParameterNullErrorException(parameterName);
+ //要求参数不为空,但是却并没有提供参数
+ throw genBindError("Parameter '" + parameterName + "' specifies a forced check, but the value is null");
}
} else if (pathVariable != null) {
if (StrUtil.isNotBlank(pathVariable.value())) {
parameterName = pathVariable.value();
}
- args[i] = parsePathVariableToParameter(target, actionKey, parameterName, parameter.getType());
+ args[i] = parsePathVariableToParameter(target, actionKey, parameterName, parameter.getType(), parameter);
} else {
args[i] = null;
}
@@ -119,83 +122,107 @@ public class RestfulUtils {
return matchingCount == sourcePaths.length;
}
- private static Object parseRequestParamToParameter(String[] value, String name, Class> parameterTypeClass) {
- if(parameterTypeClass.isArray()){
- Object [] objects = new Object[value.length];
+ private static Object parseRequestParamToParameter(String[] value, String name, Class> parameterTypeClass, Parameter parameter) {
+ if (parameterTypeClass.isArray()) {
+ Object[] objects = new Object[value.length];
for (int i = 0; i < value.length; i++) {
- objects[i] = parseCommonValue(value[i], name, parameterTypeClass);
+ objects[i] = parseCommonValue(value[i], name, parameterTypeClass, parameter);
}
return objects;
} else {
- if(value != null && value.length > 0){
- return parseCommonValue(value[0], name, parameterTypeClass);
+ if (value != null && value.length > 0) {
+ return parseCommonValue(value[0], name, parameterTypeClass, parameter);
}
}
return null;
}
- private static Object parseRequestHeaderToParameter(String header, String name, Class> parameterTypeClass) {
- return parseCommonValue(header, name, parameterTypeClass);
+ private static Object parseRequestHeaderToParameter(String header, String name, Class> parameterTypeClass, Parameter parameter) {
+ return parseCommonValue(header, name, parameterTypeClass, parameter);
}
- private static Object parseRequestBodyToParameter(String body, String name, Class> parameterTypeClass) {
+ private static Object parseRequestBodyToParameter(String body, String name, Class> parameterTypeClass, Parameter parameter) {
//先当作基本数据来转换
- Object value = parseCommonValue(body, name, parameterTypeClass);
- if(value == null){
+ Object value = parseCommonValue(body, name, parameterTypeClass, parameter);
+ if (value == null) {
value = JsonKit.parse(body, parameterTypeClass);
}
return value;
}
- private static Object parsePathVariableToParameter(String target, String actionKey, String parameterName, Class> parameterTypeClass) {
+ private static Object parsePathVariableToParameter(String target, String actionKey, String parameterName, Class> parameterTypeClass, Parameter parameter) {
Map pathVariables = parsePathVariables(target, actionKey);
String value = pathVariables.get(parameterName);
- return parseCommonValue(value, parameterName, parameterTypeClass);
+ return parseCommonValue(value, parameterName, parameterTypeClass, parameter);
}
/**
* 转换基本类型参数,目前支持string,int,double,float,boolean,long基本类型数据
+ *
* @param value
* @param name
* @param parameterTypeClass
+ * @param parameter
* @return
*/
- private static Object parseCommonValue(String value, String name, Class> parameterTypeClass) {
+ private static Object parseCommonValue(String value, String name, Class> parameterTypeClass, Parameter parameter) {
if (StrUtil.isBlank(value)) {
return null;
}
if (parameterTypeClass.equals(String.class)) {
return value;
- } else if (parameterTypeClass.equals(int.class)) {
- try {
- return Integer.valueOf(value);
- } catch (NumberFormatException e) {
- throw new ParameterParseErrorException(value, name, parameterTypeClass);
- }
- } else if (parameterTypeClass.equals(double.class)) {
- try {
- return Double.valueOf(value);
- } catch (NumberFormatException e) {
- throw new ParameterParseErrorException(value, name, parameterTypeClass);
- }
- } else if (parameterTypeClass.equals(float.class)) {
+ } else if (parameterTypeClass.equals(int.class)
+ || parameterTypeClass.equals(double.class)
+ || parameterTypeClass.equals(float.class)
+ || parameterTypeClass.equals(long.class)
+ || parameterTypeClass.equals(BigDecimal.class)
+ || parameterTypeClass.equals(short.class)) {
try {
- return Float.valueOf(value);
+ if (parameterTypeClass.equals(int.class)) {
+ return Integer.valueOf(value);
+ } else if (parameterTypeClass.equals(double.class)) {
+ return Double.valueOf(value);
+ } else if (parameterTypeClass.equals(float.class)) {
+ return Float.valueOf(value);
+ } else if (parameterTypeClass.equals(long.class)) {
+ return Long.valueOf(value);
+ } else if (parameterTypeClass.equals(BigDecimal.class)) {
+ return new BigDecimal(value);
+ } else if (parameterTypeClass.equals(short.class)) {
+ return Short.valueOf(value);
+ } else {
+ return null;
+ }
} catch (NumberFormatException e) {
- throw new ParameterParseErrorException(value, name, parameterTypeClass);
+ throw genBindError("Error resolving parameter '" + name + "', unable to match value '"
+ + value + "' to specified type '" + parameterTypeClass.getName() + "'");
}
} else if (parameterTypeClass.equals(boolean.class)) {
return Boolean.valueOf(value);
- } else if (parameterTypeClass.equals(long.class)) {
+ } else if (parameterTypeClass.equals(Date.class)) {
+ DateFormat dateFormat = parameter.getAnnotation(DateFormat.class);
+ SimpleDateFormat simpleDateFormat;
+ if (dateFormat != null) {
+ simpleDateFormat = new SimpleDateFormat(dateFormat.value());
+ simpleDateFormat.setTimeZone(TimeZone.getTimeZone(dateFormat.timeZone()));
+ } else {
+ simpleDateFormat = new SimpleDateFormat();
+ }
try {
- return Long.valueOf(value);
- } catch (NumberFormatException e) {
- throw new ParameterParseErrorException(value, name, parameterTypeClass);
+ return simpleDateFormat.parse(value);
+ } catch (ParseException e) {
+ throw genBindError("Error resolving parameter '" + name + "', unable to match value '"
+ + value + "' to specified type '" + parameterTypeClass.getName() + "'");
}
} else {
return null;
}
}
+ private static ActionException genBindError(String message) {
+ return new ActionException(HttpStatus.BAD_REQUEST.value(),
+ renderManager.getRenderFactory().getErrorRender(HttpStatus.BAD_REQUEST.value()), message);
+ }
+
}
diff --git a/src/main/java/io/jboot/components/restful/annotation/DownloadResponse.java b/src/main/java/io/jboot/components/restful/annotation/DateFormat.java
similarity index 36%
rename from src/main/java/io/jboot/components/restful/annotation/DownloadResponse.java
rename to src/main/java/io/jboot/components/restful/annotation/DateFormat.java
index c4aa83e81af1d5259ab1797017e80dc1dac13178..b8939ecfff34a25e12be585e93135ed49c935337 100644
--- a/src/main/java/io/jboot/components/restful/annotation/DownloadResponse.java
+++ b/src/main/java/io/jboot/components/restful/annotation/DateFormat.java
@@ -3,10 +3,17 @@ package io.jboot.components.restful.annotation;
import java.lang.annotation.*;
/**
- * 标注controller action是一个下载响应,并且需要action自行处理response
+ *
+ * 日期注解,可以结合@PathVarible,@RequestParam,@RequestHeader一起使用
+ *
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
+@Target(ElementType.PARAMETER)
@Documented
-public @interface DownloadResponse {
+public @interface DateFormat {
+
+ String value() default "yyyy-MM-dd HH:mm:ss";
+
+ String timeZone() default "GMT+8";
+
}
diff --git a/src/main/java/io/jboot/components/restful/annotation/PathVariable.java b/src/main/java/io/jboot/components/restful/annotation/PathVariable.java
index 68a962491c0c6af12dfd1c47400f6dfc4d3d1453..4d0c04c4ce581d4d85ebec6d52b40257539a33a8 100644
--- a/src/main/java/io/jboot/components/restful/annotation/PathVariable.java
+++ b/src/main/java/io/jboot/components/restful/annotation/PathVariable.java
@@ -12,6 +12,9 @@ import java.lang.annotation.*;
* float
* boolean
* long
+ * bigDecimal
+ * date
+ * short
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
diff --git a/src/main/java/io/jboot/components/restful/annotation/RequestBody.java b/src/main/java/io/jboot/components/restful/annotation/RequestBody.java
index 73327a66058d243fc484ea12bfc6014c6d7d221e..ae2d882638315234b73cb6a8c588de6c09f681cb 100644
--- a/src/main/java/io/jboot/components/restful/annotation/RequestBody.java
+++ b/src/main/java/io/jboot/components/restful/annotation/RequestBody.java
@@ -5,13 +5,16 @@ import java.lang.annotation.*;
/**
* 请求体参数注解
* 支持如下类型参数:
- * string / string[]
- * int / int[]
- * double / double[]
- * float / float[]
- * boolean / boolean[]
- * long / long[]
- * object / object[]
+ * string
+ * int
+ * double
+ * float
+ * boolean
+ * long
+ * object
+ * bigDecimal
+ * date
+ * short
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
diff --git a/src/main/java/io/jboot/components/restful/annotation/RequestHeader.java b/src/main/java/io/jboot/components/restful/annotation/RequestHeader.java
index 5a9679701f541fc920d706a69a9368d3546bc821..9a9c361c8e7aee0adf3a94bc374881e8950df4f3 100644
--- a/src/main/java/io/jboot/components/restful/annotation/RequestHeader.java
+++ b/src/main/java/io/jboot/components/restful/annotation/RequestHeader.java
@@ -11,7 +11,9 @@ import java.lang.annotation.*;
* float
* boolean
* long
- *
+ * bigDecimal
+ * date
+ * short
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
diff --git a/src/main/java/io/jboot/components/restful/annotation/RequestParam.java b/src/main/java/io/jboot/components/restful/annotation/RequestParam.java
index e4a16089e93e9727d943267238e0caf26fbb0a2a..906af5649de62d0167ff47dd0cedb2c6878d0fe3 100644
--- a/src/main/java/io/jboot/components/restful/annotation/RequestParam.java
+++ b/src/main/java/io/jboot/components/restful/annotation/RequestParam.java
@@ -11,7 +11,9 @@ import java.lang.annotation.*;
* float / float[]
* boolean / boolean[]
* long / long[]
- *
+ * bigDecimal / bigDecimal[]
+ * date / date[]
+ * short / short[]
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
diff --git a/src/main/java/io/jboot/components/restful/exception/ParameterNullErrorException.java b/src/main/java/io/jboot/components/restful/exception/ParameterNullErrorException.java
deleted file mode 100644
index 081867cccb5c665399abf5116e70affe88ca95b4..0000000000000000000000000000000000000000
--- a/src/main/java/io/jboot/components/restful/exception/ParameterNullErrorException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package io.jboot.components.restful.exception;
-
-/**
- * 参数为空错误
- */
-public class ParameterNullErrorException extends RuntimeException {
-
- private String parameterName;
-
-
- public String getParameterName() {
- return parameterName;
- }
-
- public ParameterNullErrorException(String parameterName) {
- super("Parameter '"+parameterName+"' specifies a forced check, but the value is null");
- this.parameterName = parameterName;
- }
-
- public ParameterNullErrorException(Exception e) {
- super(e);
- }
-
-}
diff --git a/src/main/java/io/jboot/components/restful/exception/ParameterParseErrorException.java b/src/main/java/io/jboot/components/restful/exception/ParameterParseErrorException.java
deleted file mode 100644
index 2a025ab6563b66edd8b7c875b4ab68d67c4aaf07..0000000000000000000000000000000000000000
--- a/src/main/java/io/jboot/components/restful/exception/ParameterParseErrorException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package io.jboot.components.restful.exception;
-
-/**
- * 参数类型错误
- */
-public class ParameterParseErrorException extends RuntimeException {
-
-
- private String parameterValue;
-
- private String parameterName;
-
- private Class> parameterType;
-
- public String getParameterValue() {
- return parameterValue;
- }
-
- public String getParameterName() {
- return parameterName;
- }
-
- public Class> getParameterType() {
- return parameterType;
- }
-
- public ParameterParseErrorException(String parameterValue, String parameterName, Class> parameterType) {
- super("Error resolving parameter '" + parameterName + "', unable to match value '"
- + parameterValue + "' to specified type '" + parameterType.getName() + "'");
- this.parameterValue = parameterValue;
- this.parameterName = parameterName;
- this.parameterType = parameterType;
- }
-
- public ParameterParseErrorException(Exception e) {
- super(e);
- }
-
-}
diff --git a/src/main/java/io/jboot/components/restful/exception/RequestMethodErrorException.java b/src/main/java/io/jboot/components/restful/exception/RequestMethodErrorException.java
deleted file mode 100644
index e72f83c97ea85862d73754f77e24d9396aa66cef..0000000000000000000000000000000000000000
--- a/src/main/java/io/jboot/components/restful/exception/RequestMethodErrorException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package io.jboot.components.restful.exception;
-
-/**
- * 请求方法错误
- */
-public class RequestMethodErrorException extends RuntimeException {
-
- private String actionKey;
-
- private String actionMethod;
-
- private String target;
-
- private String targetMethod;
-
- public String getActionKey() {
- return actionKey;
- }
-
- public String getActionMethod() {
- return actionMethod;
- }
-
- public String getTarget() {
- return target;
- }
-
- public String getTargetMethod() {
- return targetMethod;
- }
-
- public RequestMethodErrorException(String actionKey, String actionMethod, String target, String targetMethod) {
- super("'" + target + "' is specified as a '" + actionMethod + "' request. '" + targetMethod + "' requests are not supported");
- this.actionKey = actionKey;
- this.actionMethod = actionMethod;
- this.target = target;
- this.targetMethod = targetMethod;
- }
-}
diff --git a/src/main/java/io/jboot/components/rpc/JbootrpcConfig.java b/src/main/java/io/jboot/components/rpc/JbootrpcConfig.java
index 78b01fd1caeed0d8ba62ba81e6d602f94b0e12b0..9c3405585643bee54b9bdbe7fcff568a469fba4d 100644
--- a/src/main/java/io/jboot/components/rpc/JbootrpcConfig.java
+++ b/src/main/java/io/jboot/components/rpc/JbootrpcConfig.java
@@ -32,15 +32,27 @@ public class JbootrpcConfig {
//用于直连时的配置,直连一般只用于测试环境
//com.service.AAAService:127.0.0.1:8080,com.service.XXXService:127.0.0.1:8080
- private Map urls;
+ private Map urls;
//服务的provider指定,可以通过注解 @RPCBean 指定,也可以通过此处指定,此处的配置优先于注解
//com.service.AAAService:providerName,com.service.XXXService:providerName
- private Map providers;
+ private Map providers;
//服务的consumer指定,可以通过注解 @RPCInject 指定,也可以通过此处指定,此处的配置优先于注解
//com.service.AAAService:providerName,com.service.XXXService:providerName
- private Map consumers;
+ private Map consumers;
+
+ //当不配置的时候,默认版本号
+ private String defaultVersion = "1.0.0";
+
+ //指定的服务的版本号
+ private Map versions;
+
+ //当不指定的时候,默认分组
+ private String defaultGroup;
+
+ //指定的服务的分组
+ private Map groups;
//本地自动暴露 @RPCBean 的 service
private boolean autoExportEnable = true;
@@ -62,7 +74,7 @@ public class JbootrpcConfig {
this.urls = urls;
}
- public String getUrl(String serviceClass){
+ public String getUrl(String serviceClass) {
return urls == null ? null : urls.get(serviceClass);
}
@@ -74,7 +86,7 @@ public class JbootrpcConfig {
this.providers = providers;
}
- public String getProvider(String serviceClass){
+ public String getProvider(String serviceClass) {
return providers == null ? null : providers.get(serviceClass);
}
@@ -86,10 +98,52 @@ public class JbootrpcConfig {
this.consumers = consumers;
}
- public String getConsumer(String serviceClass){
+ public String getConsumer(String serviceClass) {
return consumers == null ? null : consumers.get(serviceClass);
}
+ public String getDefaultVersion() {
+ return defaultVersion;
+ }
+
+ public void setDefaultVersion(String defaultVersion) {
+ this.defaultVersion = defaultVersion;
+ }
+
+ public Map getVersions() {
+ return versions;
+ }
+
+ public void setVersions(Map versions) {
+ this.versions = versions;
+ }
+
+ public String getVersion(String className) {
+ String version = versions == null || versions.isEmpty() ? null : versions.get(className);
+ return version == null ? defaultVersion : version;
+ }
+
+ public String getDefaultGroup() {
+ return defaultGroup;
+ }
+
+ public void setDefaultGroup(String defaultGroup) {
+ this.defaultGroup = defaultGroup;
+ }
+
+ public Map getGroups() {
+ return groups;
+ }
+
+ public void setGroups(Map groups) {
+ this.groups = groups;
+ }
+
+ public String getGroup(String className) {
+ String group = groups == null || groups.isEmpty() ? null : groups.get(className);
+ return group == null ? defaultGroup : group;
+ }
+
public boolean isAutoExportEnable() {
return autoExportEnable;
}
diff --git a/src/main/java/io/jboot/components/rpc/dubbo/JbootDubborpc.java b/src/main/java/io/jboot/components/rpc/dubbo/JbootDubborpc.java
index 169e2bec25eaf2ee28d4dc486d0c1784ad39770c..1ce4648f1dcee689db9c47415dcbe7f2b78bccfd 100644
--- a/src/main/java/io/jboot/components/rpc/dubbo/JbootDubborpc.java
+++ b/src/main/java/io/jboot/components/rpc/dubbo/JbootDubborpc.java
@@ -41,15 +41,23 @@ public class JbootDubborpc extends JbootrpcBase {
reference.setInterface(interfaceClass);
String directUrl = rpcConfig.getUrl(interfaceClass.getName());
- if (StrUtil.isNotBlank(directUrl)){
+ if (StrUtil.isNotBlank(directUrl)) {
reference.setUrl(directUrl);
}
String consumer = rpcConfig.getConsumer(interfaceClass.getName());
- if (consumer != null){
+ if (consumer != null) {
reference.setConsumer(DubboUtil.getConsumer(consumer));
}
+ if (reference.getGroup() == null) {
+ reference.setGroup(rpcConfig.getGroup(interfaceClass.getName()));
+ }
+
+ if (reference.getVersion() == null) {
+ reference.setVersion(rpcConfig.getVersion(interfaceClass.getName()));
+ }
+
return reference.get();
}
@@ -61,10 +69,18 @@ public class JbootDubborpc extends JbootrpcBase {
service.setRef((T) object);
String provider = rpcConfig.getProvider(interfaceClass.getName());
- if (provider != null){
+ if (provider != null) {
service.setProvider(DubboUtil.getProvider(provider));
}
+ if (service.getGroup() == null) {
+ service.setGroup(rpcConfig.getGroup(interfaceClass.getName()));
+ }
+
+ if (service.getVersion() == null) {
+ service.setVersion(rpcConfig.getVersion(interfaceClass.getName()));
+ }
+
service.export();
return true;
}
diff --git a/src/main/java/io/jboot/components/rpc/motan/JbootMotanrpc.java b/src/main/java/io/jboot/components/rpc/motan/JbootMotanrpc.java
index f9c1c4b4863779b5993bb3b53a65e2f0ebd34076..9d4282c63717395449ca986880aebd0a29b6ac0f 100644
--- a/src/main/java/io/jboot/components/rpc/motan/JbootMotanrpc.java
+++ b/src/main/java/io/jboot/components/rpc/motan/JbootMotanrpc.java
@@ -51,6 +51,14 @@ public class JbootMotanrpc extends JbootrpcBase {
referer.setBasicReferer(MotanUtil.getBaseReferer(consumer));
}
+ if (referer.getGroup() == null) {
+ referer.setGroup(rpcConfig.getGroup(interfaceClass.getName()));
+ }
+
+ if (referer.getVersion() == null) {
+ referer.setVersion(rpcConfig.getVersion(interfaceClass.getName()));
+ }
+
return referer.getRef();
}
@@ -62,19 +70,27 @@ public class JbootMotanrpc extends JbootrpcBase {
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, false);
- ServiceConfig serviceConfig = MotanUtil.toServiceConfig(config);
- serviceConfig.setInterface(interfaceClass);
- serviceConfig.setRef((T) object);
- serviceConfig.setShareChannel(true);
- serviceConfig.setExport(defaultConfig.getExport(interfaceClass.getName()));
- serviceConfig.setHost(defaultConfig.getHost(interfaceClass.getName()));
+ ServiceConfig service = MotanUtil.toServiceConfig(config);
+ service.setInterface(interfaceClass);
+ service.setRef((T) object);
+ service.setShareChannel(true);
+ service.setExport(defaultConfig.getExport(interfaceClass.getName()));
+ service.setHost(defaultConfig.getHost(interfaceClass.getName()));
String provider = rpcConfig.getProvider(interfaceClass.getName());
if (provider != null) {
- serviceConfig.setBasicService(MotanUtil.getBaseService(provider));
+ service.setBasicService(MotanUtil.getBaseService(provider));
+ }
+
+ if (service.getGroup() == null) {
+ service.setGroup(rpcConfig.getGroup(interfaceClass.getName()));
+ }
+
+ if (service.getVersion() == null) {
+ service.setVersion(rpcConfig.getVersion(interfaceClass.getName()));
}
- serviceConfig.export();
+ service.export();
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
}
diff --git a/src/main/java/io/jboot/components/rpc/motan/MotanrpcConfig.java b/src/main/java/io/jboot/components/rpc/motan/MotanrpcConfig.java
index 1f96175f11b28ab8eb92ca906d22a462a1abb401..258c8f1fd74d5907937d8f874566a41b31f55b81 100644
--- a/src/main/java/io/jboot/components/rpc/motan/MotanrpcConfig.java
+++ b/src/main/java/io/jboot/components/rpc/motan/MotanrpcConfig.java
@@ -77,7 +77,7 @@ public class MotanrpcConfig {
}
public String getExport(String className) {
- String export = exports == null ? null : exports.get(className);
+ String export = exports == null || exports.isEmpty() ? null : exports.get(className);
return StrUtil.isNotBlank(export) ? export : defaultExport;
}
@@ -90,7 +90,7 @@ public class MotanrpcConfig {
}
public String getHost(String className) {
- String host = hosts == null ? null : hosts.get(className);
+ String host = hosts == null || hosts.isEmpty() ? null : hosts.get(className);
return StrUtil.isNotBlank(host) ? host : defaultHost;
}
}
diff --git a/src/main/java/io/jboot/core/JbootCoreConfig.java b/src/main/java/io/jboot/core/JbootCoreConfig.java
index d52098103f99521d39b49f4db6d2b936a36a4000..e5b573b9d778bfc1c089f877b2d3001a1a139bd5 100644
--- a/src/main/java/io/jboot/core/JbootCoreConfig.java
+++ b/src/main/java/io/jboot/core/JbootCoreConfig.java
@@ -80,7 +80,6 @@ public class JbootCoreConfig extends JFinalConfig {
private JbootRestfulManager.Config restfulConfig = new JbootRestfulManager.Config();
-
public JbootCoreConfig() {
initSystemProperties();
@@ -219,6 +218,7 @@ public class JbootCoreConfig extends JFinalConfig {
routeList.addAll(restfulRoutes);
}
+
routeList.addAll(routes.getRouteItemList());
}
@@ -293,11 +293,10 @@ public class JbootCoreConfig extends JFinalConfig {
handlers.add(new JbootGatewayHandler());
handlers.add(new JbootFilterHandler());
handlers.add(new JbootHandler());
-// handlers.setActionHandler(new RestfulHandler());
//若用户自己没配置 ActionHandler,默认使用 JbootActionHandler
if (handlers.getActionHandler() == null) {
- if (restfulRoutes.isEmpty()) {
+ if (!restfulRoutes.isEmpty()) {
handlers.setActionHandler(new RestfulHandler());
} else {
handlers.setActionHandler(new JbootActionHandler());
@@ -326,7 +325,6 @@ public class JbootCoreConfig extends JFinalConfig {
JbootGatewayManager.me().init();
JbootRestfulManager.me().init(restfulConfig);
-
JbootAppListenerManager.me().onStart();
}
diff --git a/src/main/java/io/jboot/web/handler/JbootActionHandler.java b/src/main/java/io/jboot/web/handler/JbootActionHandler.java
index c5a0a4df68cd28b1ba8d49c1a48165c903b9b6e8..114861e8624a1509faf9fa203f57f94b95fb5591 100644
--- a/src/main/java/io/jboot/web/handler/JbootActionHandler.java
+++ b/src/main/java/io/jboot/web/handler/JbootActionHandler.java
@@ -120,7 +120,7 @@ public class JbootActionHandler extends ActionHandler {
}
if (render == null
- && invocation.getReturnValue() != null
+ && void.class != action.getMethod().getReturnType()
&& renderManager.getRenderFactory() instanceof JbootRenderFactory) {
JbootRenderFactory jrf = (JbootRenderFactory) renderManager.getRenderFactory();
render = jrf.getReturnValueRender(action, invocation.getReturnValue());
diff --git a/src/main/java/io/jboot/web/render/JbootReturnValueRender.java b/src/main/java/io/jboot/web/render/JbootReturnValueRender.java
index caab4d1344aa0d2b2778ffdd3c34151e92bb466c..6061a7ff5dfe1c2bd82e6510e05b80131388335d 100644
--- a/src/main/java/io/jboot/web/render/JbootReturnValueRender.java
+++ b/src/main/java/io/jboot/web/render/JbootReturnValueRender.java
@@ -17,10 +17,8 @@ package io.jboot.web.render;
import com.jfinal.core.Action;
import com.jfinal.kit.JsonKit;
-import com.jfinal.render.FileRender;
-import com.jfinal.render.JsonRender;
-import com.jfinal.render.Render;
-import com.jfinal.render.TextRender;
+import com.jfinal.render.*;
+import io.jboot.components.restful.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -29,6 +27,7 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Map;
/**
* @author Michael Yang 杨福海 (fuhai999@gmail.com)
@@ -42,21 +41,33 @@ public class JbootReturnValueRender extends Render {
private Render render;
public JbootReturnValueRender(Action action, Object returnValue) {
+
this.action = action;
- if (isBaseType(returnValue)) {
+
+ if (returnValue == null) {
+ this.value = null;
+ } else if (isBaseType(returnValue)) {
this.value = String.valueOf(returnValue);
} else {
this.value = returnValue;
}
- if (this.value instanceof File) {
+ if (this.value == null) {
+ this.render = new NullRender();
+ } else if (this.value instanceof File) {
this.render = new FileRender((File) value);
} else if (this.value instanceof String) {
this.render = new TextRender((String) value);
} else if (this.value instanceof Date) {
this.render = new TextRender(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) value));
+ } else if (this.value instanceof Render) {
+ this.render = (Render) this.value;
} else {
- this.render = new JsonRender(JsonKit.toJson(value));
+ if (this.value instanceof ResponseEntity) {
+ this.render = new JsonRender(((ResponseEntity) this.value).getData());
+ } else {
+ this.render = new JsonRender(JsonKit.toJson(this.value));
+ }
}
}
@@ -64,25 +75,30 @@ public class JbootReturnValueRender extends Render {
@Override
public Render setContext(HttpServletRequest request, HttpServletResponse response) {
render.setContext(request, response);
+ super.setContext(request, response);
return this;
}
@Override
public Render setContext(HttpServletRequest request, HttpServletResponse response, String viewPath) {
render.setContext(request, response, viewPath);
+ super.setContext(request, response, viewPath);
return this;
}
@Override
public void render() {
+ if (this.value instanceof ResponseEntity) {
+ ResponseEntity responseEntity = (ResponseEntity) this.value;
+ Map headers = responseEntity.getHeaders();
+ headers.forEach((k, v) -> response.setHeader(k, v));
+ response.setStatus(responseEntity.getHttpStatus().value());
+ }
this.render.render();
}
private boolean isBaseType(Object value) {
- if (value == null) {
- return true;
- }
Class c = value.getClass();
return c == String.class || c == char.class
|| c == Integer.class || c == int.class
diff --git a/src/test/java/io/jboot/test/controller/IndexController.java b/src/test/java/io/jboot/test/controller/IndexController.java
index fcbdf8cd6098c2f020cc815193189a7f0da4cdc3..d402d71831a26d6de7e4890cb7ccb1ad279d725a 100644
--- a/src/test/java/io/jboot/test/controller/IndexController.java
+++ b/src/test/java/io/jboot/test/controller/IndexController.java
@@ -18,4 +18,11 @@ public class IndexController extends JbootController {
public void error500(){
}
+
+ public String ping(){
+ return "ping:" + getPara("ping");
+ }
+
+
+
}
diff --git a/src/test/java/io/jboot/test/gateway/GatewayController.java b/src/test/java/io/jboot/test/gateway/GatewayController.java
new file mode 100644
index 0000000000000000000000000000000000000000..7cca21d82ae58c51d8061956cdc10f07613a0677
--- /dev/null
+++ b/src/test/java/io/jboot/test/gateway/GatewayController.java
@@ -0,0 +1,26 @@
+package io.jboot.test.gateway;
+
+import io.jboot.web.controller.JbootController;
+import io.jboot.web.controller.annotation.RequestMapping;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author michael yang (fuhai999@gmail.com)
+ * @Date: 2020/4/5
+ */
+@RequestMapping("/gateway")
+public class GatewayController extends JbootController {
+
+ public void index(){
+
+ }
+
+
+ public void render(){
+ Map map = new HashMap();
+ map.putAll(getParas());
+ renderJson(map);
+ }
+}
diff --git a/src/test/java/io/jboot/test/restful/RestfulController.java b/src/test/java/io/jboot/test/restful/RestfulController.java
index 08a2367da89812b5c180b9358db61380e94cad13..ab1fc96c94f832c0fffff8fe4e6cfba175ab0dd0 100644
--- a/src/test/java/io/jboot/test/restful/RestfulController.java
+++ b/src/test/java/io/jboot/test/restful/RestfulController.java
@@ -15,7 +15,10 @@ import io.jboot.web.controller.annotation.RequestMapping;
import io.jboot.web.cors.EnableCORS;
import java.io.Serializable;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
@RestController
@@ -84,8 +87,10 @@ public class RestfulController extends JbootController {
// GET /restful/users
@GetMapping("/users")
- public ResponseEntity> entityUsers(){
- return new ResponseEntity<>(initData()).addHeader("x-token", StrKit.getRandomUUID()).setHttpStatus(HttpStatus.ACCEPTED);
+ public ResponseEntity entityUsers(){
+ return new ResponseEntity(initData())
+ .addHeader("x-token", StrKit.getRandomUUID())
+ .setHttpStatus(HttpStatus.ACCEPTED);
}
// PUT /restful
@@ -113,5 +118,23 @@ public class RestfulController extends JbootController {
System.out.println("delete by name : " + name);
System.out.println("get token header : " + token);
}
-
+
+ @GetMapping("/get-date")
+ public Date getDate(){
+ return new Date();
+ }
+
+ @PutMapping("/input-date")
+ public void inputDate(@RequestParam @DateFormat Date date){
+ System.out.println("input date:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
+ renderNull();
+ }
+
+ @PutMapping("/input-big-decimal")
+ public void inputBigDecimal(@RequestParam BigDecimal num){
+ System.out.println("input bigDecimal:"+num.toString());
+ renderNull();
+ }
+
+
}
diff --git a/src/test/resources/jboot.properties b/src/test/resources/jboot.properties
index 151711f485683539297be6b486cb56d94b56486b..f391de5e3c9e2a101ffbb4c30037ffc69a29037a 100644
--- a/src/test/resources/jboot.properties
+++ b/src/test/resources/jboot.properties
@@ -37,16 +37,11 @@ config.test.test.ccc.name = name3
config.test.test.ccc.type = type3
-# 配置 gateway ,访问首页的时候目标地址设置为 baidu 的地址
+# 配置 gateway ,当访问 /gateway 的时候,自动路由到 /gateway/render
jboot.gateway.enable = true
-jboot.gateway.uri = https://www.baidu.com
-#jboot.gateway.proxyRetries = 2
-jboot.gateway.pathEquals = /
-
-jboot.gateway.gitee.enable = true
-jboot.gateway.gitee.uri= https://gitee.com
-jboot.gateway.gitee.sentinelEnable= true
-jboot.gateway.gitee.sentinelBlockPage= /
-jboot.gateway.gitee.pathStartsWith = /fuhai
+jboot.gateway.uri = http://127.0.0.1:9999/gateway/render
+jboot.gateway.pathEquals = /gateway
+
+
jboot.rpc.type = local