Skip to content

ServletAPI 调用方式

元数据7GA以及之前的模式:

java
<bean id="browser.do" parent="dispatcher" scope="prototype" class="com.primeton.dgs.web.app.browse.BrowseCommand" />

class BrowseCommand {
    //request 由此注入
    public void init(HttpServletRequest request, HttpServletResponse response,
			ServletConfig servletConfig) throws Exception {
		    super.init(request, response, servletConfig);
		    isbssBs = (ISBrowserSysService) getSpringBean(ISBrowserSysService.SPRING_NAME);
	  }
    public void browserSysClassify() throws Exception {
        // 处理请求,相应内容
        String name = request.getParameter("name");  // 获取参数
    }
}

前端调用:

properties
/dgs/browser?invoke=browserSysClassify&name=DGS

问题:

采用VUE前后端分离架构时,传参一般都采用 Payload Parameters(JSON) 的方式,而不是 Query Parameters 的方式。

以 curl 为例,QueryParameter 的方式如下:

shell
curl -X POST  -d 'invoke=browserSysClassify' -d 'name=DGS'  /dgs/browser

PayloadParameter 的方式如下(Payload 的参数时直接传 JSON):

shell
curl -X POST -H 'Content-Type: application/json' \
-d '{"invoke":"browserSysClassify", "name": "DGS"}'  /dgs/browser

RESTFul API

判断 Content-Type 为 application/json 则调用为REST API。

java
BufferedReader reader = request.getReader();
String header = StringUtils.trimToNull(request.getHeader("Content-Type"));
if("application/json".equalsIgnoreCase(header)) {
    String json = IOUtils.toString(reader);
    if(StringUtils.isBlank(json)) {
        json = "{}";
    }
    JSONObject jsonObject = JSON.parseObject(json);
    // 调用 api
}

通过构造一个 Request 的包装类,把 QueryParameter 和 PayloadParameter 的参数合并。元数据接口是通过 request.getParameter("name") 的方式获得参数。这样无论两种参数传递方式,后台都可以获得参数。

java
public class MetaCubeHttpServletRequestWrapper extends HttpServletRequestWrapper {
    /**
     * 元数据部分参数是从 payload 获得的,装饰 RestFull API
     */
    protected final Map<String, Object> payloadParameters = new HashMap<>();

    public MetaCubeHttpServletRequestWrapper(HttpServletRequest request, Map<String, Object> payloadParameters) {
        super(request);
        this.payloadParameters.putAll(payloadParameters);
    }

    @Override
    public String getParameter(String name) {
        String parameter = super.getParameter(name);
        // 获取参数,如果 form 中为空,则从 payload 中获取
        return parameter == null ? (String)payloadParameters.get(name) : parameter;
    }
    @Override
    public String[] getParameterValues(String name) {
        String[] parameterValues = super.getParameterValues(name);
        // 获取参数,如果 form 中为空,则从 payload 中获取
        return parameterValues == null ? new String[]{ (String)payloadParameters.get(name)} : parameterValues;
    }
}

对于包装的 MetaCubeHttpServletRequestWrapper 在调用后台方法时,直接作为 request 参数传递,这样 Servlet 在 getParameter() 时,调用的是 MetaCubeHttpServletRequestWrapper 的结果。

java
HttpServletRequest requestWrapper = new MetaCubeHttpServletRequestWrapper(request, jsonObject);
//获取 bean
AbstractCommand cmd = CommandFactory.getInstance().getCommand(path);
if(cmd != null) {
    cmd.init(requestWrapper, response, getServletConfig());
    next = cmd.execute();
}

对于前端调用,RESTFul URL为:

shell
curl -X POST -H 'Content-Type: application/json' \
-d '{"name": "DGS"}'  /dgs/appsapi/browser/browserSysClassify

原生的调用方式 URL为:

shell
curl -X POST -H 'Content-Type: application/json' \
-d 'name=DGS' /dgs/appsapi/browser/browserSysClassify
# 或
curl -X GET /dgs/appsapi/browser/browserSysClassify?name=DGS

调用的路由参数,都在 URL 中,接口参数,则在 Payload 中。无论何种方式,都可适应。