百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT精选 > 正文

SpringBoot全局异常处理:如何优雅应对多系统多格式错误响应需求

ccwork 2025-04-10 21:14 10 浏览

SpringBoot全局异常处理:如何优雅应对多系统多格式错误响应需求

引言部分

在微服务架构中,你是否曾为处理不同外部系统的异常响应而头痛?

A系统要求返回JSON格式的:

{code: 1001, message: "错误信息"}

B系统却需要XML格式的:

2001错误描述

而C系统又有其特殊的格式要求...随着接入系统的增加,异常处理代码逐渐变得臃肿不堪,维护成本直线上升。

这种情况在企业级应用中极为常见,尤其是在集成多个第三方系统或提供多渠道API服务时。传统的做法是为每个系统编写定制化的异常处理逻辑,导致代码重复、难以维护且容易出错。

本文将探讨如何利用SpringBoot的能力构建一套灵活的全局异常处理框架,通过一次配置实现多种格式的错误响应,让你的代码更加优雅、可维护。

背景知识

Spring异常处理机制概述

SpringBoot提供了多种异常处理机制,主要包括:

  1. @ControllerAdvice/@RestControllerAdvice - 全局异常处理
  2. @ExceptionHandler - 针对特定异常的处理器
  3. HandlerExceptionResolver接口 - 自定义异常解析器

这些机制允许开发者将异常处理逻辑与业务代码分离,实现统一管理。

多系统集成的异常处理挑战

当需要对接多个外部系统时,异常处理面临以下挑战:

  1. 响应格式多样化 - JSON、XML、自定义文本等
  2. 错误码体系不统一 - 不同系统使用不同的错误码规范
  3. 字段命名差异 - code/errorCode, message/errorMessage/msg等
  4. 内容协商机制 - 根据请求决定响应格式

问题分析

传统异常处理方案的局限性

常见的SpringBoot异常处理方案通常采用以下几种方式:

  1. 单一@RestControllerAdvice + @ExceptionHandler
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity handleException(Exception ex) {
        ErrorResponse errorResponse = new ErrorResponse(1001, ex.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
    }
}

这种方式简单直接,但无法满足多种响应格式的需求。

  1. 多个@RestControllerAdvice按包路径区分
@RestControllerAdvice("「包名称,请自行替换」.system1")
public class System1ExceptionHandler {
    // System1的异常处理
}

@RestControllerAdvice("「包名称,请自行替换」.system2") 
public class System2ExceptionHandler {
    // System2的异常处理
}

这种方式需要为每个系统创建独立的控制器和异常处理器,导致代码重复且难以维护。

  1. 使用内容协商但格式固定
@RestControllerAdvice
public class ContentNegotiationExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity handleException(Exception ex, HttpServletRequest request) {
        MediaType mediaType = MediaType.APPLICATION_JSON;
        // 根据Accept头决定响应格式
        if (request.getHeader("Accept").contains("application/xml")) {
            mediaType = MediaType.APPLICATION_XML;
        }
        
        ErrorResponse error = new ErrorResponse(1001, ex.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .contentType(mediaType)
                .body(error);
    }
}

这种方式虽然支持不同的响应格式,但错误信息的结构是固定的,无法满足不同系统对字段名称和结构的要求。

关键挑战的技术本质

实现多系统异常处理的核心挑战在于:

  1. 异常类型与响应格式的解耦
  2. 响应内容与媒体类型的动态适配
  3. 错误码与业务场景的映射管理
  4. 请求来源识别与响应策略选择

解决方案详解

我们将设计一个灵活的全局异常处理框架,能够根据请求来源和内容类型,动态选择异常处理策略,生成符合目标系统要求的错误响应。

整体架构

核心组件说明

  1. ErrorResponse接口 - 定义错误响应的行为
  2. 具体ErrorResponse实现 - 不同格式的错误响应
  3. ErrorResponseFactory接口 - 定义错误响应创建工厂
  4. 具体Factory实现 - 针对不同系统的工厂实现
  5. ErrorResponseResolver - 根据请求选择合适的工厂
  6. GlobalExceptionHandler - 全局异常处理入口

关键代码实现

首先,定义核心接口和基础实现:

