成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Boot 接口響應封裝與國際化、多租戶拓展實戰

開發 前端
?在企業級應用中,構建一個統一、標準、可擴展的接口返回結構,對于前后端協作、異常處理、國際化、多租戶支持等都有重要意義。

在企業級應用中,構建一個統一、標準、可擴展的接口返回結構,對于前后端協作、異常處理、國際化、多租戶支持等都有重要意義。本文基于 Spring Boot 框架,提供一套完整的接口封裝方案,并進一步集成:

  • 通用返回值結構 Result<T>
  • 分頁數據結構 PageResult<T>
  • 國際化消息支持(i18n)
  • 多語言錯誤碼體系
  • 多租戶 traceId 注入機制
  • 全局異常統一處理
  • 自動封裝響應體
  • Swagger 文檔兼容

項目結構總覽

src/
└── main/
    ├── java/
    │   └── com/icoderoad/
    │       ├── common/
    │       │   ├── model/            # Result、PageResult、ErrorCode
    │       │   ├── handler/          # ResponseBodyAdvice & ExceptionHandler
    │       │   ├── i18n/             # 國際化消息工具
    │       │   └── trace/            # traceId / tenantId 線程上下文
    │       └── user/controller/      # 示例業務接口
    └── resources/
        ├── messages.properties
        ├── messages_en.properties
        └── application.yml

統一返回結構:Result

/common/model/Result.java

package com.icoderoad.common.model;


public class Result<T> {
    private int code;
    private String msg;
    private T data;
    private String traceId;


    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.setCode(ErrorCode.SUCCESS.getCode());
        result.setMsg(ErrorCode.SUCCESS.getMessage());
        result.setData(data);
        result.setTraceId(TraceContextHolder.getTraceId());
        return result;
    }


    public static <T> Result<T> failed(ErrorCode errorCode) {
        Result<T> result = new Result<>();
        result.setCode(errorCode.getCode());
        result.setMsg(errorCode.getMessage());
        result.setTraceId(TraceContextHolder.getTraceId());
        return result;
    }


    public Result<T> withMsg(String msg) {
        this.msg = msg;
        return this;
    }


    public Result<T> withCode(int code) {
        this.code = code;
        return this;
    }


    public Result<T> withTraceId(String traceId) {
        this.traceId = traceId;
        return this;
    }


    // Getter & Setter 省略
}

分頁響應結構:PageResult

/common/model/PageResult.java

package com.icoderoad.common.model;


import java.util.List;


public class PageResult<T> {
    private long pageNum;
    private long pageSize;
    private long total;
    private long totalPage;
    private List<T> list;


    public PageResult(long pageNum, long pageSize, long total, List<T> list) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.total = total;
        this.list = list;
        this.totalPage = (long) Math.ceil((double) total / pageSize);
    }


    // Getter & Setter 省略
}

統一錯誤碼定義:ErrorCode 枚舉

/common/model/ErrorCode.java

package com.icoderoad.common.model;


import com.icoderoad.common.i18n.MessageUtils;


public enum ErrorCode {
    SUCCESS(200, "success"),
    FAILED(500, "failed"),
    UNAUTHORIZED(401, "unauthorized"),
    USER_NOT_FOUND(40001, "user.not.found"),
    SYSTEM_ERROR(50001, "system.error");


    private final int code;
    private final String i18nKey;


    ErrorCode(int code, String i18nKey) {
        this.code = code;
        this.i18nKey = i18nKey;
    }


    public int getCode() {
        return code;
    }


    public String getMessage() {
        return MessageUtils.get(i18nKey);
    }
}

國際化支持:MessageUtils 工具類

/common/i18n/MessageUtils.java

package com.icoderoad.common.i18n;


import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import java.util.Locale;


@Component
public class MessageUtils {


    private static MessageSource messageSource;


    @Autowired
    public MessageUtils(MessageSource messageSource) {
        MessageUtils.messageSource = messageSource;
    }


    public static String get(String key, Object... args) {
        Locale locale = LocaleContextHolder.getLocale();
        return messageSource.getMessage(key, args, locale);
    }
}

/resources/messages.properties

success=成功
failed=失敗
unauthorized=未授權
user.not.found=用戶不存在
system.error=系統異常

/common/trace/TraceContextHolder.java

package com.icoderoad.common.trace;


public class TraceContextHolder {
    private static final ThreadLocal<String> TRACE_ID = new ThreadLocal<>();
    private static final ThreadLocal<String> TENANT_ID = new ThreadLocal<>();


    public static void setTraceId(String traceId) {
        TRACE_ID.set(traceId);
    }


    public static String getTraceId() {
        return TRACE_ID.get();
    }


    public static void setTenantId(String tenantId) {
        TENANT_ID.set(tenantId);
    }


    public static String getTenantId() {
        return TENANT_ID.get();
    }


    public static void clear() {
        TRACE_ID.remove();
        TENANT_ID.remove();
    }
}

/common/trace/TraceInterceptor.java

package com.icoderoad.common.trace;


import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;


