@NameBinding注解名称绑定过滤器/拦截器,只针对某一些资源方法执行处理逻辑
一、为什么要用名称绑定
一般情况下,借助Spring的过滤器或者拦截器等对Http请求或响应进行处理就能满足需求。但是在有些场景下若只需对特定的xxxResource做拦截处理,这个时候使用@NameBinding注解名称绑定指定过滤器或拦截器,就能够对特点资源方法拦截处理。
(但是这种场景下为什么不用切面实现还没搞清楚,欢迎评论区补充!过滤器、拦截器、切面的区别可以参考上篇博客。)
二、案例详解
2.1 导入依赖
@NameBinding注解属于javax.ws.rs的注解,需要导入指定的依赖:
<!-- 扫描Resteasy风格接口必须加此依赖,否则报404-->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-spring-boot-starter</artifactId>
<version>4.4.0.Final</version>
</dependency>
2.2 声明绑定注解
package com.wyw.learn.namebindingvsaop;
import javax.ws.rs.NameBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@NameBinding // 添加该注解后,只需要在接口和拦截器/过滤器添加@NameBindingAnno注解即可绑定接口与拦截器/过滤器的关系
public @interface AddDescForDish {、
}
2.3 注解绑定拦截器/过滤器
该案例中绑定过滤器,注意实现ContainerResponseFilter接口的过滤器需要添加@Provicer注解,该过滤器才可生效;
package com.wyw.learn.namebindingvsaop;
import org.springframework.stereotype.Component;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.util.Arrays;
/**
* @author name: silk
* @version 1.0
* @description: TODO
* @date 2024/4/22 16:48
*/
@Component
@Provider
@AddDescForDish
public class NameBindingResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext req, ContainerResponseContext resp) throws IOException {
Object entity = resp.getEntity();
Class<?> clazz = entity.getClass();
System.out.println("clazz: " + clazz);
Arrays.stream(entity.getClass().getDeclaredFields()).forEach(field -> {
field.setAccessible(true);
if ("description".equals(field.getName())) {
try {
field.set(entity, "这是NameBinding逻辑");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
}
}
2.4 注解绑定接口
该接口必须是RestEasy风格,因为@NameBinding是javax.ws.rs的注解;
package com.wyw.learn.namebindingvsaop;
import com.wyw.learn.excel.Dish;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.math.BigDecimal;
/**
* @author name: silk
* @version 1.0
* @description: TODO
* @date 2024/4/22 16:11
*/
@Path("/nameBinding")
@Component
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@RequiredArgsConstructor
public class NameBindingTestController {
@Path("/nameBinding")
@GET
@AddDescForDish
public Dish testNameBinding() {
Dish dish = new Dish();
dish.setName("糖醋小排");
dish.setPrice(new BigDecimal("100"));
return dish;
}
@Path("/noNameBinding")
@GET
public Dish testNoNameBinding() {
Dish dish = new Dish();
dish.setName("鱼香肉丝");
dish.setPrice(new BigDecimal("200"));
return dish;
}
}
2.5 调用结果