// 错误响应接口
public interface ErrorResponse {
    ResponseEntity toResponseEntity();
}

// JSON格式错误响应
@Data
@AllArgsConstructor
public class JsonErrorResponse implements ErrorResponse {
    private int code;
    private String message;
    private Map data;
    
    @Override
    public ResponseEntity toResponseEntity() {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .contentType(MediaType.APPLICATION_JSON)
                .body(this);
    }
}

// XML格式错误响应
@Data
@AllArgsConstructor
@JacksonXmlRootElement(localName = "error")
public class XmlErrorResponse implements ErrorResponse {
    @JacksonXmlProperty(localName = "code")
    private int code;
    
    @JacksonXmlProperty(localName = "desc")
    private String desc;
    
    @Override
    public ResponseEntity toResponseEntity() {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .contentType(MediaType.APPLICATION_XML)
                .body(this);
    }
}

// 自定义格式错误响应
@Data
@AllArgsConstructor
public class CustomErrorResponse implements ErrorResponse {
    private String errorCode;
    private String errorMessage;
    
    @Override
    public ResponseEntity toResponseEntity() {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .contentType(MediaType.APPLICATION_JSON)
                .body(this);
    }
}

接下来,实现错误响应工厂接口及其实现:

// 错误响应工厂接口
public interface ErrorResponseFactory {
    ErrorResponse createErrorResponse(Exception ex, HttpServletRequest request);
    boolean supports(HttpServletRequest request);
}

// 系统A的错误响应工厂
@Component
public class SystemAErrorResponseFactory implements ErrorResponseFactory {
    
    @Override
    public ErrorResponse createErrorResponse(Exception ex, HttpServletRequest request) {
        int code = 1001; // 默认错误码
        
        // 针对不同异常设置不同错误码
        if (ex instanceof IllegalArgumentException) {
            code = 1002;
        } else if (ex instanceof ResourceNotFoundException) {
            code = 1003;
        }
        
        return new JsonErrorResponse(code, ex.getMessage(), Collections.emptyMap());
    }
    
    @Override
    public boolean supports(HttpServletRequest request) {
        String systemId = request.getHeader("X-System-ID");
        return "SystemA".equals(systemId);
    }
}

// 系统B的错误响应工厂
@Component
public class SystemBErrorResponseFactory implements ErrorResponseFactory {
    
    @Override
    public ErrorResponse createErrorResponse(Exception ex, HttpServletRequest request) {
        int code = 2001; // 系统B的默认错误码
        
        // 针对不同异常设置不同错误码
        if (ex instanceof IllegalArgumentException) {
            code = 2002;
        } else if (ex instanceof ResourceNotFoundException) {
            code = 2003;
        }
        
        return new XmlErrorResponse(code, ex.getMessage());
    }
    
    @Override
    public boolean supports(HttpServletRequest request) {
        String systemId = request.getHeader("X-System-ID");
        return "SystemB".equals(systemId);
    }
}

然后,实现错误响应解析器:

@Component
public class ErrorResponseResolver {
    
    private final List factories;
    
    // 构造函数注入所有工厂实现
    public ErrorResponseResolver(List factories) {
        this.factories = factories;
    }
    
    public ResponseEntity resolve(Exception ex, HttpServletRequest request) {
        // 查找支持当前请求的工厂
        for (ErrorResponseFactory factory : factories) {
            if (factory.supports(request)) {
                ErrorResponse errorResponse = factory.createErrorResponse(ex, request);
                return errorResponse.toResponseEntity();
            }
        }
        
        // 默认错误响应
        JsonErrorResponse defaultResponse = new JsonErrorResponse(
            9999, 
            "Unknown error: " + ex.getMessage(), 
            Collections.emptyMap()
        );
        return defaultResponse.toResponseEntity();
    }
}

最后,实现全局异常处理器:

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    private final ErrorResponseResolver resolver;
    
    public GlobalExceptionHandler(ErrorResponseResolver resolver) {
        this.resolver = resolver;
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity handleException(Exception ex, HttpServletRequest request) {
        return resolver.resolve(ex, request);
    }
    
    // 可以针对特定异常定义专门的处理方法
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity handleResourceNotFoundException(
            ResourceNotFoundException ex, 
            HttpServletRequest request) {
        return resolver.resolve(ex, request);
    }
}

