gpt4 book ai didi

java - 在 Spring Controller 方法调用上填充对象

转载 作者:行者123 更新时间:2023-11-30 04:13:52 27 4
gpt4 key购买 nike

编辑我添加了更多详细信息以帮助其他人,并将原始问题留作历史记录

背景 我已经设计了一个 REST 调用原型(prototype),该调用在与我的客户端软件配合使用的 Spring Controller 中返回 JSON。客户端软件有特定的方式来查询数据。该查询与我的 Spring 代码不兼容,因此我用几行代码进行了转换。我将转换代码重构为它自己的对象。我不想在需要它的 REST 方法中每次都创建它,而是希望在它到达我的方法之前预先填充它。

问题在 Spring Controller 中,我可以让 Spring 从 URL 和 header 中的值预填充对象,类似于 Spring 从表单填充对象的方式吗?

当前代码

@RequestMapping(value="", headers = "Accept=application/json", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<String> searchUserProjects(
@RequestParam(required = false) String projectName,
@RequestParam(required = false) String sortBy,
@RequestHeader(value = "Range") String range) {

原始问题我知道在Spring中你可以获取表单的属性并将它们映射到一个对象。另外,我知道你可以将一个字段映射到属性转换器对象,我不记得确切的名称,但我已经做到了。我的问题是,Spring 是否可以从 URL 和 header 中的值填充对象,然后将其传递到方法中,而不是在 Controller 的方法签名处声明它们?

编辑:

applicationContext.xml中的注册方法

<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="app.util.dojo.DojoQueryProcessorHandlerMethodArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>

以及带有参数的处理程序方法

public ResponseEntity<String> searchUserProjects(@RequestParam(required = false) String projectName, @ProcessDojoQuery DojoRestQueryProcessor dojoQueryResults) {

DojoRestQueryProcessor.java

package app.util.dojo;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

public class DojoRestQueryProcessor {

protected String[] rangeArray;
protected String range;
protected String sortBy;
protected int startIndex;
protected int endIndex;

public DojoRestQueryProcessor() {
}
public DojoRestQueryProcessor(String range, String sortBy) {
if (range== null && sortBy == null)
return;
if (range.length() <= 3 || !range.contains("-"))
throw new DojoRestQueryProcessorException("Range value does not meet spec. " + range);
this.rangeArray = range.substring(6).split("-");
this.range = range;
this.sortBy = sortBy;
}

public PageRequest createPageRequest() {
startIndex = Integer.parseInt(rangeArray[0]);
endIndex = Integer.parseInt(rangeArray[1]);
if (startIndex >= endIndex)
throw new IllegalArgumentException("The starting index for a range needs to be less than the end index.");

Sort.Order[] sortOrders = null;
if (sortBy != null && sortBy.length() > 2)
sortOrders = convertDojoSortValuesToSpringSorts(sortBy.split(","));
int pageSize = endIndex-startIndex+1;
int pageNum = ((endIndex+1)/pageSize)-1;
PageRequest pageRequest = null;
if (sortOrders != null)
pageRequest = new PageRequest(pageNum, pageSize, new Sort(sortOrders));
else
pageRequest = new PageRequest(pageNum, pageSize);
return pageRequest;
}

public static Sort.Order[] convertDojoSortValuesToSpringSorts(String[] sortStrings) {
if (sortStrings == null)
return null;
Sort.Order[] sortOrders = new Sort.Order[sortStrings.length];
for (int i = 0; i < sortStrings.length; i++) {
String sortString = sortStrings[i];
if (sortString.startsWith("-")) {
sortOrders[i] = new Sort.Order(Direction.DESC, sortString.substring(1));
} else {
sortOrders[i] = new Sort.Order(Direction.ASC, sortString.substring(1));
}
}
return sortOrders;
}

public int getStartIndex() {
return startIndex;
}

public int getEndIndex() {
return endIndex;
}

public String getRange() {
return range;
}

public String getSortBy() {
return sortBy;
}


}

我的方法处理程序:

package app.util.dojo;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;

public class DojoQueryProcessorHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {


@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(ProcessDojoQuery.class) && parameter.getParameterType().equals(DojoRestQueryProcessor.class) ;
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
throws Exception {
String rangeField = parameter.getParameterAnnotation(ProcessDojoQuery.class).rangeField();
String sortByField = parameter.getParameterAnnotation(ProcessDojoQuery.class).sortByField();

String range = getRangeValue(rangeField, webRequest);
String sortBy = getSortByValue(sortByField, webRequest);
return new DojoRestQueryProcessor(range, sortBy);
}

private String getSortByValue(String rangeField, NativeWebRequest webRequest) {
Map<String, String> pathVariables = getPathVariables(webRequest);
return pathVariables.get(rangeField);
}

private Map<String, String> getPathVariables(NativeWebRequest webRequest) {
HttpServletRequest httpServletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
return (Map<String, String>) httpServletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
}

private String getHeaderValue(String headerName, NativeWebRequest webRequest) {
HttpServletRequest httpServletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
return httpServletRequest.getHeader(headerName);
}

private String getRangeValue(String rangeField, NativeWebRequest webRequest) {
return getHeaderValue(rangeField, webRequest);
}

}

最佳答案

这是可能的,但你必须自己做(一次)。

此接口(interface)为 HandlerMethodArgumentResolver 。我的看法是,您将创建一个注释,例如 @FromUrlAndHeaders 并使用它来注释方法中的参数:

@RequestMapping(value = "/someRequest/path")
public String doBusiness(@FromUrlAndHeaders CustomObject customObject) {
// do business with customObject
}

然后有趣的部分是创建您自己的HandlerMethodArgumentResolver

public class FromUrlAndHeadersHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(FromUrlAndHeaders.class);
}

@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// use the various objects here
// request to get parameters and headers
// mavContainer for model attributes (if you need)
// parameter for class type and annotation attributes
// etc.

// note that the parameter class type matters, are your creating a CustomObject, a String, a DifferentClassObject, etc...
}
}

然后您可以注册此HandlerMethodArgumentResolver并让它工作。

<小时/>

DispatcherServlet 堆栈使用 HandlerMethodArgumentResolver 实现实例列表来决定将哪些参数传递给您的方法。有一个用于 @ModelAttribute@PathVariable@RequestParam@RequestBody ModelMap,对于HttpServletRequest,对于HttpServletResponse,基本上都是默认支持的各个参数类型。您可以在 javadoc 中查看所有内容。

相关:

关于java - 在 Spring Controller 方法调用上填充对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18925236/

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