Why does Value in Spring MVC need an asterisk?

Asked

Viewed 226 times

8

Why do I need to put * no value when there is nothing else? I mean, before using Spring MVC worked smoothly only as /planilha/.

The getPlanilha works properly but if it has the same RequestMethod and consumes will execute the create ? Since you both will have /planilha/QualquerCoisa ONLY because of the asterisk.

@RequestMapping(value = "/planilha/**", method = RequestMethod.POST, consumes = "application/json")
public String create(HttpServletRequest request, @RequestBody String jsonStr) {...}

@RequestMapping(value = "/planilha/{id}", method = RequestMethod.GET)
public String getPlanilha(@PathVariable("id") String id) {...}

According to the documentation:

? More than one Crate
* Zero or more characters
** Matches zero or more 'Directories' in a path.

I understood the functionality but the doubt will run create remains.

2 answers

6


Well, let’s go by part.

Why do I need to put * in value when there’s nothing left?

Actually it doesn’t. You can just leave planilha/ OR planilha, for example. A POST call in http://{host}:{porta}/{contexto}/planilha/ OR http://{host}:{porta}/{contexto}/planilha, respectively, and Content-Type equal to application/json will work.

before using Spring MVC ran smoothly only as /planilha/.

I believe you’re probably referring to Servlets, @WebServlet("/planilha/") or mapping in web.xml, right? Well, see example above =)

The getPlanilha works properly but if it has the same RequestMethod and consumes will execute the create?

For possuir o mesmo RequestMethod e consumes I believe you’re referring to the method create. So, yes, if the HTTP method is POST and exists in the request header a Content-Type=application/json, will be the method create to be called. Why? Because there is no other more specific mapping than it that meets these requirements. If, on the other hand, I had a map like this:

@RequestMapping(value = "/planilha/{id}", method = RequestMethod.POST, consumes = "application/json")
public String newCreate(@PathVariable("id") String id, @RequestBody String jsonStr) {...}

Seria newCreate to be executed as the most specific existing mapping.

To documentation Spring MVC is quite clear on the specificity of URL patterns.

  • The default Mapping Pattern /** is Less specific than any other Pattern. For example /api/{a}/{b}/{c} is more specific.
  • To prefix Pattern such as /public/** is Less specific than any other Pattern that doesn’t contain double wildcards. For example /public/path3/{a}/{b}/{c} is more specific.

You can see more about the patterns used in the matcher used by spring, called AntPathMatcher.

Now, for example, let’s consider some requests based on the mapping of your controller. Consider this:

@Controller
public class PlanilhaController {

    private static final Logger LOGGER = Logger.getLogger(PlanilhaController.class.getName());

    @RequestMapping(value = "/planilha/**", method = RequestMethod.POST, consumes = "application/json")
    public String create(final HttpServletRequest request, @RequestBody final String json) {
        LOGGER.info(String.format("PlanilhaController#create --> called create with json '%s'", json));
        LOGGER.info(String.format("PlanilhaController#create --> called create on path '%s'", request.getRequestURI()));
        return "page";
    }

    @RequestMapping(value = "/planilha/{id}", method = RequestMethod.GET)
    public String getPlanilha(@PathVariable("id") final String id) {
        LOGGER.info(String.format("PlanilhaController#getPlanilha --> called getPlanilha with id '%s'", id));
        return "page";
    }

}
  • Call GET in http://{host}:{porta}/{contexto}/planilha/bruno will produce this log:

    Apr 14, 2015 9:49:55 PM com.brunocesar.controller.PlanilhaController getPlanilha
    INFORMAÇÕES: PlanilhaController#getPlanilha --> called getPlanilha with id 'bruno'
    
  • Call GET in http://{host}:{porta}/{contexto}/planilha/bruno/cesar will produce a HttpRequestMethodNotSupportedException with a log like this:

    Apr 14, 2015 9:50:09 PM com.brunocesar.controller.ControllerErrorHandler processException
    ADVERTÊNCIA: ControllerErrorHandler#processException --> message: 'Request method 'GET' not supported
    
  • Call POST and Content-Type equal to application/json in http://{host}:{porta}/{contexto}/planilha/ will produce log more or less like this:

    Apr 14, 2015 9:50:36 PM com.brunocesar.controller.PlanilhaController create
    INFORMAÇÕES: PlanilhaController#create --> called create with json '{"name":"bruno"}'
    Apr 14, 2015 9:50:36 PM com.brunocesar.controller.PlanilhaController create
    INFORMAÇÕES: PlanilhaController#create --> called create on path '/springmvc-sample/planilha/'
    
  • Call POST and Content-Type equal to application/json in http://{host}:{porta}/{contexto}/planilha will produce log more or less like this:

    Apr 14, 2015 9:51:22 PM com.brunocesar.controller.PlanilhaController create
    INFORMAÇÕES: PlanilhaController#create --> called create with json '{"name":"bruno"}'
    Apr 14, 2015 9:51:22 PM com.brunocesar.controller.PlanilhaController create
    INFORMAÇÕES: PlanilhaController#create --> called create on path '/springmvc-sample/planilha'
    
  • Call POST and Content-Type equal to application/json in http://{host}:{porta}/{contexto}/planilha/bruno will produce log more or less like this:

    Apr 14, 2015 9:52:10 PM com.brunocesar.controller.PlanilhaController create
    INFORMAÇÕES: PlanilhaController#create --> called create with json '{"name":"bruno"}'
    Apr 14, 2015 9:52:10 PM com.brunocesar.controller.PlanilhaController create
    INFORMAÇÕES: PlanilhaController#create --> called create on path '/springmvc-sample/planilha/bruno'
    
  • Call POST and Content-Type equal to application/xml in http://{host}:{porta}/{contexto}/planilha/bruno will produce a HttpMediaTypeNotSupportedException with a log something like this:

    Apr 14, 2015 9:52:45 PM com.brunocesar.controller.ControllerErrorHandler processException
    ADVERTÊNCIA: ControllerErrorHandler#processException --> message: 'Content type 'application/xml' not supported
    

-1

I believe it is just a Web MVC convention. In my view, when making a /planilha/ In Web MVC you can infer that there must be something after the last /, therefore the need to specify how the match will be after the /.

I believe that the most appropriate would be to use only /planilha (without the last /). So by just doing /planilha it will run create and while doing /planilha/QualquerCoisa will make the getPlanilha

  • Well, this can’t be handled so simply. You need to see that the semantics of the maps are different, try to consider this in your answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.