@Component
public class TraceInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String traceId = UUID.randomUUID().toString().replaceAll("-", "");
        String tenantId = request.getHeader("X-Tenant-ID");
        TraceContextHolder.setTraceId(traceId);
        TraceContextHolder.setTenantId(tenantId != null ? tenantId : "default");
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        TraceContextHolder.clear();
    }
}

自動封裝返回值:ResponseBodyAdvice

/common/handler/GlobalResponseHandler.java

package com.icoderoad.common.handler;


import com.alibaba.fastjson.JSON;
import com.icoderoad.common.model.Result;
import com.icoderoad.common.trace.TraceContextHolder;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;


@RestControllerAdvice
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {


    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return !Result.class.isAssignableFrom(returnType.getParameterType());
    }


    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof String) {
            return JSON.toJSONString(Result.success(body));
        }
        return Result.success(body);
    }
}

統一異常處理

/common/handler/GlobalExceptionHandler.java

package com.icoderoad.common.handler;


import com.icoderoad.common.model.ErrorCode;
import com.icoderoad.common.model.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


@RestControllerAdvice
public class GlobalExceptionHandler {


    @ExceptionHandler(Exception.class)
    public Result<String> handle(Exception e) {
        if (e instanceof BusinessException) {
            return Result.failed(ErrorCode.USER_NOT_FOUND).withMsg(e.getMessage());
        } else if (e instanceof UnauthorizedException) {
            return Result.failed(ErrorCode.UNAUTHORIZED);
        }
        return Result.failed(ErrorCode.SYSTEM_ERROR);
    }
}

Swagger 集成通用返回類型

/common/config/SwaggerConfig.java

package com.icoderoad.common.config;


import com.icoderoad.common.model.Result;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;


@Configuration
public class SwaggerConfig {
    @Bean
    public Docket createApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .genericModelSubstitutes(Result.class)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.icoderoad"))
                .paths(PathSelectors.any())
                .build();
    }
}

使用示例:分頁用戶查詢

@GetMapping("/users")
public Result<PageResult<User>> getUsers(@RequestParam int pageNum, @RequestParam int pageSize) {
    PageInfo<User> pageInfo = userService.getUsers(pageNum, pageSize);
    PageResult<User> pageResult = new PageResult<>(
        pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getList());
    return Result.success(pageResult);
}

總結

特性

實現方案

通用響應結構

Result / PageResult

異常統一封裝

GlobalExceptionHandler

自動響應包裝

ResponseBodyAdvice

國際化支持

MessageSource + messages.properties

錯誤碼多語言

ErrorCode + i18nKey

traceId + 多租戶

攔截器 + ThreadLocal

API文檔兼容

Swagger genericModelSubstitutes


責任編輯:武曉燕 來源: 路條編程
相關推薦

2022-07-27 10:39:14

Spring代碼IDEA

2011-08-29 09:48:30

springMVC

2024-01-04 08:16:34

Spring國際化標準

2011-07-08 11:13:42

Cocoa Touch XCode

2016-03-25 11:18:23

中華網

2020-05-14 18:04:20

Spring BootSaaS平臺

2009-06-25 16:04:30

2010-01-04 13:09:51

Silverlight

2011-05-17 09:39:38

JavaSE

2011-08-19 13:13:14

struts2Java

2009-02-04 15:04:13

2009-12-29 15:05:29

WPF支持國際化

2024-09-04 10:27:53

2010-03-02 16:44:59

CentOS Mono

2010-07-28 14:52:29

Flex國際化

2024-05-17 08:25:06

數據驅動React語言包

2024-01-17 10:16:22

前端國際化消息鍵

2017-01-09 16:24:07

滴滴Android 端 App

2023-01-31 10:29:26

JavaScript國際化國際化庫

2024-08-01 09:10:03

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩av黄色 | 精品亚洲一区二区 | 婷婷色国产偷v国产偷v小说 | 亚洲第一天堂 | 波多野结衣一区二区三区在线观看 | 欧日韩在线| 亚洲精品黑人 | 久久综合狠狠综合久久综合88 | 国产在线一区二区 | 日韩成人在线免费观看 | 一级全黄少妇性色生活免费看 | 中文二区 | 亚洲成人免费视频 | 国产视频一区二区三区四区五区 | 欧美日韩精品在线一区 | 91原创视频在线观看 | 国内自拍偷拍视频 | 久久69精品久久久久久久电影好 | 国产精品久久国产精品久久 | 久草网址| 91在线精品视频 | 亚洲欧美日韩国产综合 | 三极网站 | 日韩有码一区 | 夜夜爽99久久国产综合精品女不卡 | 中文字幕免费在线观看 | 伊人最新网址 | 一区二区三区国产好的精 | 日韩中文字幕一区 | 久久电影一区 | 久久精品亚洲精品 | 国产激情91久久精品导航 | 亚洲福利在线观看 | 自拍偷拍第一页 | 日本一区二区三区视频在线 | 91精品一区二区三区久久久久久 | 国产成人精品免费视频大全最热 | 日韩在线观看中文字幕 | 亚洲444kkkk在线观看最新 | 91在线观看免费视频 | 国产精品资源在线 |