java - Spring Boot 响应过滤器,用于在发送到客户端之前重构 Controller 响应

标签 java spring spring-boot servlets

我有几个 Spring Boot Rest Controller ,我希望将标准 JSON 响应结构发送到客户端。

标准响应将由responseTime、apiResponseCode、status、apiName、response(根据api而有所不同)组成。见下文:

{
"responseTime": "2020-04-19T08:36:53.001",
"responseStatus": "SUCCESS",
"apiResponseCode": "SUCCESS",
"apiName": "PROPERTY_STORE_GET_PROPERTIES",
"response": [
    {
        "propertyName": "app.name",
        "propertyValue": "property-store"
    }
]
}

为了实现这一点,我创建了以下模型类:

package com.example.response.model;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;

public class ApplicationResponse<T> implements Serializable {
   private static final long serialVersionUID = -1715864978199998776L;
   LocalDateTime responseTime;
   Status responseStatus;
   ApiResponseCode apiResponseCode;
   String apiName;
   T response;

   public ApplicationResponse(LocalDateTime responseTime, Status status, 
          ApiResponseCode apiRespCode, String apiName, T response) {
    this.responseTime = responseTime;
    this.responseStatus = status;
    this.apiResponseCode = apiRespCode;
    this.apiName = apiName;
    this.response = response;
}

// getters and setters

为了创建通用响应包装器,我创建了下面的响应 util 类。

import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.response.model.ApplicationResponse;

public class ResponseUtil {
    public static <T> ApplicationResponse<T> createApplicationResponse(String 
         apiName, T response) {
         return new ApplicationResponse<>(LocalDateTime.now(), 
               Status.SUCCESS, ApiResponseCode.SUCCESS, apiName,
               response);
}

private ResponseUtil() {
}
}

现在的问题是我来自 Controller 的响应应该以标准方式序列化。下面显示的是我的 Controller 方法。

package com.example.propertystore.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.exception.ApplicationException;
import com.example.exception.ApplicationExceptionHelper;
import com.example.propertystore.constants.PropertyStoreApiName;
import com.example.propertystore.dto.PropertyDTO;
import com.example.propertystore.entity.Property;
import com.example.propertystore.service.PropertyStoreService;
import com.example.response.ResponseUtil;
import com.example.response.model.ApplicationResponse;

@RestController
public class PropertyStoreControllerImpl implements PropertyStoreController {

@Autowired
PropertyStoreService propertyStoreService;

@Autowired
ApplicationExceptionHelper exceptionHelper;

@Override
public ApplicationResponse<List<PropertyDTO>> getProperties() throws ApplicationException {
    ApplicationResponse<List<PropertyDTO>> response = null;
    try {
        response = ResponseUtil.createApplicationResponse(
            PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(),
                propertyStoreService.getProperties());
    } catch (Exception e) {
        exceptionHelper.raiseApplicationException( HttpStatus.INTERNAL_SERVER_ERROR, Status.FAILURE,
                ApiResponseCode.INTERNAL_SERVER_ERROR,
                PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(), null);
    }
    return response;
}}

在当前的实现中,我需要做的是在我的 Controller 中,我必须通过调用ResponseUtil.createApplicationResponse()来转换响应。这将导致整个 Controller 方法与 createApplicationResponse() 方法调用乱七八糟。

我想探索的是,是否有更简洁的方法使用 servlet 过滤器或 AOP 来实现此目的?

PS:我尝试了过滤选项,但无法理解如何继续操作。在 doFilter() 中检索 response.getOutputStream() 后卡住了。

希望有人能帮忙吗?

最佳答案

只需将所有响应包装到装饰器对象中即可。

class ResponseDecorator<T> {
  //global.fields (time,code, status.....)
  T response;
}

然后将此响应包装器包装到 ResponseEntity

关于java - Spring Boot 响应过滤器,用于在发送到客户端之前重构 Controller 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61292354/

相关文章:

java - 如何获取线程内分配的变量的值?

javascript - Thymeleaf 对象到 Javascript 对象错误 : TemplateProcessingException

java - java注释如何与spring一起工作,它们是在运行时还是在启动时扫描的?

java - Spring 启动 : need to be informed/notified when Web-Server is Up

Java Spring Boot休息服务之争

java - 在 spring boot 测试中使用 wiremock 随机端口设置属性

java - 从 ByteBuffer.array() 解码数据时 BitmapFactory.decodeByteArray 返回 null

java - 如何在Java servlet中获取asp.net创建的cookie?

java - Spring 的带注释的 IOC 对于 Guice 人来说是令人困惑的。帮助启发我

java - 如何在 Spring Boot 中使用 Java 从 JSON 响应中提取特定部分?