Spring MVC 4 - @PathVariable annotation example

Posted on April 9, 2017


Technologies used:   JDK 1.8.0_121 | Spring 4.3.7.RELEASE | Maven 3.3.9 | Apache Tomcat 7.0.47 | Eclipse Neon.3

In Spring MVC, the @PathVariable annotation binds a URI template variable to a method parameter in a controller.

A URI template contains one or more path variables enclosed by braces ({}) as follows.

http://www.example.com/user/{firstName}/{lastName}

When path variables of a URI template are substituted with actual value then it becomes a URI.

http://www.example.com/user/Sunil/Singh

Let’s see a complete example of how to use @PathVariable annotation to bind URI template variables to method parameters in a controller.

Jar dependencies

Add the following jar dependencies in your pom.xml file.

<!-- Spring MVC Dependency -->
  <dependency>
	 <groupId>org.springframework</groupId>
	 <artifactId>spring-webmvc</artifactId>
	 <version>4.3.7.RELEASE</version>
  </dependency>

  <!-- JSTL Dependency -->
  <dependency>
	 <groupId>javax.servlet.jsp.jstl</groupId>
	 <artifactId>javax.servlet.jsp.jstl-api</artifactId>
	 <version>1.2.1</version>
  </dependency>
  <dependency>
	 <groupId>taglibs</groupId>
	 <artifactId>standard</artifactId>
	 <version>1.1.2</version>
  </dependency>

  <!-- Servlet Dependency -->
  <dependency>
	 <groupId>javax.servlet</groupId>
	 <artifactId>javax.servlet-api</artifactId>
	 <version>3.1.0</version>
	 <scope>provided</scope>
  </dependency>

 

Controller class

Create a @Controller class whose handler methods are annotated with @GetMapping annotation and method parameters are annotated with @PathVariable annotation.

Use the @ResponseBody annotation to bind the handler method’s return type to the web response body.

MyController.java

package com.boraji.tutorial.spring.controller;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author imssbora
 */
@Controller
public class MyController {

   /*
    * Binding a URI template variable to a method parameter using 'name' or 'value'
    * attribute of @PathVariable
    */
   @GetMapping("/request1/{name}")
   @ResponseBody
   public String handler(@PathVariable(name = "name") String name) {

      return "URL parameter <br> " 
            + "name =" + name;
   }

   /*
    * Binding URI template variables to method parameters without using 'name' or
    * 'value' attribute of @PathVariable.
    */
   @GetMapping("/request2/{firstName}/{lastName}")
   @ResponseBody
   public String handler(@PathVariable String firstName, @PathVariable String lastName) {

      return "URL parameters - <br>" 
            + " firstName = " + firstName + " <br>" 
            + " lastName = " + lastName;
   }

   /*
    * If method parameter type is not String then Spring automatically converts
    * to the appropriate type such as int, long, float etc.
    */
   @GetMapping("/request3/{name}/{age}/{salary}/{active}")
   @ResponseBody
   public String handler(@PathVariable("name") String name, 
         @PathVariable("age") int age,
         @PathVariable("salary") double salary, 
         @PathVariable("active") boolean active) {

      return "URL parameters - <br>" 
            + " name = " + name + " <br>" 
            + " age = " + age + " <br>" 
            + " salary = " + salary
            + " <br>" + " active = " + active;
   }

   /*
    * Binding all URI template variable to Map
    */
   @GetMapping("/request4/{name}/{age}/address/{city}/{country}")
   @ResponseBody
   public String handler(@PathVariable Map<String, String> params) {

      StringBuilder builder = new StringBuilder();
      builder.append("URL parameters - <br>");
      for (Entry<String, String> entry : params.entrySet()) {
         builder.append(entry.getKey() + " = " + entry.getValue() + "<br>");
      }
      return builder.toString();
   }

   /*
    * Binding date and time URL template variable to LocalDate and LocalTime
    */
   @GetMapping("/request5/{date}/{time}")
   @ResponseBody
   public String handler(
         @DateTimeFormat(pattern = "yyyy-MM-dd") @PathVariable("date") LocalDate date,
         @DateTimeFormat(pattern = "HH:mm:ss") @PathVariable("time") LocalTime time) {

      return "URL parameters - <br>" 
            + " date = " + date + " <br>" 
            + " time = " + time;
   }

   /*
    * Binding URI template variable to array and list
    */
   @GetMapping("/request6/{country}/{city}")
   @ResponseBody
   public String handler(@PathVariable("country") String[] country, 
         @PathVariable("city") List<String> city) {

      return "URL parameters - <br>" 
            + " country = " + Arrays.asList(country) + " <br>" 
            + " city = " + city;
   }
}

 

Spring configuration

Create a web @Configuration class annotated with @EnableWebMvc and @ComponentScan as follows.

WebConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * @author imssbora
 */

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.boraji.tutorial.spring.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {

   @Bean
   public InternalResourceViewResolver resolver() {
      InternalResourceViewResolver resolver = new InternalResourceViewResolver();
      resolver.setViewClass(JstlView.class);
      resolver.setPrefix("/WEB-INF/views/");
      resolver.setSuffix(".jsp");
      return resolver;
   }

}

The @EnableWebMvc enables default Spring MVC configuration and provides the functionality equivalent to <mvc:annotation-driven/> element in XML based configuration.

The @ComponentScan scans the stereotype annotations (@Controller@Service etc...) in a package specified by basePackages attribute.

Servlet container initialization

Create a container initializer class by extending the AbstractAnnotationConfigDispatcherServletInitializer class as follows.

MyWebAppInitializer.java

package com.boraji.tutorial.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * @author imssbora
 */
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] {};
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { WebConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

The AbstractAnnotationConfigDispatcherServletInitializer class, implements the WebApplicationInitializer, is implemented in Servlet 3.0+ environments in order to configure the ServletContext programmatically.

 

Build + Deploy + Run application

Use the following maven commands to build, deploy and run embedded Tomcat server.

mvn clean install  (This command triggers war packaging)

mvn tomcat7:run (This command run embedded tomcat and deploy war file automatically)

You can refer this link to learn how to run the above commands in Eclipse IDE.

 

Type the following URLs in browser's address bar and see output…

1 - http://localhost:8080/request1/Sunil

SpringMVC-PathVariable1.png

2 - http://localhost:8080/request2/Sunil/Singh

SpringMVC-PathVariable2.png

3 - http://localhost:8080/request3/David/45/45000.00/1

SpringMVC-PathVariable3.png

4 - http://localhost:8080/request4/David/45/address/India/Delhi

SpringMVC-PathVariable4.png

5 - http://localhost:8080/request5/2017-04-09/12:15:25

SpringMVC-PathVariable5.png

6 - http://localhost:8080/request6/IND,USA,JPN,UK,AUS/DELHI,JANAN,NEW%20YORK

SpringMVC-PathVariable6.png