实践案例

下面通过一个完整的示例展示我们的解决方案如何工作。

项目结构

src/
  ├── main/
  │    ├── java/
  │    │    └── 「包名称,请自行替换」/
  │    │         ├── config/
  │    │         │    └── WebConfig.java
  │    │         ├── controller/
  │    │         │    └── DemoController.java
  │    │         ├── exception/
  │    │         │    ├── GlobalExceptionHandler.java
  │    │         │    ├── ErrorResponse.java
  │    │         │    ├── JsonErrorResponse.java
  │    │         │    ├── XmlErrorResponse.java
  │    │         │    ├── CustomErrorResponse.java
  │    │         │    ├── ErrorResponseFactory.java
  │    │         │    ├── SystemAErrorResponseFactory.java
  │    │         │    ├── SystemBErrorResponseFactory.java
  │    │         │    ├── SystemCErrorResponseFactory.java
  │    │         │    └── ErrorResponseResolver.java
  │    │         └── Application.java
  │    └── resources/
  │         └── application.yml
  └── test/
       └── java/
            └── 「包名称,请自行替换」/
                 └── controller/
                      └── DemoControllerTest.java

完整代码实现

Maven依赖:


    
        org.springframework.boot
        spring-boot-starter-web
    
    
        com.fasterxml.jackson.dataformat
        jackson-dataformat-xml
    
    
        org.projectlombok
        lombok
        true
    
    
        org.springframework.boot
        spring-boot-starter-test
        test
    

Web配置类:

package 「包名称,请自行替换」.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        // 配置内容协商
        configurer
            .favorParameter(true)
            .parameterName("format")
            .ignoreAcceptHeader(false)
            .useRegisteredExtensionsOnly(false)
            .defaultContentType(MediaType.APPLICATION_JSON)
            .mediaType("json", MediaType.APPLICATION_JSON)
            .mediaType("xml", MediaType.APPLICATION_XML);
    }
}

异常类:

package 「包名称,请自行替换」.exception;

public class ResourceNotFoundException extends RuntimeException {
    
    public ResourceNotFoundException(String message) {
        super(message);
    }
    
    public ResourceNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}

测试控制器:

package 「包名称,请自行替换」.controller;

import 「包名称,请自行替换」.exception.ResourceNotFoundException;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class DemoController {
    
    @GetMapping("/test/{id}")
    public String test(@PathVariable String id) {
        if ("error".equals(id)) {
            throw new IllegalArgumentException("Invalid ID provided");
        } else if ("notfound".equals(id)) {
            throw new ResourceNotFoundException("Resource not found with ID: " + id);
        }
        return "Success with ID: " + id;
    }
}

自定义系统C错误响应工厂:

package 「包名称,请自行替换」.exception;

import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Component
public class SystemCErrorResponseFactory implements ErrorResponseFactory {
    
    @Override
    public ErrorResponse createErrorResponse(Exception ex, HttpServletRequest request) {
        String errorCode = "ERR-GEN-001";
        
        if (ex instanceof IllegalArgumentException) {
            errorCode = "ERR-VAL-001";
        } else if (ex instanceof ResourceNotFoundException) {
            errorCode = "ERR-RES-001";
        }
        
        return new CustomErrorResponse(errorCode, ex.getMessage());
    }
    
    @Override
    public boolean supports(HttpServletRequest request) {
        String systemId = request.getHeader("X-System-ID");
        return "SystemC".equals(systemId);
    }
}

测试案例

package 「包名称,请自行替换」.controller;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@AutoConfigureMockMvc
public class DemoControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testSystemAJsonError() throws Exception {
        MvcResult result = mockMvc.perform(get("/api/test/error")
                        .header("X-System-ID", "SystemA")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isBadRequest())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$.code").value(1002))
                .andExpect(jsonPath("$.message").value("Invalid ID provided"))
                .andReturn();  // 这里获取返回结果

