编辑我添加了更多的细节来帮助别人,并把最初的问题留给了历史
背景--我已经为一个REST调用做了原型,该调用在Spring中返回JSON,它与我的客户端软件一起工作。客户端软件有其查询数据的特定方式。该查询与我的Spring代码不兼容,所以我有几行代码进行了转换。我将转换代码重构为自己的对象。与其在我的REST方法中创建需要它的每一次,我希望在它到达我的方法之前预先填充它。
问题在Spring中,我能让Spring从URL和头中的值中预先填充一个对象,类似于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和报头中的值中填充一个对象,然后将其传递到方法中,而不是在控制器的方法签名处声明它们吗?
编辑:
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;
}
}
我的方法Handler:
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);
}
}
发布于 2013-09-20 20:36:49
这是可能的,但你必须自己做(一次)。
它的接口是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中看到所有这些内容。
相关信息:
发布于 2013-09-20 20:32:57
也许我没有得到你的问题,这不是你想要的,但如果你想要在行动方法中注入所有参数,只需声明如下:
@RequestMapping(method = { RequestMethod.POST })
public ResponseEntity doSomethingCool(@RequestParam Map<String, String> parameters) {
...
}
https://stackoverflow.com/questions/18925236
复制相似问题