gpt4 book ai didi

java - Spring:HandlerMethodArgumentResolved 不适用于自定义注释参数

转载 作者:行者123 更新时间:2023-12-02 09:28:05 26 4
gpt4 key购买 nike

我已经在互联网上搜索了几个小时,并尝试了我找到的解决方案,以便在 Controller 方法上使用自定义参数注释。

这背后的想法是,我想练习在使用 spring 时如何使用自定义注释来映射请求、响应和各种事物。

所以我想要的是创建一个注释参数,它应该创建一个 Map 实例,我的界面是这样编码的:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SearchCriteria {
String value() default "";
}

解析器:

public class SearchCriteriaResolver implements HandlerMethodArgumentResolver {
private Logger log = LoggerFactory.getLogger(SearchCriteriaResolver.class);

private Map<String, Object> parameters = new HashMap<>() {{
put("name", "");
put("limit", 10);
}};

@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(SearchCriteria.class);
}

@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();

log.info("Parameter test: " + request.getParameter("test"));

return this.parameters;
}
}

配置器:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new SearchCriteriaResolver());
}
}

我在互联网上多次发现处理程序是这样创建的。所以在 Controller 中,我使用这样的注释:

@RestController
@RequestMapping("/series")
public class SeriesController {
private static final Logger log = LoggerFactory.getLogger(SeriesController.class);

@Autowired
SeriesService seriesService;

@GetMapping
public ResponseEntity<List<SeriesBatch>> getSeriesList(@SearchCriteria Map<String, Object> parameters) {
log.info("GET /series/ -> getSeriesList");
log.info(parameters.toString());

List<SeriesBatch> seriesList = this.seriesService.findAll();

return new ResponseEntity<>(seriesList, HttpStatus.OK);
}

...
}

所以每次触发此端点时我都会检查日志,但解析器上的日志不会被触发,并且 Controller 方法中的日志仅显示一个空对象。我已经调试了应用程序开始,以查看是否正在调用 resolvers.add ,确实如此,但由于某种我不知道的原因,该注释的逻辑没有被执行。

注意:我正在学习 spring 并在很长一段时间后收回JAVA,所以如果能解释为什么它必须是这样的,我将不胜感激答案已给出。

最佳答案

重构您的代码,将您存储在java.util.Map中的数据之前的实例现在将存储在其他一些对象中,例如自定义类的实例 SearchParams 。您甚至可以将 map 包装为该类中的成员,以暂时保持简单:

class SearchParams {

private Map<String, Object> values = new HashMap<>();

public void setValue(String key, Object value) {
this.values.put(key, value);
}

public Object getValue(String key) {
this.values.get(key);
}

public Map<String, Object> list() {
return new HashMap<>(this.values);
}
}

现在更改您的 Controller 方法以接受 SearchParams对象而不是 Map<String, Object> :

    public ResponseEntity<List<SeriesBatch>> getSeriesList(@SearchCriteria SearchParams parameters) { ... }

最后但并非最不重要的一点是,你必须更改你的 @SearchCriteria注释实现,例如如下:

public class SearchCriteriaResolver implements HandlerMethodArgumentResolver {

@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(SearchCriteria.class);
}

@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {

// somehow determine search params

// setup + return your new SearchParams object to encapsulate your determined search params
SearchParams searchParams = new SearchParams();
searchParams.add("somekey", "somevalue");
return searchParams;
}
}

现在,请尝试一下,如果效果很好请告诉我;-)

详细说明:

看看 Spring 的 org.springframework.web.method.support.HandlerMethodArgumentResolverComposite类,尤其是 getArgumentResolver(MethodParameter parameter)方法。在底层,Spring 维护着一个不同的列表 HandlerMethodArgumentResolver实例并循环它们以找到与给定方法参数匹配的实例(然后将方法参数的值映射到某个其他对象!)。已注册的 HandlerMethodArgumentResolvers 之一的类型为 org.springframework.web.method.annotation.MapMethodProcessor 。如果参数 if 类型为 java.util.Map,MapMethodProcessor 也会匹配并首先匹配(参见下面所附的屏幕截图)。这就是为什么您的自定义 HandlerMethodArgumentResolver 从未被调用...

enter image description here

[[https://reversecoding.net/spring-mvc-requestparam-binding-request-parameters/]]显示了一个示例,其中 java.util.Map用作 Controller 方法的参数 -> 搜索 '7. @RequestParam 与 map '

配置顺序/更改自定义任意优先级的可能方法 HandlerMethodArgumentResolverWebConfig配置类:

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
// add custom resolver to beginning of resolver list
resolvers.add(0, new SearchCriteriaResolver());
}

关于java - Spring:HandlerMethodArgumentResolved 不适用于自定义注释参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58193500/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com