        // 打印响应内容
        System.out.println("Response Body: " + result.getResponse().getContentAsString());
    }

    @Test
    public void testSystemBXmlError() throws Exception {
        MvcResult result = mockMvc.perform(get("/api/test/notfound")
                        .header("X-System-ID", "SystemB")
                        .accept(MediaType.APPLICATION_XML))
                .andExpect(status().isBadRequest())
                .andExpect(content().contentType(MediaType.APPLICATION_XML))
                .andExpect(xpath("/error/code").string("2003"))
                .andExpect(xpath("/error/desc").string("Resource not found with ID: notfound"))
                .andReturn();  // 这里获取返回结果

        // 打印响应内容
        System.out.println("Response Body: " + result.getResponse().getContentAsString());
    }

    @Test
    public void testSystemCCustomError() throws Exception {
        MvcResult result = mockMvc.perform(get("/api/test/error")
                        .header("X-System-ID", "SystemC")
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isBadRequest())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$.errorCode").value("ERR-VAL-001"))
                .andExpect(jsonPath("$.errorMessage").value("Invalid ID provided"))
                .andReturn();  // 这里获取返回结果

        System.out.println("Response Body: " + result.getResponse().getContentAsString());
    }
}

运行效果

当向系统A发送请求时,得到JSON格式的错误响应:

{
  "code": 1002,
  "message": "Invalid ID provided",
  "data": {}
}

当向系统B发送请求时,得到XML格式的错误响应:


  2003
  Resource not found with ID: notfound

当向系统C发送请求时,得到自定义格式的错误响应:

{
  "errorCode": "ERR-VAL-001",
  "errorMessage": "Invalid ID provided"
}

进阶优化

异常-错误码映射管理

为避免在代码中硬编码错误码,可以采用配置化方式管理异常与错误码的映射关系:

@Component
public class ErrorCodeMappingManager {
    
    // 系统A的错误码映射
    private final Map<Class, Integer> systemAMappings;
    
    // 系统B的错误码映射
    private final Map<Class, Integer> systemBMappings;
    
    // 系统C的错误码映射
    private final Map<Class, String> systemCMappings;
    
    public ErrorCodeMappingManager() {
        // 初始化系统A的错误码映射
        systemAMappings = new HashMap<>();
        systemAMappings.put(IllegalArgumentException.class, 1002);
        systemAMappings.put(ResourceNotFoundException.class, 1003);
        systemAMappings.put(Exception.class, 1001); // 默认错误码
        
        // 初始化系统B的错误码映射
        systemBMappings = new HashMap<>();
        systemBMappings.put(IllegalArgumentException.class, 2002);
        systemBMappings.put(ResourceNotFoundException.class, 2003);
        systemBMappings.put(Exception.class, 2001); // 默认错误码
        
        // 初始化系统C的错误码映射
        systemCMappings = new HashMap<>();
        systemCMappings.put(IllegalArgumentException.class, "ERR-VAL-001");
        systemCMappings.put(ResourceNotFoundException.class, "ERR-RES-001");
        systemCMappings.put(Exception.class, "ERR-GEN-001"); // 默认错误码
    }
    
    public Integer getSystemAErrorCode(Exception ex) {
        return findMostSpecificErrorCode(ex, systemAMappings);
    }
    
    public Integer getSystemBErrorCode(Exception ex) {
        return findMostSpecificErrorCode(ex, systemBMappings);
    }
    
    public String getSystemCErrorCode(Exception ex) {
        return findMostSpecificErrorCode(ex, systemCMappings);
    }
    
    // 查找最匹配的错误码
    private  T findMostSpecificErrorCode(Exception ex, Map<Class, T> mappings) {
        Class exClass = ex.getClass();
        while (exClass != null) {
            if (mappings.containsKey(exClass)) {
                return mappings.get(exClass);
            }
            exClass = exClass.getSuperclass();
        }
        return mappings.get(Exception.class); // 返回默认错误码
    }
}

请求来源识别策略优化

除了使用请求头,还可以通过其他方式识别请求来源:

@Component
public class RequestSourceIdentifier {
    
    // 识别请求来源的方法集合
    private final List<Function> identifierFunctions;
    
