All the code can be found on it's github repository.
The build file
The most important parts are the repositories section and the dependencies section. The repositories section defines where to find the dependencies of your project designated in the dependencies section. In this case we can get everything from Maven central. The ext section defines some variables used for the specific versions of your dependencies. The buildscript section allows us to add functionality into gradle. In this case we are adding a tomcat plugin so we can launch a tomcat instance directly from the gradle build.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply plugin: "eclipse" | |
apply plugin: "idea" | |
apply plugin: "war" | |
apply plugin: "tomcat" | |
war { baseName='hello-world' } | |
sourceCompatibility = 1.7 | |
buildscript { | |
repositories { | |
jcenter() | |
} | |
dependencies { classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.0' } | |
} | |
repositories { | |
mavenCentral() | |
} | |
ext { | |
jacksonVersion="2.2.3" | |
springVersion="4.0.1.RELEASE" | |
tomcatVersion="7.0.50" | |
} | |
dependencies { | |
providedCompile "javax.servlet:javax.servlet-api:3.1.0", "javax.servlet.jsp:jsp-api:2.1" | |
runtime ("javax.servlet:jstl:1.2") { | |
exclude group: "javax.servlet", module: "javax.servlet-api" | |
exclude group: "javax.servlet", module: "jsp-api" | |
} | |
compile "org.springframework:spring-context:$springVersion" | |
compile "org.springframework:spring-core:$springVersion" | |
compile "org.springframework:spring-web:$springVersion" | |
compile "org.springframework:spring-webmvc:$springVersion" | |
compile "com.fasterxml.jackson.core:jackson-core:$jacksonVersion" | |
compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" | |
compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" | |
testCompile "junit:junit:4.11" | |
testCompile "org.springframework:spring-test:$springVersion" | |
tomcat "org.apache.tomcat.embed:tomcat-embed-core:$tomcatVersion", | |
"org.apache.tomcat.embed:tomcat-embed-logging-juli:$tomcatVersion" | |
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:$tomcatVersion") { | |
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj' | |
} | |
} |
The Configuration
We will be using a completely XML-less configuration. This requires a server that supports servlet 3.0 and above. This means >= Tomcat 7 or >= Jetty 8. Major takeaway is that we will put our controller in the com.hello.controller package so we need to scan that package.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.hello; | |
import org.springframework.context.annotation.ComponentScan; | |
import org.springframework.context.annotation.Configuration; | |
@Configuration | |
@ComponentScan(basePackages = { "com.hello.controller", "com.hello.config" }) | |
public class AppConfig { | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.hello.config; | |
import javax.servlet.Filter; | |
import javax.servlet.ServletRegistration.Dynamic; | |
import org.springframework.web.filter.CharacterEncodingFilter; | |
import org.springframework.web.filter.HiddenHttpMethodFilter; | |
import org.springframework.web.filter.HttpPutFormContentFilter; | |
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; | |
import com.hello.AppConfig; | |
import com.hello.WebConfig; | |
public class ServletInitializer extends | |
AbstractAnnotationConfigDispatcherServletInitializer { | |
@Override | |
protected Class<?>[] getRootConfigClasses() { | |
return new Class[] { AppConfig.class }; | |
} | |
@Override | |
protected Class<?>[] getServletConfigClasses() { | |
return new Class[] { WebConfig.class }; | |
} | |
@Override | |
protected String[] getServletMappings() { | |
return new String[] { "/" }; | |
} | |
@Override | |
protected void customizeRegistration(Dynamic registration) { | |
registration.setInitParameter("dispatchOptionsRequest", "true"); | |
} | |
@Override | |
protected Filter[] getServletFilters() { | |
CharacterEncodingFilter charFilter = new CharacterEncodingFilter(); | |
charFilter.setEncoding("UTF-8"); | |
charFilter.setForceEncoding(true); | |
return new Filter[] { new HiddenHttpMethodFilter(), charFilter, | |
new HttpPutFormContentFilter() }; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.hello; | |
import org.springframework.context.annotation.ComponentScan; | |
import org.springframework.context.annotation.Configuration; | |
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; | |
import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; | |
@EnableWebMvc | |
@Configuration | |
@ComponentScan(basePackages = "com.hello.controller") | |
public class WebConfig extends WebMvcConfigurerAdapter { | |
@Override | |
public void configureDefaultServletHandling( | |
DefaultServletHandlerConfigurer configurer) { | |
configurer.enable(); | |
} | |
} |
The Controller
Spring 4 introduced a new controller annotation @RestController. This is just a convenience annotation that means the class is an @Controller class and all the methods are @ResponseBody methods. This is a nice addition when building out REST webservices using Spring MVC.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.hello.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.bind.annotation.RestController; | |
@RestController | |
@RequestMapping("/hello") | |
public class HelloController { | |
@RequestMapping(method = RequestMethod.GET, value = "/{name}") | |
public String sayHello(@PathVariable("name") String name) { | |
return name + " from the server"; | |
} | |
} |
The view
We are using AngularJS to interact with our controller. The way most of the webapps I've been writing lately work is having a Java backend provide a REST webservice to a javascript frontend. There are pros and cons to this approach which can be debated but I've been having fun and been productive using this method.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*jshint unused: false */ | |
/*global angular:true */ | |
// Declare app level module | |
var App = angular.module('App', []); | |
(function() { | |
'use strict'; | |
App.controller("HelloCtrl", ['$scope', '$http', | |
function($scope, $http) { | |
$scope.name = "User"; | |
$scope.message = ""; | |
$scope.getName = function() { | |
$http.get('hello/' + $scope.name).then(function(response) { | |
$scope.message = "Hello " + response.data; | |
}); | |
}; | |
} | |
]); | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html ng-app="App"> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Hello</title> | |
</head> | |
<body ng-controller="HelloCtrl"> | |
<input type="text" ng-model="name"></input><button ng-click="getName()">Submit</button> | |
<div>{{message}}</div> | |
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.js"></script> | |
<script src="js/app.js"></script> | |
</body> | |
</html> |
The Controller Test
Spring has really nice support for testing your controllers as well.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.hello.controller; | |
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | |
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; | |
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; | |
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | |
import org.junit.Before; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.http.MediaType; | |
import org.springframework.test.context.ContextConfiguration; | |
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | |
import org.springframework.test.context.web.WebAppConfiguration; | |
import org.springframework.test.web.servlet.MockMvc; | |
import org.springframework.test.web.servlet.setup.MockMvcBuilders; | |
import org.springframework.web.context.WebApplicationContext; | |
import com.hello.AppConfig; | |
import com.hello.WebConfig; | |
@RunWith(SpringJUnit4ClassRunner.class) | |
@WebAppConfiguration | |
@ContextConfiguration(classes = { AppConfig.class, WebConfig.class }) | |
public class HelloControllerTest { | |
@Autowired | |
private WebApplicationContext wac; | |
private MockMvc mockMvc; | |
@Before | |
public void setup() throws Exception { | |
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); | |
} | |
@Test | |
public void helloTest() throws Exception { | |
String name = "Test"; | |
mockMvc | |
.perform(get("/hello/{name}", name).accept(MediaType.APPLICATION_JSON)) | |
.andDo(print()) | |
.andExpect(status().isOk()) | |
.andExpect( | |
content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) | |
.andExpect(content().string(name + " from the server")); | |
} | |
} |
No comments:
Post a Comment