Spring中的@RequestParam如何处理Guava的Optional?

时间:2013-11-27 08:58:48

标签: spring spring-mvc guava nullable optional

@RequestMapping(value = "/contact.html", method = RequestMethod.POST)
public final ModelAndView contact(
        @RequestParam(value = "name", required = false) Optional<String> name) {

如果不需要参数值且没有发送任何内容,Spring的@RequestMapping如何处理来自OptionalGuava library

会不会是:

  • 设为null
  • 设为Optional.absent()

可以Optional.fromNullable(T)用于接受请求吗?

3 个答案:

答案 0 :(得分:47)

编辑(2015年10月): Spring 4处理java.util.Optional(来自Java 8)开箱即用,保证Optional本身不为空,但最初的问题是关于Guava的com.google.common.base.Optional在这种特定情况下非常不鼓励使用@RequestParam(因为它 可以为空)。

原始答案(关于番石榴的Optional):

不要这样做,只需使用String并让Spring处理null

Optional<T>应该用作return value,很少用作参数。在这种特殊情况下,Spring会将缺少的"name"参数映射到null,因此即使在实施自定义property editor后,您也会使用null检查:

@RequestMapping("foo")
@ResponseBody
public String foo(@RequestParam(required = false) final Optional name) {
  return "name: " + (name == null ? "null" : name.get());
}

完全没必要(并且错过了Optional),因为它可以通过以下方式实现:

@RequestMapping("foo")
@ResponseBody
public String foo(@RequestParam(required = false) final String name) {
  return "name: " + (name == null ? "null" : name);
}

答案 1 :(得分:4)

我建议使用Java 8版本:java.util.Optional。查看http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html中的Oracle文档。 还要为变量命名,特别是如果你使用Spring 3或更高版本:。

import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class LoginController
{

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView getLoginPage(@RequestParam(name = "error", required = false) Optional<String> errorMsg)
    {
        //error.ifPresent(LOGGER::debug); //Java 8 with Optional
        return new ModelAndView("login", "error", errorMsg);
    }

}

java.util.Optional对于管理Spring中的 errors 等可选参数非常有用。

答案 2 :(得分:0)

你问题的答案是可选参数首先是设置为null。

在Spring HandlerMethodInvoker中,我找到了resolveRequestParam方法

    Object paramValue = null;
    ...
    if (multipartRequest != null) {
    ...
    // Check if this is multipart request and set paramValue in this case.
    }
    // Otherwise
    if (paramValue == null) {
        String[] paramValues = webRequest.getParameterValues(paramName);
        if (paramValues != null) {
            paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);
        }
    }
    if (paramValue == null) {
       if (defaultValue != null) {
            paramValue = resolveDefaultValue(defaultValue);
        }
        else if (required) {
            raiseMissingParameterException(paramName, paramType);
        }
        ...
     }
     ...

首先我们检查它是否是一个多部分请求。否则,我们从servlet请求中通过参数名称获取参数值。最后,如果参数值为null,我们检查是否需要参数。如果需要,我们抛出异常,否则返回null。