    public RequestSourceIdentifier() {
        identifierFunctions = new ArrayList<>();
        
        // 从请求头识别
        identifierFunctions.add(request -> request.getHeader("X-System-ID"));
        
        // 从请求参数识别
        identifierFunctions.add(request -> request.getParameter("systemId"));
        
        // 从请求路径识别
        identifierFunctions.add(request -> {
            String path = request.getRequestURI();
            if (path.startsWith("/api/system-a")) {
                return "SystemA";
            } else if (path.startsWith("/api/system-b")) {
                return "SystemB";
            } else if (path.startsWith("/api/system-c")) {
                return "SystemC";
            }
            return null;
        });
        
        // 从客户端IP识别(示例)
        identifierFunctions.add(request -> {
            String ip = request.getRemoteAddr();
            // 根据IP范围判断系统来源
            // ...
            return null;
        });
    }
    
    public String identifySource(HttpServletRequest request) {
        for (Function function : identifierFunctions) {
            String source = function.apply(request);
            if (source != null && !source.isEmpty()) {
                return source;
            }
        }
        return "default"; // 默认来源
    }
}

基于注解的异常处理

可以通过自定义注解简化异常与错误码的关联:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ErrorInfo {
    String systemA() default "";
    String systemB() default "";
    String systemC() default "";
}

@ErrorInfo(systemA = "1002", systemB = "2002", systemC = "ERR-VAL-001")
public class ValidationException extends RuntimeException {
    // ...
}

配合自定义工厂实现:

@Component
public class AnnotationBasedErrorResponseFactory implements ErrorResponseFactory {
    
    private final String systemId;
    
    public AnnotationBasedErrorResponseFactory(String systemId) {
        this.systemId = systemId;
    }
    
    @Override
    public ErrorResponse createErrorResponse(Exception ex, HttpServletRequest request) {
        ErrorInfo errorInfo = ex.getClass().getAnnotation(ErrorInfo.class);
        String errorCode = "9999"; // 默认错误码
        
        if (errorInfo != null) {
            switch (systemId) {
                case "SystemA":
                    errorCode = errorInfo.systemA();
                    break;
                case "SystemB":
                    errorCode = errorInfo.systemB();
                    break;
                case "SystemC":
                    errorCode = errorInfo.systemC();
                    break;
            }
        }
        
        // 根据系统ID创建不同格式的错误响应
        // ...
    }
    
    @Override
    public boolean supports(HttpServletRequest request) {
        String requestSystemId = request.getHeader("X-System-ID");
        return systemId.equals(requestSystemId);
    }
}

总结与展望

本文介绍了一种灵活的SpringBoot全局异常处理框架,通过工厂模式和策略模式,实现了针对不同系统返回不同格式错误响应的需求。主要特点包括:

  1. 高度解耦 - 异常处理逻辑与业务代码完全分离
  2. 可扩展性强 - 轻松添加新的响应格式和系统适配
  3. 配置灵活 - 支持多种请求来源识别策略
  4. 易于维护 - 错误码集中管理,避免硬编码

未来可以考虑的优化方向:

  1. 基于配置文件的错误码管理 - 将错误码映射关系移至配置文件,支持动态修改
  2. 国际化支持 - 增加多语言错误消息支持
  3. 错误日志与监控集成 - 与日志系统和监控系统集成,提高可观测性
  4. 自定义序列化支持 - 增加更多自定义格式的序列化支持

这种方案特别适用于以下场景:

  1. 多渠道API服务 - 同一API需要服务多个客户端,每个客户端要求不同的错误响应格式
  2. 微服务网关 - 作为不同微服务的统一入口,需要适配不同的错误处理机制
  3. 系统集成项目 - 需要与多个第三方系统集成,每个系统有自己的错误处理规范

通过本文提供的框架,您可以大幅减少异常处理的重复代码,提高系统的可维护性和扩展性,让错误处理不再成为系统集成的痛点。

注意:本文仅供学习参考。

更多文章一键直达:

冷不叮的小知识

相关推荐

二十三、Java类与对象简介(java第十一章类和对象)

在Java编程语言中,类(Class)和对象(Object)是面向对象编程(OOP)的核心概念。描述类类是Java程序的基本组成单元,是对象的模板。类定义了对象的属性和方法。属性是对象的状态信息,而方...

设计模式-结构型-代理模式(proxy)

