Spring custom web argument resolver

Posted on: September 7th, 2012 by Spade No Comments »

Одна из любимых всеми и крайне удобных возможностей Spring MVC – это механизм data binding. Мы можем выполнить привязку наших объектов к параметрам запроса, хэдерам, кукам и т.д. Иногда, однако, может возникнуть потребность создать собственную привязку, которой по умолчанию в спринге нет. Мы можем с легкостью расширить функциональность data binding своей собственной логикой.

Допустим, нам нужно получать в контроллере IP-адрес пользователя. Его можно достать из запроса, но это потребует лишнего действия, да и врожденное чувство прекрасного внутри нас будет протестовать против такого подхода. А хорошо было бы иметь нечто вроде:

@RequestMapping(value = {"/", "/save"}, method = RequestMethod.POST)
    public String save(@RemoteAddress String address, ...) throws Exception{
    . . . . 
}

Для этого создадим аннотацию RemoteAddress, которая будет “аннотация-маркер”, так как нам не нужно хранить в ней какую-либо информацию.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface RemoteAddress {
}

Чтоб Spring смог автоматически проделать отображение параметра запроса в наш объект, нам нужно описать этот механизм в классе типа WebArgumentResolver:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.context.request.NativeWebRequest;
 
import javax.servlet.http.HttpServletRequest;
 
public class RemoteAddressWebArgumentResolver implements WebArgumentResolver {
 
    private static final Logger log = LoggerFactory.getLogger(RemoteAddressWebArgumentResolver.class);
 
    @Override
    public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception {
 
        RemoteAddress remoteAddress = methodParameter.getParameterAnnotation(RemoteAddress.class);
 
        if (remoteAddress != null) {
            HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();
 
            return request.getRemoteAddr();
        }
        return UNRESOLVED;
    }
}

И добавить его в список argument-resolvers в файле конфига спринга. Стоит обратить внимание, что для такого типа конфигурации требуется версия не ниже 3.1 (http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd):

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="com.acestime.service.RemoteAddressWebArgumentResolver"/>
    </mvc:argument-resolvers>
</mvc:annotation-driven>

Все максимально просто и быстро.

Leave a Reply