0

我正在使用 Spring-mvcContentNegotiatingViewResolver来处理我的响应对象并解析为特定格式。当我从控制器返回对象时,它会添加我的响应对象,但也会添加我用来映射请求参数的对象。我的控制器充当休息控制器。因为我想使用 spring 来创建休息服务ContentNegotiatingViewResolver。调试后,我发现InvocableHandlerMethdod其中invokeForRequest方法包含以下参数的类:

public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
  ...............................................

ModelAndViewContainer参数中包含以下细节:

ModelAndViewContainer: View is [null]; default model {oauthClientDetail=com.netsol.entities.OauthClientDetail@9ac35e, org.springframework.validation.BindingResult.oauthClientDetail=org.springframework.validation.BeanPropertyBindingResult: 0 errors}

我无法弄清楚为什么要OauthClientDetail设置对象ModelAndViewContainer以及如何防止这种情况。

以下是我的控制器代码:

@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
public ApiResponse<UserDetail> changePassword(@Valid OauthClientDetail clientDetail,
        BindingResult bindingResult,
        @RequestParam(value = "password", required = true) String password) {
    logger.info("In changePassword Service...... ");

    if(bindingResult.hasErrors()){
        throw new InvalidRequestException("Error", bindingResult);
    }

    UserDetail detail = userService.changeUserPassword(password, clientDetail, encoder);
    ApiResponse<UserDetail> response = new ApiResponse<UserDetail>();
    if(detail != null){
        response.setErrorCode(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getValue());
        response.setErrorMessage(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getMessage());
        response.setResponse(detail);
    }else{
        response.setErrorCode(CommonUtility.API_RESPONSE_STATUS.FAIL.getValue());
        response.setErrorMessage(CommonUtility.API_RESPONSE_STATUS.FAIL.getMessage());
        response.setResponse(null);
    }
    return response; 
}

rest-servlet.xml 配置:

 bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
    <property name="favorParameter" value="true" />
    <property name="parameterName" value="mediaType" />
    <property name="ignoreAcceptHeader" value="true" />
    <property name="useJaf" value="false" />
    <property name="defaultContentType" value="application/json" />

    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
            <entry key="xml" value="application/xml" />
        </map>
    </property>
</bean>

<bean
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="contentNegotiationManager" ref="contentNegotiationManager" />
    <property name="order" value="1" />
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
            <entry key="xml" value="application/xml" />
            <entry key="html" value="text/html" />
        </map>
    </property>
    <property name="defaultViews">
        <list>
            <bean
                class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />

            <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                <constructor-arg>
                    <bean class="org.springframework.oxm.xstream.XStreamMarshaller">
                        <property name="autodetectAnnotations" value="true" />
                        <property name="aliases">
                            <map>
                                <entry key="list" value="java.util.List" />
                                <entry key="string" value="java.lang.String" />
                                <entry key="hsahmap" value="java.util.HashMap" />
                                <entry key="object" value="java.lang.Object" />
                                <entry key="hashSet" value="java.util.HashSet" />
                            </map>
                        </property>
                        <property name="supportedClasses">
                            <list>
                                <value>java.util.List</value>
                                <value>java.lang.String</value>
                                <value>java.util.Map</value>
                                <value>java.lang.Object</value>
                                <value>java.util.Set</value>
                                <value>java.lang.Long</value>
                                <value>java.util.Date</value>
                            </list>
                        </property>
                    </bean>
                </constructor-arg>
            </bean>
        </list>
    </property>
    <property name="defaultContentType" ref="htmlMediaType" />
    <property name="ignoreAcceptHeader" value="true" />
</bean>

<bean id="htmlMediaType" class="org.springframework.http.MediaType">
    <constructor-arg value="text" />
    <constructor-arg value="html" />
</bean>

我来自 chromepostman客户端的请求:

POST /empirecl-api/api/changePassword HTTP/1.1
Host: localhost:8080
Authorization: Bearer b3f46274-b019-4d7b-a3bd-5c19e9660c2f
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

clientId=my-client-with-secret&clientSecret=12345678&clientSecretConfirm=12345678&password=12345678

我的回应是:

{
"oauthClientDetail": {
    "userId": null,
    "clientId": "my-client-with-secret",
    "additionalInformation": null,
    "authorities": null,
    "authorizedGrantTypes": null,
    "autoapprove": null,
    "clientSecret": "12345678",
    "clientSecretConfirm": "12345678",
    "resourceIds": null,
    "scope": null,
    "webServerRedirectUri": null,
    "createdOn": null,
    "updatedOn": null,
    "active": null,
    "lastLogin": null
},
"apiResponse": {
    "errorCode": 0,
    "errorMessage": "Success",
    "response": {
        "userName": "my-client-with-secret",
        "dateCreated": null,
        "dateUpdated": null,
        "active": "true"
    }
}
}

作为响应,oauthClientDetail对象包含值,我通过请求发送并映射到对象中。由此,我假设我的地图对象是在响应中设置的。我如何防止在响应中设置此对象。

4

1 回答 1

0

我从这个MappingJacksonJsonView 返回顶级 json 对象链接中找到了解决方案。需要@ResponseBody在控制器中添加注解并设置produces={"application/json"}。以下是我的新代码:

 @RequestMapping(value = "/changePassword", method = RequestMethod.POST, produces={"application/json"})
public @ResponseBody ApiResponse<UserDetail> changePassword(@Valid OauthClientDetail clientDetail,
        BindingResult bindingResult,
        @RequestParam(value = "password", required = true) String password) {
    logger.info("In changePassword Service...... ");

    if(bindingResult.hasErrors()){
        throw new InvalidRequestException("Error", bindingResult);
    }

    UserDetail detail = userService.changeUserPassword(password, clientDetail, encoder);
    ApiResponse<UserDetail> response = new ApiResponse<UserDetail>();
    if(detail != null){
        response.setSuccess(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getValue());
        response.setMessage(CommonUtility.API_RESPONSE_STATUS.SUCCESS.getMessage());
        response.setResponse(detail);
    }else{
        response.setSuccess(CommonUtility.API_RESPONSE_STATUS.FAIL.getValue());
        response.setMessage(CommonUtility.API_RESPONSE_STATUS.FAIL.getMessage());
        response.setResponse(null);
    }
    return response; 
}
于 2014-07-30T13:36:19.957 回答