spring 4 web app
DESCRIPTION
The Web and Spring MVC continue to be one of the most active areas of the Spring Framework with each new release adding plenty of features and refinements requested by the community. Furthermore version 4 added a significant choice for web applications to build WebSocket-style architectures. This talk provides an overview of the areas in which the framework has evolved along with highlights of specific noteworthy features from the most recent releases.TRANSCRIPT
![Page 1: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/1.jpg)
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Spring 4 Web ApplicationsRossen Stoyanchev
@rstoya05
![Page 2: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/2.jpg)
About me
• Spring Framework committer• 598 commits / 143,459 ++ / 95,254 --
• Focus on web applications and Spring MVC
• Spring 4 WebSocket messaging lead
![Page 3: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/3.jpg)
Spring MVC 4.1 update
in context of other recent releases
and related projects
![Page 4: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/4.jpg)
Spring MVC Annotations
• @MVC very popular and evolving through feedback
• Started in 2.5 + REST in 3.0
• Many refinements in 3.1 and 3.2
• WebSocket messaging in 4.0
• Continues to evolve in 4.x
![Page 5: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/5.jpg)
@Controller
• The central component stereotype in Spring MVC
• Contains @RequestMapping methods
• Supporting methods:@ModelAttribute/@InitBinder/@ExceptionHandler
![Page 6: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/6.jpg)
@RestController
• Another component stereotype
• Meta-annotated with @Controller + @ResponseBody
• @ResponseBody “inherited” on method level
• No need to add it, assumed by default
![Page 7: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/7.jpg)
@ControllerAdvice
• Yet another component stereotype
• “Global” supporting methods:@ExceptionHandler, @ModelAttribute, @InitBinder
• Auto-detected, just declare it as a bean
• Fine-grained control @ControllerAdvice(basePackageClasses=MyController.class)
![Page 8: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/8.jpg)
Using @ControllerAdvice
• Global exception handling with error details• ResponseEntityExceptionHandler
• Model attribute preparation• like HandlerInterceptor.preHandle but within @MVC
• Common DataBinder initialization
• ResponseBodyAdvice
![Page 9: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/9.jpg)
ResponseBodyAdvice
• Callback for @ResponseBody / ResponseEntity methods
• Just before the response is written (and committed)• you can still modify headers• or the object to be written to the response
• Two implementations already• JsonViewResponseBodyAdvice• AbstractJsonpResponseBodyAdvice
![Page 10: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/10.jpg)
Jackson @JsonView Support
@RestControllerclass UserController {
@RequestMapping("/user")@JsonView(PublicView.class)public User getUser() { return new User("eric", "7!#H2");}
}
interface PublicView {};
class User {
@PublicViewprivate String username;
private String password;
...
}
![Page 11: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/11.jpg)
JSONP Support
Simply declare as Spring-managed bean:
@ControllerAdviceprivate static class JsonpAdviceextends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {super("callback");
} }
Name of JSONP query param(s)
![Page 12: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/12.jpg)
java.util.Optional method argument (JDK 1.8)
@RestControllerpublic class TestController { @RequestMapping("/test") public void handle(@RequestParam Optional<LocalDate> date) { StringBuilder sb = new StringBuilder("Date: "); date.ifPresent(s -> sb.append(s.toString())); // ... }
}
![Page 13: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/13.jpg)
ListenableFuture return type
• ListenableFuture• together with AsyncRestTemplate
• Supported on @RequestMapping methods in 4.1• return instead of DeferredResult
• Useful in some cases• business service returns ListenableFuture
![Page 14: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/14.jpg)
@ModelAttribute Method Invocation Order
• Invocation respects inter-dependencies in 4.1
@ModelAttribute("foo")public Object getFoo() {
}
@ModelAttribute("bar")public Object getBar(@ModelAttribute("foo") Object foo) {
}
consumes“foo”
produces“foo”
![Page 15: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/15.jpg)
HttpMessageConverter Additions
• Gson• lighter footprint (vs Jackson); used in Spring Android
• Google Protocol Buffers
• effective inter-service communication data protocol
• Jackson / XML• just add jackson-dataformat-xml to classpath
![Page 16: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/16.jpg)
ResponseEntity builder
public ResponseEntity<String> handle() { String body = "Hello World"; HttpHeaders headers = new HttpHeaders() headers.setLocation(location); return new ResponseEntity<String>(body, headers, HttpStatus.CREATED);}
public ResponseEntity<String> handle() { URI location = ...; return ResponseEntity.created(location).body("Hello World");}
BEFORE
AFTER
![Page 17: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/17.jpg)
RequestEntity builder
HttpHeaders headers = new HttpHeaders();headers.setAccept(MediaType.APPLICATION_JSON);HttpEntity httpEntity = new HttpEntity("Hello World", headers);restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);
restTemplate.exchange(
RequestEntity.post(uri).accept(MediaType.APPLICATION_JSON).body("Hello World"), String.class);
BEFORE
AFTER
![Page 18: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/18.jpg)
Link to @RequestMapping / fromMethodCall
// static import MvcUriComponentsBuilder.*
fromMethodCall(on(MyController.class).getAddress("US")).buildAndExpand(1).toUri();
@RequestMapping("/people/{id}/addresses")public class MyController {
@RequestMapping("/{country}")public HttpEntity getAddress(@PathVariable String country) {}
}
![Page 19: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/19.jpg)
@RequestMapping names
• HandlerMethodMappingNamingStrategy
• A default name assigned to all mappings• e.g. class: MyController, method: getAddress• mapping name: “MC#getAddress”
• Mapping names logged on startup at TRACE
• Override default• @RequestMapping(name=”custom-name”)
![Page 20: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/20.jpg)
Link to @RequestMapping / fromMappingName
// static import MvcUriComponentsBuilder.*
fromMappingName("MC#getAddress").arg(0, "US").buildAndExpand(1);
@RequestMapping("/people/{id}/addresses")public class MyController {
@RequestMapping("/{country}")public HttpEntity getAddress(@PathVariable String country) {}
}
![Page 21: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/21.jpg)
Link to @RequestMapping / in views
• mvcUrl function in Spring JSP tag library• shortcut for MvcUriComponentsBuilder.fromMappingName
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<a href="${s:mvcUrl('MC#getAddress) .arg(0, 'US').buildAndExpand(1)}">...</a>
![Page 22: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/22.jpg)
Static Resource Handling
• Major Spring Framework 4.1 feature
• Evolve existing ResourceHttpRequestHandler mechanism
• ResourceResolver and ResourceTransformer chains• arbitrary resolution (version in URL path)
• ResourceUrlProvider • prepare “public” resource URL (e.g. insert version)
![Page 23: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/23.jpg)
“Fingerprinting” URLs (content-based version)
boolean useResourceCache = !this.environment.acceptsProfiles("dev"); VersionResourceResolver resolver = new VersionResourceResolver();resolver.addContentVersionStrategy("/**"); registry.addResourceHandler("/**").addResourceLocations(locations) .resourceChain(useResourceCache).addResolver(resolver);
Example URL:“/css/font-awesome.min-7fbe76cdac.css”
![Page 24: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/24.jpg)
Resource Handling: Comprehensive Strategy
• Much more to discuss• optimization of resources (minify, concatenate)• effective HTTP caching• runtime vs build-time approaches
• Separate talk tomorrow (Wednesday) 8:30 AM
Resource Handling in Spring MVC 4.1Brian Clozel, Rossen Stoyanchev
![Page 25: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/25.jpg)
Groovy Markup Templating
• MarkupTemplateEngine in Groovy 2.3 (XML, XHTML, HTML5)
• DRY markup, Groovy DSL (also see blog post)
yieldUnescaped '<!DOCTYPE html>' html(lang:'en') { head { meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"') title('My page') } body { p('This is an example of HTML contents') } }
![Page 26: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/26.jpg)
Groovy Markup Templating in Spring MVC
• Spring MVC integration
• GroovyMarkupView/ViewResolver/Configurer • similar to FreeMarker and Velocity
![Page 27: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/27.jpg)
New in MVC Java Config: view resolvers
@Configuration@EnableWebMvcpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewResolverRegistry registry) { registry.enableContentNegotiation(new MappingJackson2JsonView()); registry.jsp(); } }
![Page 28: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/28.jpg)
New in MVC Namespace: view resolvers
<mvc:view-resolvers>
<mvc:content-negotiation>
<mvc:default-views>
<bean class="org.springframework.web..MappingJackson2JsonView"/>
</mvc:default-views>
</mvc:content-negotiation>
<mvc:jsp />
</mvc:view-resolvers>
![Page 29: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/29.jpg)
MVC Java Config: enhanced view controllers
@Configuration@EnableWebMvcpublic class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addRedirectViewController("/old/path", "/new/path"); registry.addStatusController("/path", HttpStatus.NOT_FOUND); } }
![Page 30: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/30.jpg)
MVC Namespace: enhanced view controllers
1234
<mvc:redirect-view-controller path="/old" redirect-url="/new" context-relative="false" status-code="308" keep-query-params="true" /> <mvc:status-controller path="/bad" status-code="404" />
![Page 31: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/31.jpg)
WebSocket Support
• Introduced in 4.0
• Foundational WebSocket API
• Transparent SockJS layer• fall back on HTTP streaming or long polling• wide range of browser versions
• Higher-level STOMP messaging• enables @Controller-style programming model
![Page 32: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/32.jpg)
WebSocket Messaging
@Controller
STOMP
WebSocket API
SockJS
websocket / xhr-streaming / eventsource / xhr / ...
spring-messaging
spring-websocket
![Page 33: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/33.jpg)
Example STOMP Message
SENDdestination:/topic/greetingscontent-type:text/plain
Hello world!
COMMANDheader1:value1header2:value2
Body
STOMPFrame
![Page 34: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/34.jpg)
HTTP Requests with Push Notifications
@Controllerpublic class AccountController { @Autowired private SimpMessagingTemplate template; @RequestMapping(value="/accounts", method=RequestMethod.POST) public void save(@Valid Account account) { // ... // notify connected users this.template.convertAndSend("/topic/accounts", account); }
}
![Page 35: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/35.jpg)
@Controller HTTP and WebSocket Processing
@Controllerpublic class PortfolioController { @MessageMapping("/trade") public void executeTrade(Trade trade) { // ... } @RequestMapping(value="/trades/{id}", method=RequestMethod.GET) public Trade getTrade(Integer id) { // ... }
}
![Page 36: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/36.jpg)
Much More on WebSockets
• WebSocket messaging-style, event-driven architecture• very different from REST/HTTP
• There is a lot to consider and learn
• Separate talk today (Tuesday) at 12:45 am
Deep Dive into Spring WebSocketsSergi Almar
![Page 37: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/37.jpg)
• A tool for getting started quickly
• One-stop shop for Spring application development
• Builds on many spring projects• does all the hard work so you don’t have to
• Focused on the 80% common case• more opinionated and more instantly useful• yet remains flexible
Spring Boot
![Page 38: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/38.jpg)
@RestController
@EnableAutoConfiguration
public class Example {
public static void main(String[] args) throws Exception {
SpringApplication.run(Example.class, args);
}
@RequestMapping("/")
public String home() {
return "Hello World!";
}
}
Spring Boot: Up and Running in Minutes!
$ mvn spring-boot:run
![Page 39: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/39.jpg)
• The @MVC programming model you know
• Optimized to be production ready• auto-config, conventions• embedded servlet container, metrics, logging
• Separate talk today (Tuesday) at 2:30 pm
Spring Boot for the Web TierPhil Webb, Dave Syer
Spring Boot for Web Applications
![Page 40: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/40.jpg)
Spring MVC Test Updates
• Assert JSON responses with JSONAssert library• similar to what XMLUnit does for XML
• AsyncRestTemplate client-side support
• MockMvcBuilder "recipes" via MockMvcConfigurer • added to simplify Spring Security setup
![Page 41: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/41.jpg)
HtmlUnit Extension for Spring MVC Test
• Separate Github project spring-test-htmlunit
• Use HtmlUnit, WebDriver, Geb + your Spring MVC Test setup
• See talk tomorrow (Wednesday) at 4:30 pm
The Quest for the Holy Integration TestKen Krueger, Rob Winch
![Page 42: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/42.jpg)
Q & A
![Page 43: Spring 4 Web App](https://reader030.vdocuments.net/reader030/viewer/2022020110/547e7f7fb4af9fda158b5638/html5/thumbnails/43.jpg)
Thank you!