1.概念需要给对象提供一个代理以控制对该对象的访问,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介;根据代理类生成时机不同,分为静态代理和动态代理;静态代理代理类在编...

深度解析设计模式七大原则之——里氏替换原则

临近端午节,各位读者,你们假期行程安排好了吗?“菜鸟”已经做好决定了,谁都不能阻拦(产品经理也不行),“菜鸟”要好好在家休息三天。最近实在是太累了,一直在疯狂的加班。好了好了言归正传,开始我们的正文。...

Java代理模式详解:智能中介的编程艺术

一、生活场景中的代理思维想象您要租房子,但不想直接与房东打交道,这时房产中介就发挥作用了:1.中介帮您筛选房源(访问控制)2.签约前验证房东资质(预处理)3.协助办理合同手续(功能增强)4.处...

哪个创意最能打动你? 为你欣赏的“创意之星”投一票

这一期的《超级课堂·暑期特别活动》将评出5位“创意之星”,获得价值2000元的奖品。本期我们选登了部分中小学生在昙华林留下的创意作品,欢迎为最能打动你的作品投上一票。大众评审目前采取微信投票:扫描二维...

Netty基础—6.Netty实现RPC服务(netty reactor)

大纲1.RPC的相关概念2.RPC服务调用端动态代理实现3.Netty客户端之RPC远程调用过程分析4.RPC网络通信中的编码解码器5.Netty服务端之RPC服务提供端的处理6.RPC服务调用端实现...

静态代理和动态代理(静态代理和动态代理的优缺点)

1.什么是代理很多人肯定听过和看到过飞机票代理点,火车票代理点。那这些代理点干得事情就是帮航空公司,火车站出售火车票的工作。它们算是一个中间商。实际的服务不是由它们提供。而是由真正的服务商提供。通过这...

Java反射机制与Spring动态代理深度解析

一、Java反射机制原理剖析1.1反射的本质与实现基础Java反射(Reflection)是Java语言的核心特性,允许程序在运行时:动态加载类获取类结构元数据操作类属性和方法关键技术支撑:java...

Java 代理模式详解(java代理原理)

1.代理模式代理模式是一种比较好理解的设计模式。简单来说就是我们使用代理对象来代替对真实对象(realobject)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象...

SpringBoot全局异常处理:如何优雅应对多系统多格式错误响应需求

SpringBoot全局异常处理:如何优雅应对多系统多格式错误响应需求引言部分在微服务架构中,你是否曾为处理不同外部系统的异常响应而头痛?A系统要求返回JSON格式的:{code:1001,mes...

3分钟吃透代理技术!(代理一般都是怎么做)

最近有学员问了我一些问题,什么是代理,又该在什么地方使用。结合之前的讨论,这篇文章我们一起细致的讲解一下关于代理的一些问题。在Java中,代理通常分为两类:静态代理动态代理两者技术实现是不一样的,...

苏州网络维护 | 学习网络维护,从哪入手

我们想要学习网络维护,从哪入手呢?先带大家了解下网络维护1.培养基础知识:建立对计算机网络基本原理的理解。学习计算机网络的基础概念,如IP地址、子网掩码、路由器、交换机、协议等。2.学习网络技术:深入...

CAD如何快速一键编号?(cad如何一次性全部编号)

cad一键自动编号。·第一步,在命令行数abh空格。·第二步,打开自动编号对话框,选择用默认的图言编号,编号文字的高度根据图纸的大小设置零点八。当然如果图纸很大,设置比如十一百的有可能数字编号,这点很...

职场新人必知的10个高效工作法,助你快速升职加薪

初入职场,面对繁杂的工作任务和陌生的职场环境,如何才能快速适应并脱颖而出?以下是10个高效工作法,帮助职场新人提升工作效率,快速实现升职加薪的目标。---1.制定每日工作计划-推荐理由:每天开始...

《魔导英雄传说》新手攻略,快速升级,礼包码,最强阵容排列

《魔导英雄传说》新手攻略一、武将培养指南英雄选择与培养:英雄品质分为SSR、SR、A,优先培养SSR英雄,如张飞、孙尚香等核心英雄阵营搭配:同阵营上阵英雄越多,战力加成越高,建议优先培养同一阵营的英雄...