How does @RequestParam in Spring handle Guava's Optional?

本小妞迷上赌 提交于 2019-12-20 17:36:25

问题


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

How does Spring's @RequestMapping handle an Optional from Guava library if the parameter value is not required and nothing is sent?

Will it be:

  • Set to null
  • Set to Optional.absent()

Can Optional.fromNullable(T) be used to accept the request?


回答1:


EDIT (October 2015): Spring 4 handles java.util.Optional (from Java 8) out of the box and guarantees that Optional itself is not null, but original question was about Guava's com.google.common.base.Optional which usage as @RequestParam is highly discouraged in this specific case (because it can be null).

ORIGINAL ANSWER (about Guava's Optional):

Don't do that, just use String and let Spring handle null in its way.

Optional<T> is supposed to be used as return value and rarely as a parameter. In this particular case Spring will map missing "name" parameter to null, so even if after implementing custom property editor you'll finish with null check:

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

which is completely unnecessary (and missuses Optional), because it can be achieved with:

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



回答2:


I recommend to use the Java 8 version: java.util.Optional. Look at the Oracle documentation in http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html. Also put a name to the variable, specially if your using Spring 3 or higher:.

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 is very useful for managing optional parametrers, like errors in Spring.




回答3:


The answer on you question will be optional parameter first is setting to null.

In Spring HandlerMethodInvoker I found resolveRequestParam method

    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);
        }
        ...
     }
     ...

So first we check if it is a multipart request. Otherwise we get parameters values by parameter name from servlet request. Finally if parameter value null we check if parameter is required. If required we throw exception, otherwise return null.



来源:https://stackoverflow.com/questions/20237796/how-does-requestparam-in-spring-handle-guavas-optional

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!