catch内部抛出异常,还会执行finally代码块吗
是的,无论catch
块内部是否抛出异常,finally
块中的代码总是会执行。这是Java语言设计的一部分,用于确保一些重要的清理工作(如关闭资源)总是能够执行。
以下是一个示例代码:
public class Main {
public static void main(String[] args) {
try {
System.out.println("In try block");
throw new Exception("Exception in try");
} catch (Exception e) {
System.out.println("In catch block");
throw new RuntimeException("Exception in catch");
} finally {
System.out.println("In finally block");
}
}
}
运行结果将是:
In try block
In catch block
In finally block
Exception in thread "main" java.lang.RuntimeException: Exception in catch
at Main.main(Main.java:9)
...
可以看到,即使catch
块中抛出了新的异常,finally
块中的代码仍然被执行。
@SentinelResource
注解
@SentinelResource
是阿里巴巴开源的流量控制组件 Sentinel 提供的一个注解,用于定义资源并配置流量控制、熔断降级等规则。它可以帮助开发者更方便地在代码中进行流量控制和熔断处理。
以下是 @SentinelResource
注解的主要作用和使用方法:
主要作用
- 定义资源:通过
@SentinelResource
注解可以将某个方法定义为一个受保护的资源,Sentinel 会对该资源进行流量控制和熔断降级。 - 配置流量控制和熔断降级:可以通过注解的属性来配置流量控制和熔断降级的处理逻辑。
- 异常处理:可以指定当资源被限流或熔断时的处理逻辑。
- 降级处理:可以指定当资源被降级时的处理逻辑。
使用方法
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
public class MyService {
@SentinelResource(value = "myResource", blockHandler = "handleBlock", fallback = "handleFallback")
public String myMethod(String param) {
// 业务逻辑
return "Success";
}
// 限流或熔断时的处理逻辑
public String handleBlock(String param, BlockException ex) {
return "Blocked by Sentinel: " + ex.getClass().getSimpleName();
}
// 降级处理逻辑
public String handleFallback(String param, Throwable ex) {
return "Fallback: " + ex.getMessage();
}
}
注解属性
value
:资源名称,必需项。blockHandler
:指定限流或熔断时的处理方法,方法签名需要和原方法一致,并且最后加一个BlockException
参数。fallback
:指定降级处理方法,方法签名需要和原方法一致,并且最后加一个Throwable
参数。blockHandlerClass
:指定blockHandler
方法所在的类,如果不在当前类中定义。fallbackClass
:指定fallback
方法所在的类,如果不在当前类中定义。
通过使用 @SentinelResource
注解,可以方便地对方法进行流量控制和熔断降级处理,提高系统的稳定性和可靠性。
handleBlock
和handleFallback
有什么区别?
handleBlock
和 handleFallback
是 Sentinel 中用于处理不同类型异常的两种方法。它们的主要区别在于处理的场景不同:
handleBlock
- 处理场景:
handleBlock
方法用于处理 限流 或 熔断 导致的异常。 - 异常类型:
handleBlock
方法的最后一个参数必须是BlockException
,这是 Sentinel 用于表示限流或熔断的异常类型。 - 使用场景:当资源被 Sentinel 限流或熔断时,会调用
handleBlock
方法进行处理。
示例:
@SentinelResource(value = "myResource", blockHandler = "handleBlock")
public String myMethod(String param) {
// 业务逻辑
return "Success";
}
public String handleBlock(String param, BlockException ex) {
return "Blocked by Sentinel: " + ex.getClass().getSimpleName();
}
handleFallback
- 处理场景:
handleFallback
方法用于处理 业务异常 或 其他运行时异常。 - 异常类型:
handleFallback
方法的最后一个参数必须是Throwable
,这是 Java 中所有异常的基类。 - 使用场景:当资源方法执行过程中抛出业务异常或其他运行时异常时,会调用
handleFallback
方法进行处理。
示例:
@SentinelResource(value = "myResource", fallback = "handleFallback")
public String myMethod(String param) {
// 业务逻辑
if (param.equals("error")) {
throw new RuntimeException("Business exception");
}
return "Success";
}
public String handleFallback(String param, Throwable ex) {
return "Fallback: " + ex.getMessage();
}
总结
handleBlock
:用于处理 限流 或 熔断 导致的异常,方法签名中需要包含BlockException
参数。handleFallback
:用于处理 业务异常 或 其他运行时异常,方法签名中需要包含Throwable
参数。
@JsonProperty
@JsonProperty
是 Jackson 库中的一个注解,用于在序列化和反序列化过程中指定 JSON 属性的名称。它可以应用于类的字段或方法上,以便在 JSON 和 Java 对象之间进行转换时使用不同的属性名称。
主要作用
- 序列化:将 Java 对象转换为 JSON 时,使用
@JsonProperty
指定的名称作为 JSON 属性名称。 - 反序列化:将 JSON 转换为 Java 对象时,使用
@JsonProperty
指定的名称来匹配 JSON 属性。
使用方法
假设我们有一个 Java 类 Token
,其中包含一个字段 accessToken
,我们希望在 JSON 中将其表示为 access_token
。
示例代码
import com.fasterxml.jackson.annotation.JsonProperty;
public class Token {
@JsonProperty("access_token")
private String accessToken;
// 构造函数
public Token() {}
public Token(String accessToken) {
this.accessToken = accessToken;
}
// Getter 和 Setter
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
序列化示例
将 Java 对象转换为 JSON:
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
Token token = new Token("myAccessToken");
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(token);
System.out.println(jsonString); // 输出: {"access_token":"myAccessToken"}
}
}
反序列化示例
将 JSON 转换为 Java 对象:
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
String jsonString = "{\"access_token\":\"myAccessToken\"}";
ObjectMapper mapper = new ObjectMapper();
Token token = mapper.readValue(jsonString, Token.class);
System.out.println(token.getAccessToken()); // 输出: myAccessToken
}
}
总结
@JsonProperty("access_token")
:用于指定在 JSON 中对应的属性名称为access_token
。- 序列化:将 Java 对象转换为 JSON 时,
accessToken
字段会被序列化为access_token
。 - 反序列化:将 JSON 转换为 Java 对象时,
access_token
属性会被映射到accessToken
字段。
通过使用 @JsonProperty
注解,可以方便地控制 JSON 和 Java 对象之间的属性名称映射,确保数据在传输和存储过程中保持一致性。