Spring MVC DispatcherServlet改造为 CSE RestServlet 常见问题汇编
【摘要】 本文是使用CSE RestServlet替换Spring MVC DispatcherServlet常见问题汇总。
将Spring Boot的REST应用改造为CSE的REST应用的核心部分就是使用CSE RestServlet替换Spring MVC DispatcherServlet。有很多文章介绍了相关工作量评估、替换原理、改造步骤等。比如:
[改造原理和步骤] 在Spring Boot中使用CSE
[改造工作量评估] 微服务改造设计参考
[改造步骤和实践] 基于Spring Boot 2.0的IoT应用集成和使用CSE实践
本文主要是常见问题汇总。
--------------------------------------
问题摘要:使用RequestMapping定义多个Path
问题描述:
@RequestMapping(value = {"/v3-ext/agencies", "/v3-huawei/agencies", "/v3.0/OS-AGENCY/agencies"},
method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public Map<String, Object> listAgency(@RequestParam("domain_id") String domainId)
以上接口定义了多个Path。在CSE中,一个接口只能允许一个Path,并且必须存在唯一的operation id。默认情况下operation id就是方法名。
错误日志:
解决建议:
可以将一个接口拆分为多个接口。
@RequestMapping(value = {"/v3-ext/agencies"},
method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public Map<String, Object> listAgency1(@RequestParam("domain_id") String domainId)
@RequestMapping(value = {"/v3.0/OS-AGENCY/agencies"},
method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public Map<String, Object> listAgency2(@RequestParam("domain_id") String domainId)
--------------------------------------
问题摘要:不支持在接口参数里面使用HttpServletResponse
问题描述:
@RequestMapping(value = "/v3/groups/{group_id}/users/{user_id}", method = RequestMethod.HEAD, produces = "application/json;charset=UTF-8")
public void isUserOfGroup(@PathVariable("group_id") String groupId,
@PathVariable("user_id") String userId, HttpServletResponse response)
以上接口使用了HttpServletResponse作为接口参数。CSE的通信层与编码层是完全解耦的,业务代码不能直接操作通信层的响应。另外,CSE要求所有接口都需要有明确的定义(即契约,swagger),开发的时候,接口定义即文档。
错误日志:
解决建议:
这种情况需要试业务逻辑进行分析,将操作response的内容抽取为响应值。比如:
response.setStatus(resultCode)
这种代码只是想设置响应的错误码,可以替换为下面的方式:
@RequestMapping(value = "/v3/groups/{group_id}/users/{user_id}", method = RequestMethod.HEAD, produces = "application/json;charset=UTF-8")
@ApiResponses({
@ApiResponse(code = 200, response = String.class, message = ""),@ApiResponse(code = 204, response = String.class, message = "")
})
public Response isUserOfGroup(@PathVariable("group_id") String groupId,
@PathVariable("user_id") String userId) throws BadRequestException {
if(groupService.isUserOfGroup(groupId, userId)) {
return Response.create(javax.ws.rs.core.Response.Status.OK, "");
} else {
return Response.create(javax.ws.rs.core.Response.Status.NO_CONTENT, "");
}
}
--------------------------------------
问题摘要:参数数据类型里面包含抽象数据结构
问题描述:
@RequestMapping(value = "/v3/regions/{region_id}", method = RequestMethod.GET, produces="application/json;charset=UTF-8")
public Map<String, Region> getRegion(@PathVariable("region_id") String regionId)
其中Region类包含字段locales是Map,没有具体类型。
public class Region {
private String id;
private String description;
private String parent_region_id;
private String type;
private Map locales;
private Links links;
错误日志:
解决建议:
这种情况是具体情况修改为具体类型即可,比如Map<String,String>,或者修改为Object。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
liubao682018/11/13 06:34:201楼编辑删除举报
问题描述:
@RequestMapping(value = "/v3/endpoints", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public Map<String, Object> listEndpoint(@RequestMapping(value = "interface", required = false) String inf,
@RequestMapping(value = "service_id", required = false) String serviceId,
HttpServletRequest request) {
参数名称包含"interface", "user.name"等JAVA关键字、“.”等特殊字符。
错误日志:
解决建议:
目前暂时没有解决办法,需要修改参数名称。
liubao682018/11/13 06:46:472楼编辑删除举报
问题描述:存在两个REST接口是重载方法,接口参数列表不同,方法名相同。CSE要求operation id唯一,默认为方法名。
错误日志:
解决建议:可以重命名方法。也可以使用@ApiOperation(value="operationId")给重载方法指定一个不同的名称。
China_RKD2018/11/13 07:00:133楼编辑删除举报
1. 问题描述: 使用swagger 注解 @ApiModelProperty 标识 entity 的时候,慎用 name 属性
错误日志:
解决建议
public class BaeEntity {
// 注意不能写成 @ApiModelProperty 这样生成契约时会直接覆盖掉 id property,使用value 属性添加对id的描述
@ApiModelProperty = "主键id")
private String id;
}
China_RKD2018/11/13 07:09:304楼编辑删除举报
// 错误代码示例, 直接使用 int String long...
@ApiImplicitParams() = "xxx", notes = "xxx", httpMethod = "POST")
@ApiImplicitParams() @ApiImplicitParams() @ApiImplicitParams() = "query", name = "xxx", value = "xxx",dataType = "int"),
@ApiImplicitParams() = "query", name = "xxx", value = "xxx",dataType = "long"),
public ResponseEntity<xx> xx(
@ApiImplicitParams() = "xx") int xx,
@ApiImplicitParams() = "xx") long xx) {
// xxx
}
====
// 代码更正,详情可参考 https://swagger.io/docs/specification/data-models/data-types/
@ApiImplicitParams() = "xxx", notes = "xxx", httpMethod = "POST")
@ApiImplicitParams() @ApiImplicitParams() @ApiImplicitParams() = "query", name = "xxx", value = "xxx",dataType = "integer", format = "int32"),
@ApiImplicitParams() = "query", name = "xxx", value = "xxx",dataType = "integer", format = "int64"),
liubao682018/11/13 07:11:035楼编辑删除举报
问题描述:
@Configuration
public class DemoConfig extends WebMvcConfigurerAdapter {
@Configuration
public public void addInterceptors(InterceptorRegistry registry)
或者
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
错误日志:
解决建议:
这种方式是Spring MVC的方式,CSE提供了类似的方式,CSE有Handler、HttpServerFilter等机制可以替换使用。https://bbs.huaweicloud.com/blogs/02de5f11cb6e11e8bd5a7ca23e93a891介绍了Spring MVC的运行时和CSE的运行时差异. Handler, HttpServerFilter机制开发指南参考: https://docs.servicecomb.io/java-chassis/zh_CN/general-development/http-filter.html 和 https://docs.servicecomb.io/java-chassis/zh_CN/references-handlers/intruduction.html
liubao682018/11/13 13:08:346楼编辑删除举报
问题描述:
@RestController
public class AgencyController
这样的接口定义没有发布为REST接口。
错误日志:
解决建议:
在CSE 2.3.52版本之前,都不会扫描@RestController发布为REST接口
问题描述:
@RestController
public
华为微服务青铜三2018/12/13 08:52:427楼编辑删除举报
很多时候需要接收http的上下文,用来获取浏览器传下来的httpheader或cookie
liubao682019/01/21 02:33:44编辑删除举报
liubao682019/06/29 08:20:078楼编辑删除举报
解答:这个需要对CSE的运行机制有所了解, CSE运行的底座支持Servlet,也支持vert.x http和highway等。 Filter技术只有Servlet容器提供(比如tomcat等),运行于其他底座的时候就无法使用Filter。 但是如果使用tomcat作为底座,比如spring boot,仍然是可以使用的。 例子下面文档中的例子: https://bbs.huaweicloud.com/blogs/b5dfdf9d51bf11e9bd5a7ca23e93a891
vert.x http和spring boot servlet的例子: https://github.com/huaweicse/cse-java-chassis-samples/tree/master/porter
yd_2172151152022/12/20 08:46:229楼编辑删除举报
开发环境:
1. 项目使用了spring boot+spring mvc+mybaits+maven
2. ServiceComb使用2.6.0版本, Controller使用的@RestController,接口使用的public
3. 服务提供方导入java-chassis-spring-boot-starter-servlet,registry-service-center
4. 在ServiceComb的Console已找到服务提供方实例
5. 排除了Spring Securit的自动注入
6. ServiceComb在application中的environment使用的development
7. 下载的CSE未进行任何配置的修改
在各种回答说未将接口注册,但解决方案未提及,请问还需有哪些方面的改动