You can use this article to understand how to use Spring MVC to create websites or RESTful services. And also get an overview of frequently asked questions covering the most common tasks of Spring MVC.
Note: An article of ~ 7,500 words is probably not worth reading on a mobile device. Bookmark it and come back later.
Content
Introduction
What is Spring MVC?
Spring MVC β - Spring. - RESTful (, JSON/XML) Spring, , REST Spring Boot .
, ?
, : .
( , Spring Spring Boot, , Spring Framework?)
HttpServlets 101
- Java Spring (MVC/Boot) , :
- HTML β - HTML-, .
- JSON/XML β - RESTful, JSON XML. Javascript - , .
- , , .
- ? Java?
- Java HttpServlets. HTML, JSON XML. , 1 - Java (Spring MVC, Wicket, Struts) HttpServlets.
( : HttpServlets, .)
HTML- HttpServlets
HttpServlet, HTML-.
package com.marcobehler.springmvcarticle;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyServletV1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
if (req.getRequestURI().equals("/")) {
resp.setContentType("text/html");
resp.getWriter().print("<html><head></head><body><h1>Welcome!</h1><p>This is a very cool page!</p></body></html>");
}
else {
throw new IllegalStateException("Help, I don't know what to do with this url");
}
}
}
.
public class MyServletV1 extends HttpServlet {
Java HttpServlet.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
() GET, doGet () . POST doPost (). HTTP .
if (req.getRequestURI().equals("/")) {
, URL- , . Β«/Β», www.marcobehler.com, www.marcobehler.com/hello.
resp.setContentType("text/html");
ServletResponse, , . HTML.
resp.getWriter().print("<html><head></head><body><h1>Welcome!</h1><p>This is a very cool page!</p></body></html>");
: - β HTML! HTML- ServletResponse. response writer.
, Tomcat Jetty. , , , :
package com.marcobehler.springmvcarticle;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.Tomcat;
public class TomcatApplicationLauncher {
public static void main(String[] args) throws LifecycleException {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.getConnector();
Context ctx = tomcat.addContext("", null);
Wrapper servlet = Tomcat.addServlet(ctx, "myServlet", new MyServletV2());
servlet.setLoadOnStartup(1);
servlet.addMapping("/*");
tomcat.start();
}
}
.
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.getConnector();
Tomcat, 8080.
Context ctx = tomcat.addContext("", null);
Wrapper servlet = Tomcat.addServlet(ctx, "myServlet", new MyServletV2());
Tomcat. , Tomcat .
servlet.addMapping("/*");
Tomcat, , . /* , (/users, /register, /checkout).
tomcat.start();
. main(), 8080 - (http://localhost:8080 /), HTML.
, , doGet () doPost (), - . .
JSON HttpServlets
, ( ) HTML- REST API . React AngularJS URL- :
/api/users/{userId}
JSON userId. MyServlet , , - ?
package com.marcobehler.springmvcarticle;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyServletV2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
if (req.getRequestURI().equals("/")) {
resp.setContentType("text/html");
resp.getWriter().print("<html><head></head><body><h1>Welcome!</h1><p>This is a very cool page!</p></body></html>");
} else if (req.getRequestURI().startsWith("/api/users/")) {
Integer prettyFragileUserId = Integer.valueOf(req.getRequestURI().lastIndexOf("/") + 1);
resp.setContentType("application/json");
resp.getWriter().print("{\n" +
" \"id\":" + prettyFragileUserId + ",\n" +
" \"age\": 55,\n" +
" \"name\" : \"John Doe\"\n" +
"}");
} else {
throw new IllegalStateException("Help, I don't know what to do with this url");
}
}
}
.
} else if (req.getRequestURI().startsWith("/api/users/")) {
if doGet /api/users/.
Integer prettyFragileUserId = Integer.valueOf(req.getRequestURI().lastIndexOf("/") + 1);
URL. URL β userID, , 5 /api/users/5. , int, !
resp.setContentType("application/json");
JSON .
resp.getWriter().print("{\n" +
" \"id\":" + prettyFragileUserId + ",\n" +
" \"age\": 55,\n" +
" \"name\" : \"John Doe\"\n" +
"}");
, JSON β , HTTPServletResponse. , JSON Java- , .
Β« Β»
, :
- HTTP- , URI , .. : .
- , . : , . , .
- JSON HTML .
, ? , ? URI , JSON, ?
Spring MVC.
DispatcherServlet
Spring MVC , Model-View-Controller. .
, Spring MVC β , -?
DispatcherServlet.
( , , , )
Spring MVC DispatcherServlet?
, - Java , Spring MVC , HTTP- ( DispatcherServlet -).
HTTP-, ? Β« Β», HTML .
DispatcherServlet :
- URI HTTP . : POST /register?name=john&age33.
- (/ ) Java REST ,, .
- , .. , , , , .
- HTML/JSON/XML.
, , DispatcherServlet .

. ModelAndView ? DispatcherServlet ?
Let's-write-HTML? .
β HTML
, HTML , Spring MVC ( Spring Boot), . .
Spring
(POST/register?name=john&age33) .
package com.marcobehler.springmvcarticle;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class RegistrationController {
@PostMapping("/register")
public String registerUser(@RequestParam(required = false) Integer age, @RequestParam String name, Model model) {
User user = new User(name, age);
model.addAttribute("user", user);
return "registration-success";
}
}
.
@Controller
public class RegistrationController {
Spring Controller, .
@PostMapping("/register")
DispatcherServlet, , POST /register, (, ?Username=), .
public String registerUser(@RequestParam(required = false) Integer age, @RequestParam String name, Model model) {
, .
, , URL (?age=10&name=Joe), POST. , name ( age )
age, , Integer ( , Integer)
, , Spring MVC model . , , HTML-, .
User user = new User(name, age);
, . , , . -.
model.addAttribute("user", user);
Β«userΒ». , HTML- , , Β«${user.name}Β». .
return "registration-success";
registration-success. , , .. HTML, , Spring .
Views ()
, (, , ) Spring MVC , .. , , registration-success.html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text="'Hello ' + ${user.name} + '!'"></p>
</body>
</html>
HTML-, . , .
<p th:text="'Hello ' + ${user.name} + '!'"></p>
, th:text=? Spring? - ?
: Spring MVC HTML. HTML- , , .
Thymeleaf, Spring MVC.
Spring MVC
, Spring MVC, : Thymeleaf, Velocity, Freemarker, Mustache JSP ( ).
, , , , HTML- β , .
, , , . , ?
ViewResolver?
, Spring HTML-, .
, , ViewResolver. , , Spring ViewResolvers , . ViewResolvers, .
, Thymeleaf. , ThymeleafViewResolver.
package com.marcobehler.springmvcarticle;
import org.springframework.context.annotation.Bean;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
public class ThymeleafConfig {
@Bean
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("classpath:/templates");
templateResolver.setSuffix(".html");
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
}
.
@Bean
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
, ThymeleafViewResolver Spring ViewResolver. (: registration-success), ViewResolvers .
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
ThymeleafViewResolver Thymeleaf . SpringResourceTemplateResolver. .
SpringResourceTemplateResolver Thymeleaf
templateResolver.setPrefix("classpath:/templates");
templateResolver.setSuffix(".html");
, ( Spring Resources): Β« classpath, /templatesΒ». .html. :
, String, registration-success, ThymeleafViewResolver : classpath:/templates/registration-success.html.
: Spring Boot
: , ViewResolver, Spring Boot. . Spring Boot , , spring-boot-starter-thymeleaf.
ViewResolver , src/main/resources/template.
, Spring Boot Spring MVC . .
: Model-View-Controller
Controller & ViewResolver, Spring Model-View-Controller.
- (Controller, @PostMapping, @RequestParam) , .
- ( ), . , .
- β HTML. , (). HTTP-. HTTP- .
.
, , Spring , HTTP, - .
, Spring MVC HTTP.
, HTTP-.
@GetMapping @RequestMappping
@GetMapping . *@RequestMapping*
. :
@GetMapping("/books")
public void book() {
}
@RequestMapping(value = "/books", method = RequestMethod.GET)
public void book2() {
}
@GetMapping, @[Post|Put|Delete|Patch]Mapping @RequestMapping(method=XXX). (Spring 4.3+) () URL, , @RequestMapping , Spring.
@RequestParam
HTTP-, URL (?Key=value) , @RequestParam.
, (, HTTP String int), .
@PostMapping("/users")
public User createUser(@RequestParam(required = false) Integer age, @RequestParam String name) {
}
, 400 Bad Request , Spring Boot, , :
{"timestamp":"2020-04-26T08:34:34.441+0000","status":400,"error":"Bad Request","message":"Required Integer parameter 'age' is not present","path":"/users"}
, Spring @RequestParams - . " ".
, getter/setter.
@PostMapping("/users")
public User createUser(UserDto userDto) {
}
@PathVariable
, URI , @PathVariable. , userId=123, URL: GET / users/123
- , {} .
, PathVariables .
@GetMapping("/users/{userId}")
public User getUser(@PathVariable(required = false) String userId) {
return user;
}
PathVariables, , Java- ( , getter/setter).
@GetMapping("/users/{userId}")
public User getUser(UserDto userDto) {
return user;
}
:
, HTML- Spring MVC :
- , "" . Spring , ( , ) .
- , . .
- , HTML , .
- , , Spring , HTML- .
- , , , Spring Boot , .
.
REST β XML/JSON
RESTFul , -. , -, () JSON XML. , , JSON, , JSON.
, JSON HTTP-.
POST http://localhost:8080/users
{"email": "angela@merkel.de"}
Java ( Spring MVC) JSON . , , . Java, Spring JSON.
public class UserDto {
private String email;
}
, , HTML . RESTful , HTML , JSON.
HTTP β Java Java β HTTP .
, , Spring MVC REST .
REST
, XML/JSON, @RestController Controller. ( @RestController Controller, . FAQ ).
REST- , , :
package com.marcobehler.springmvcarticle;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
@RestController
public class BankController {
@GetMapping("/transactions/{userId}")
public List<Transaction> transactions(String userId) {
List<Transaction> transactions = Collections.emptyList();
return transactions;
}
}
.
@RestController
public class BankController {
BankController @RestController, Spring, HTML- ModelAndView. XML/JSON ( - ) HTTP.
public List<Transaction> transactions(String userId) {
String (). List, Spring JSON XML. , , Java Transaction (- - ):
[
{
"occurred": "28.04.2020 03:18",
"description": "McDonalds - Binging",
"id": 1,
"amount": 10
},
{
"occurred": "28.04.2020 06:18",
"description": "Burger King - Never enough",
"id": 2,
"amount": 15
}
]
Spring MVC , JSON? XML? YAML? REST , ?
Spring .
, , , REST .
? Accept HTTP-.
GET http://localhost:8080/transactions/{userid}
Accept: application/json
Spring MVC Accept : JSON (application/json), List JSON. ( . , Accept .)
, HTTP, .
. .
RESTful API , JSON XML. , REST :
POST http://localhost:8080/users
{"email": "angela@merkel.de"}
Spring , JSON, XML YAML? , , , Content-Type.
POST ...
Content-Type: application/json; charset=UTF-8
...
REST ?
package com.marcobehler.springmvcarticle;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BookingController {
@PostMapping("/transactions")
public Transaction transaction(@RequestBody TransactionDto dto) {
Transaction transaction = null;
return transaction;
}
}
.
public Transaction transaction(@RequestBody TransactionDto dto) {
@RequestParam @Pathvariable, , @RequestBody.
@RequestBody Content-Type Spring , HTTP- Content-Type, : JSON .
Transaction transaction = null;
return transaction;
}
JSON, TransactionDTO, , Transaction, . Spring MVC.
: Spring Accept Content-Type, , Java JSON. XML. .
( / / .)
, Spring MVC , HttpMessageConverters.
HttpMessageConverter?
HttpMessageConverter β ( , , ).
- canRead (MediaType) β (JSON | XML | YAML | . .)? MediaType Content-Type.
- canWrite (MediaType) β (JSON | XML | YAML | . .)? MediaType, , Accept.
- read(Object, InputStream, MediaType) β Java- (JSON | XML | YAML | . .) InputStream
- write(Object, OutputStream, MediaType) β Java- OutputStream (JSON | XML | YAML | . .)
, MessageConverter , MediaTypes (, application/json), / .
HttpMessageConverters?
, . Spring MVC , HTTPMessageConverters β .
, . , Spring AllEncompassingFormHttpMessageConverter ( ).
static {
ClassLoader classLoader = AllEncompassingFormHttpMessageConverter.class.getClassLoader();
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
}
.
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
Spring MVC javax.xml.bind.Binder , , , JAXB.
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
Spring MVC ..jackson..ObjectMapper ..jackson..JsonGenerator , , , Jackson JSON.
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
Spring MVC ..jackson..XmlMapper , , , XML Jackson s XML.
. Spring HttpMessageConverter , «».
if (jaxb2Present && !jackson2XmlPresent) {
addPartConverter(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
addPartConverter(new MappingJackson2HttpMessageConverter());
}
else if (gsonPresent) {
addPartConverter(new GsonHttpMessageConverter());
}
: Spring Boot
Spring Boot Spring MVC . Spring Boot Jackson .
JSON Spring Boot, HttpMessageConverts .
: REST
HTML JSON / XML , Model View.
Java, Spring MVC JSON / XML , HttpMessageConverters.
, :
- .
- Accept Content-Type .
- ?
GitHub:
https://github.com/marcobehler/spring-mvc-article
SpringMvcArticleApplication, -.
Spring MVC Spring Boot?
: , Spring Boot Spring MVC.
Spring Framework?.
Spring MVC?
Spring MVC, Spring Boot .
- : https://start.spring.io/.
- Spring Web .
/ RESTful- Spring MVC.
HTTP- Spring MVC?
Spring MVC , HTTP β .
, JSON, XML HTTP (Multipart) Fileuploads, Spring Java.
HTTP- Spring MVC?
Spring MVC HttpServletResponse β .
HTML, JSON, XML WebSocket. , Java .
REST
- HTML , @ResponseBody , XML / JSON.
- REST , @ResponseBody. @ResponseBody .
@Controller
@ResponseBody
public @interface RestController {
- REST XML / JSON HTML.
. XML JSON β , Spring MVC. / REST - , , YAML. , HttpMessageConverter ApplicationContext.
?
, , Thymeleaf Spring, . , Thymeleaf ( ), , .
404? .
, , JSON XML, @ResponseBody.
Spring 404 Not Found .
package com.marcobehler.springmvcarticle;
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;
@Controller
public class _404WithMissingResponseBodyController {
@GetMapping("/users/{id}")
public User getUser_404(@PathVariable String id) {
return new User("Everyone's name is John", id);
}
@GetMapping("/users2/{id}")
@ResponseBody
public User getUser_200(@PathVariable String id) {
return new User("Everyone's name is John", id);
}
}
: @ResponseBody REST .
, ?
HTTP , .
@PostMapping("/users")
public void method1() {
}
@GetMapping("/users")
publi void method(2) {
}
HTTP , .
@PostMapping("/users")
public void method1() {
}
@PostMapping("/users")
publi void method(2) {
}
IllegalStateException, .
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'howToPassAndRetrieveRequestParametersController' method
com.marcobehler.springmvcarticle.HowToPassAndRetrieveRequestParametersController
to {POST /users3}: There is already 'howToPassAndRetrieveRequestParametersController' bean method
URL @RequestParams?
, Spring URL. :
, , , Β«+Β» , , marco+wantsnospam@marcobehler.com.
@GetMapping("/confirm")
public void confirm(@RequestParam String email, @RequestParam String token){
}
β+β URL - , @RequestParam?
Β«marco[space]wantnospam@marcobehler.comΒ», Spring + , RFC3986.
: , URL-, , : marco%2Bwantsnospam@marcobehler.com, Spring .
HttpSession ?
Spring MVC REST HttpSession , Spring ( , ).
@RestController
public class HttpSessionController {
@GetMapping("/session")
public String getSession(HttpSession httpSession) {
System.out.println("httpSession = " + httpSession);
return httpSession.getId();
}
}
, HttpSession .
@Service
class SomeOtherService {
@Autowired
private HttpSession httpSession;
public HttpSession getHttpSession() {
return httpSession;
}
}
HttpServletRequest?
Spring MVC REST HttpServletRequest , Spring (, )
@RestController
public class HttpServletRequestController {
@Autowired
private SomeRequestService someRequestService;
@GetMapping("/request")
public String getRequest(HttpServletRequest request) {
System.out.println("request = " + request);
return request.toString();
}
}
, HttpServletRequest .
@Service
class SomeRequestService {
@Autowired
private HttpServletRequest httpServletRequest;
public HttpServletRequest getRequest() {
return httpServletRequest;
}
}
HTTP ?
, , . @RequestHeader.
, .
package com.marcobehler.springmvcarticle;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import java.util.Map;
@Controller
public class HttpHeaderController {
@GetMapping("/headers1")
public void singleHeader(@RequestHeader("x-forwarded-for") String xForwardedFor) {
}
@GetMapping("/headers2")
public void headersAsMap(@RequestHeader Map<String,String> headers) {
}
@GetMapping("/headers3")
public void headersAsObject(HttpHeaders headers) {
}
}
cookie?
cookie @CookieValue . cookie HttpServletResponse.
package com.marcobehler.springmvcarticle;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@Controller
public class CookieController {
@GetMapping("/cookie")
public void handle(@CookieValue("JSESSIONID") String cookie, HttpServletResponse response) {
response.addCookie(new Cookie("SOME_COOKIE_NAME", "This is a crazy new cookie!"));
}
}
IP- ?
. httpServletRequest.getRemoteAddr(), , , IP- -, , 99,99% Nginx Apache.
, X-Forwarded-For IP-. , , , CDN, CloudFront? X-Forwarded-For :
X-Forwarded-For: MaybeSomeSpoofedIp, realIp, cloudFrontIp
, , , , X-Forwarded-For. IP-. CloudFront , IP- CloudFront . !
, IP. , !
package com.marcobehler.springmvcarticle;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
public class IpController {
private static final String[] HEADERS_TO_TRY = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"REMOTE_ADDR"};
@GetMapping("/ip")
public String getClientIpAddress(HttpServletRequest request) {
for (String header : HEADERS_TO_TRY) {
String ip = request.getHeader(header);
if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
return getRealClientIpAddress(ip);
}
}
return request.getRemoteAddr();
}
public String getRealClientIpAddress(String ipString) {
String[] manyPossibleIps = ipString.split(",");
for (int i = manyPossibleIps.length - 1; i >= 0; i--) {
String rightMostIp = manyPossibleIps[i].trim();
if (isKnownAddress(rightMostIp)) {
continue;
} else {
return rightMostIp;
}
}
return ipString;
}
private boolean isKnownAddress(String rightMostIp) {
return false;
}
}
Spring MVC?
, HTML-, :
<form method="POST" enctype="multipart/form-data" action="/upload">
File to upload:<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
@PostMapping MultiPartFile, .
package com.marcobehler.springmvcarticle;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@Controller
public class FileUploadController {
@PostMapping("/upload")
public String handleFileUpload(@RequestParam MultipartFile file) throws IOException {
final Path uploadDestination = Paths.get("C:\\uploads").resolve(file.getName());
file.transferTo(uploadDestination);
return "redirect:/";
}
}
(xls, pdf, csv, jpg, zip) Spring ?
, HttpServletResponse byte[] .
, Spring- 'ResponseEntity '. , , .
- β FileSystemResource
- β ClassPathResource
- Β«-Β» β InputStreamResource
- byte[] β ByteArrayResource
, , HTTP- ( , ..).
package com.marcobehler.springmvcarticle;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.server.ResponseStatusException;
import java.io.IOException;
@Controller
public class FileDownloadController {
@RequestMapping(value = "/download/{jpgName}", method = RequestMethod.GET)
public ResponseEntity<Resource> downloadJpg(
@PathVariable String jpgName) throws IOException {
final ClassPathResource downloadResource = new ClassPathResource(jpgName);
if (!downloadResource.exists()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
headers.setContentLength(downloadResource.contentLength());
headers.setContentDispositionFormData("attachment", jpgName);
return new ResponseEntity<>(downloadResource, headers, HttpStatus.OK);
}
}
?
Spring MVC , , .
ControllerAdvice RestControllerAdvice @ResponseStatus @ExceptionHandler. :
- , REST .
- @ResponseStatus HTTP, .
- @ExceptionHandler , -.
- , REST .
package com.marcobehler.springmvcarticle;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.CONFLICT)
@ExceptionHandler(SomeConflictException.class)
public String handleConflict(SomeConflictException e, Model model) {
model.addAttribute("message", e.getMessage());
return "new-template";
}
@ResponseStatus(HttpStatus.NOT_IMPLEMENTED)
@ExceptionHandler(NotYetImplementedExceptoin.class)
public void handleBandwithLimitExceeded(NotYetImplementedExceptoin e) {
}
}
(400, 404 ..) ?
ResponseStatusException , , .
ResponseEntity, .
package com.marcobehler.springmvcarticle;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.server.ResponseStatusException;
@Controller
public class HttpStatusCodeController {
@GetMapping("/somePath")
public void alwaysThrowsException() {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Well, that just wasn't right!");
}
}
XYZ Spring MVC?
Spring MVC , , -.
, , , ViewHandlers, InitBinders, RootContexts, , .., Spring MVC. , .
. , :
- Spring MVC β MVC-, - HTML JSON/XML -.
- , Spring, Spring Boot.
- -, , HTTP- / .
That's all for today. Thanks for reading.
Acknowledgments
Many thanks to Patricio "Pato" Moschcovich , who not only corrected this article, but also gave invaluable feedback!