Java 向WebMVC端点添加(自定义)解码器
我有一个WebMVC端点:Java 向WebMVC端点添加(自定义)解码器,java,spring,spring-mvc,Java,Spring,Spring Mvc,我有一个WebMVC端点: @RequestMapping(path = "/execution/{id}", method = RequestMethod.POST) public ResponseEntity<...> execute(@PathVariable String id) { ... } 请注意@DecodedIdentifier注释。我知道它不存在,但希望它能解释我的意图。我知道这在Jersey的JAX-RS实现中是可能的,但是Sprin
@RequestMapping(path = "/execution/{id}", method = RequestMethod.POST)
public ResponseEntity<...> execute(@PathVariable String id) {
...
}
请注意@DecodedIdentifier
注释。我知道它不存在,但希望它能解释我的意图。我知道这在Jersey的JAX-RS实现中是可能的,但是Spring的WebMVC呢
在这里,我使用的是base64解码,但我想知道是否也可以插入自定义解码器。尽管您可以使用注释,但我建议您为此使用自定义解码器 按照您的示例,您可以这样做 首先,您需要定义一个适合转换的自定义类。例如:
公共类解码器标识符{
私有最终字符串id;
公共解码器标识符(字符串id){
this.id=id;
}
公共字符串getId(){
返回此.id;
}
}
然后,为自定义类定义一个转换器。它可以执行Base64解码:
公共类DecodedIdentifierConverter实现转换器{
@凌驾
公共解码器标识符转换(字符串源){
返回新的DecodedIdentifier(Base64.getDecoder().decode(source));
}
}
为了向Spring介绍此转换器,您有几个选项
如果您运行的是Spring Boot,那么您所要做的就是将该类注释为@组件
,该组件将负责转换器
的注册
@组件
公共类DecodeDidIdentifierConverter实现转换器{
@凌驾
公共解码器标识符转换(字符串源){
返回新的DecodedIdentifier(Base64.getDecoder().decode(source));
}
}
确保配置组件扫描,以便Spring可以检测类中的@组件注释
如果您使用的是不带Spring Boot的Spring MVC,则需要:
@配置
@EnableWebMvc
公共类WebConfig实现WebMVCConfiguer{
@凌驾
公共void addFormatters(FormatterRegistry注册表){
addConverter(新的DecodedIdentifierConverter());
}
}
注册转换器
后,您可以在控制器中使用它
:
@RequestMapping(path=“/execution/{id}”,method=RequestMethod.POST)
公共响应执行(@PathVariable DecodedIdentifier id){
...
}
您还可以遵循其他选项。请考虑阅读,它将为您提供关于问题的进一步信息。
作为旁注,上面提到的文章指出,您可以在类中直接定义valueOf
方法,该类将存储转换服务的结果,在您的示例中是DecodedIdentifier
,它将允许您摆脱Converter
类:老实说,我从未尝试过这种方法,我不知道在什么条件下它可以工作。话虽如此,如果它有效,它可以简化您的代码。请,如果你认为合适的话,试试看。
更新
感谢@Aman的评论,我仔细阅读了Spring文档。在那之后,我发现,尽管我认为前面提到的转换方法更适合于用例——您实际上正在执行转换——另一个可能的解决方案可能是使用定制
我已经知道Spring使用这种机制来执行多重转换,但我不知道有可能实现答案中提出的最初想法。考虑注释,比如,它非常有意义。事实上,这种方法在Stackoverflow中已有描述(参见中的公认答案)
在您的案例中(基本上是上述案例答案的抄本):
首先,定义DecodedIdentifier
注释:
import java.lang.annotation.Documented;
导入java.lang.annotation.ElementType;
导入java.lang.annotation.Retention;
导入java.lang.annotation.RetentionPolicy;
导入java.lang.annotation.Target;
@记录
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER,ElementType.ANNOTATION_TYPE})
public@interface解码器标识符{
}
事实上,您可以考虑通过包括(例如)处理信息的编码来丰富注释
然后,创建相应的注释FormatterFactory
:
import java.text.ParseException;
导入java.util.Base64;
导入java.util.Collections;
导入java.util.Locale;
导入java.util.Set;
导入org.springframework.context.support.EmbeddedValueResolutionSupport;
导入org.springframework.format.AnnotationFormatterFactory;
导入org.springframework.format.Formatter;
导入org.springframework.format.Parser;
导入org.springframework.format.Printer;
导入org.springframework.stereotype.Component;
@组成部分
公共类DecodeDidIdentifierFormatterFactory扩展了EmbeddedValueResolutionSupport
实现AnnotationFormatterFactory{
@凌驾
公共设置getPrinter(DecodeDidIdentifier注释,类字段类型){
返回此.getFormatter(注释);
}
@凌驾
公共解析器getParser(DecodedIdentifier注释,类fieldType){
返回此.getFormatter(注释);
}
专用格式化程序getFormatter(DecodedIdentifier注释){
返回新格式化程序(){
@凌驾
公共字符串解析(字符串文本、区域设置)引发ParseException{
//如果注释可以提供有关
//若要使用编码,此逻辑将具有高度可重用性
返回新字符串(Base64.getDecoder().decode(text));
}
@凌驾
公共字符串打印(字符串对象、区域设置){
返回对象;
}
};
}
}
在Spring MVC配置中注册工厂:
@配置
@EnableWebMvc
公共类WebConfig实现WebMVCConfiguer{
@凌驾
公共void addFormatters(FormatterRegi
@RequestMapping(path = "/execution/{id}", method = RequestMethod.POST)
public ResponseEntity<...> execute(@PathVariable @DecodedIdentifier String id) {
...
}
public class DecodedIdentifierArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(DecodedIdentifier.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String value = webRequest.getParameterValues(parameter.getParameterName())[0];
return Base64.getDecoder().decode(value);
}
}