2013-09-20 4 views
1

Edit я добавил более подробно, чтобы помочь другим и оставил оригинальный вопрос для историиPopulate объект на вызов метода Spring Controller

фона Я прототип REST вызова, который возвращает JSON в Spring Controller, который работает с мое клиентское программное обеспечение. Клиентское программное обеспечение имеет конкретный способ запроса данных. Этот запрос несовместим с моим кодом Spring, поэтому у меня было несколько строк, которые сделали преобразование. Я преобразовал код преобразования в свой собственный объект. Вместо того чтобы создавать каждый раз в моих методах REST, которые его требуют, я хотел бы, чтобы он был предварительно заполнен до того, как он дойдет до моего метода.

Вопрос В контроллере весны я могу установить 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 заполнила объект из значений в URL-адресе и заголовке, а затем передала это в метод вместо того, чтобы объявить их на сигнатуре метода контроллера?

Edit:

Метод регистрации в 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); 
    } 

} 

ответ

2

Возможно, но вам придется делать это самостоятельно (один раз).

Интерфейс для этого 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.

Похожие:

+1

Спасибо за ваш ответ. Мне это очень полезно. – SerotoninChase

+0

Похоже, что это сработает. Я еду прямо сейчас, поэтому завтра буду проверять. – Joe

+0

Я создал код и зарегистрировал его. Во время запуска появляется аргумент resolver. Однако объект создается Spring и не вызывает мой код. Любые мысли о том, как исправить это? – Joe

0

может быть, я не получил свой вопрос, и это не то, что ищете, но если вы хотите, чтобы все параметры должны быть впрыскивается в методе действия, просто объявить его как:

@RequestMapping(method = { RequestMethod.POST }) 
    public ResponseEntity doSomethingCool(@RequestParam Map<String, String> parameters) { 
... 
} 
Смежные вопросы