Responding to HTTP requests is a complicated process — Spring handles that complexity and exposes
it through simple annotations. Even exceptions get first-class support, via ResponseStatusException
or the @ResponseStatus annotation.
With the core annotations, you can:
- Map HTTP requests to controllers and methods (
@RestController,@RequestMapping) - Specify a base path at the class level (
@RequestMappingon the class) - Declare request types with HTTP-method annotations (
@GetMapping,@PostMapping,@PutMapping,@DeleteMapping) - Access request parameters in a method (
@RequestParam) - Bind data via template variables (
@PathVariable) - Fine-tune the response status code (
@ResponseStatus)
All of these (and ResponseStatusException) come from org.springframework.web.bind.annotation.
Worked example: SuperHeroController
package codecademy;
import java.util.List;import java.lang.Iterable;import java.util.Date;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.PathVariable;
@RestController@RequestMapping("/superHeroes")public class SuperHeroController {
private final SuperHeroRepository superHeroRepository; private final SuperReportRepository superReportRepository;
public SuperHeroController(SuperHeroRepository superHeroRepository, SuperReportRepository superReportRepository) { this.superHeroRepository = superHeroRepository; this.superReportRepository = superReportRepository; }
@GetMapping() public Iterable<SuperHero> getSuperHeros() { Iterable<SuperHero> superHeroes = superHeroRepository.findAll(); return superHeroes; }
@PostMapping(path="/addNew") public String createNewSuperHero(@RequestParam String firstName, @RequestParam String lastName, @RequestParam String superPower) { SuperHero newSuperHero = new SuperHero(firstName, lastName, superPower); superHeroRepository.save(newSuperHero); return "New Super Hero successfully added!"; }
@PostMapping(path="/help") public String postHelp(@RequestParam String postalCode, @RequestParam String streetAddress) { SuperReport newSuperReport = new SuperReport(postalCode, streetAddress, ""); superReportRepository.save(newSuperReport); return "Thanks! Super Heroes have been dispatched to your location!"; }
@GetMapping(path="/heroReport") public Iterable<SuperReport> getHeroReport() { Iterable<SuperReport> superReport = superReportRepository.findAll(); return superReport; }
@PostMapping(path="/{postalCode}") public Iterable<SuperReport> getHeroReportByPostal(@PathVariable String postalCode) { Iterable<SuperReport> superReport = superReportRepository.findByPostalCode(postalCode); return superReport; }}Notice the mix: @RequestParam pulls individual fields off the query string (createNewSuperHero,
postHelp), while @PathVariable binds a value straight out of the URL path
(getHeroReportByPostal).
Second example: TravelAdventuresController
Same annotations, different resource — also demonstrates @RequestBody for accepting a full JSON
object instead of individual params:
package com.codecademy.plants.controllers;import java.util.List;import com.codecademy.plants.entities.Adventure;import com.codecademy.plants.repositories.AdventureRepository;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;
@RestController@RequestMapping("/traveladventures")public class TravelAdventuresController {
private final AdventureRepository adventureRepository;
public TravelAdventuresController(AdventureRepository adventureRepo) { this.adventureRepository = adventureRepo; }
@GetMapping() public Iterable<Adventure> getAdventure() { Iterable<Adventure> adventures = this.adventureRepository.findAll(); return adventures; }
@GetMapping(path = "/bycountry/{country}") public List<Adventure> getByCountry(@PathVariable String country) { return this.adventureRepository.findByCountry(country); }
@GetMapping(path = "/bystate") public List<Adventure> getByState(@RequestParam String state) { return this.adventureRepository.findByState(state); }
@PostMapping() public String addNewAdventure(@RequestBody Adventure adventure) { this.adventureRepository.save(adventure); return "New adventure saved to the repository"; }}