Use Scala to build Spring boot framework 1. Objective
Spring boot is the most popular web framework on the Java development platform. Scala is a static type of functional programming language that runs on the JVM. The Big data processing spark framework is developed in the Scala language.
This example integrates the Spring boot framework into a Scala project. Use the user Rights management provided by the Spring security module. Make a simple user login and Rights management.
Techniques used to spring boot Web service,swagger, H2 database, spring boot jpa,spring security
2. Create a MAVEN Spring boot application
- Create a MAVEN project and add the content to the Maven Pom file.
<?xml version= "1.0" encoding= "UTF-8"? ><project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http ://www.w3.org/2001/XMLSchema-instance "xsi:schemalocation=" http://maven.apache.org/POM/4.0.0/http Maven.apache.org/maven-v4_0_0.xsd "> <modelVersion>4.0.0</modelVersion> <groupid>com.example </groupId> <artifactId>scala-spring-boot</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <parent> <groupid>org.springframework.boot</groupid > <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.release</version > <relativePath/> <!--lookup parent from repository to </parent> <name>a Camel Scala Rou Te</name> <properties> <project.build.sourceencoding>utf-8</project.build.sourceencoding > <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <scala.version>2.11.7</scala.version> </properties > <dependencyManagement> <dependencies> </dependencies> </dependencyManagement> <de pendencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactid>s pring-boot-starter-web</artifactid> </dependency> <dependency> <groupid>org.springframe work.boot</groupid> <artifactId>spring-boot-starter-test</artifactId> </dependency> < ;d ependency> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-starter-da ta-jpa</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</gr oupid> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency& Gt <groupid>org.sPringframework.boot</groupid> <artifactId>spring-boot-starter-aop</artifactId> </dependency > <dependency> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot -starter-thymeleaf</artifactid> </dependency> <dependency> <groupid>org.springframework .boot</groupid> <artifactId>spring-boot-starter-validation</artifactId> </dependency> & lt;dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> < ;scope>runtime</scope> </dependency> <!--Scala---<dependency> <groupid>o Rg.scala-lang</groupid> <artifactId>scala-library</artifactId> <version>${scala.version} </version> </dependency> <dependency> <groupId>org.scala-lang</groupId> < Artifactid>scala-compilEr</artifactid> <version>${scala.version}</version> </dependency> <!--Swagger--> ; <dependency> <groupId>io.springfox</groupId> <artifactid>springfox-swagger-ui</artifa ctid> <version>2.7.0</version> </dependency> <dependency> <GROUPID>IO.SPR Ingfox</groupid> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version& Gt </dependency> </dependencies> <build> <defaultGoal>install</defaultGoal> <sourced Irectory>src/main/scala</sourcedirectory> <testsourcedirectory>src/test/scala</ testsourcedirectory> <plugins> <plugin> <groupid>org.springframework.boot</groupid& Gt <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupid& Gt;net.alchim31.maven&lT;/groupid> <artifactId>scala-maven-plugin</artifactId> <version>3.2.1</version> <executions> <execution> <id>compile-scala</id> <phase> ;compile</phase> <goals> <goal>add-source</goal> <goal> compile</goal> </goals> </execution> <execution> <id> ;test-compile-scala</id> <phase>test-compile</phase> <goals> &L t;goal>add-source</goal> <goal>testCompile</goal> </goals> < ;/execution> </executions> <configuration> <recompilemode>incremental</reco mpilemode> <scalaVersion>${scala.version}</scalaVersion> <args> <arg& gt;-deprecation</arg&Gt </args> <jvmArgs> <jvmArg>-Xms64m</jvmArg> <jvmarg>-xmx1024m& lt;/jvmarg> </jvmArgs> </configuration> </plugin> </plugins> </buil D></project>
- We use the Scala plugin to compile the code in the Src/main/scala and Src/test/scala directories into Java code.
3. Create Apiapplication Scala class
- This is the spring's entry class. At run time, the class guides the spring application and starts the spring context.
@SpringBootApplicationclass ApiApplicationobject ApiApplication extends App { SpringApplication.run(classOf[ApiApplication], args :_*)}
4. Create a restful API
@RestController and @requestmapping are used to create restful Web services in spring. Examples of controllers in Scala such as the following
@RestController@RequestMapping(path = Array("/api"))class UserController(@Autowired val userService: UserService, @Autowired val dataSource: DataSource) { @GetMapping(path = Array("/users")) def getAllUsers(): Iterable[Users] = { userService.listUsers() } @GetMapping(path = Array("/users/{id}")) def getUser(@PathVariable id: Long): Users = { userService.getUser(id) } @PostMapping(path = Array("/users")) def createUser(@RequestBody users: Users): ResponseEntity[Long] = { val id = userService.createUser(users) new ResponseEntity(id, new HttpHeaders, HttpStatus.CREATED) }}
5. Create a UserService class
@Serviceclass UserService(@Autowired private val userRepository: UserRepository) { @PreAuthorize("hasRole(‘admin‘)") def listUsers(): Iterable[Users] = { userRepository.findAll } @PreAuthorize("hasRole(‘user‘)") @PostAuthorize("returnObject.username==principal.username || hasRole(‘admin‘)") def getUser(id: Long):Users = { userRepository.findOne(id) } @PreAuthorize("hasRole(‘admin‘)") def createUser(users: Users): Long = { userRepository.save(users) users.id }}
- Add a @preauthorize and @postauthorize to the UserService method. If the logged-on user has the "admin" role, this user runs the Listusers () and CreateUser () operations.
If the logged-on user has the "user" role, the user only runs the GetUser () operation.
- These operations are implemented through the authorities table. The following is an example of Import.sql:
DROP IF EXISTS authorities;CREATE TABLE authorities (id bigint auto_increment not null, username varchar_ignorecase(50) not null, authority varchar_ignorecase(50) not null, constraint fk_authorities_users foreign key(username) references users(username));INSERT INTO users (id, username, password,enabled) VALUES (1, ‘root‘, ‘root‘, true), (2, ‘user‘, ‘user‘, true);INSERT INTO authorities (id, username, authority) VALUES (1, ‘root‘, ‘ROLE_user‘), (2, ‘root‘, ‘ROLE_admin‘), (3, ‘user‘, ‘ROLE_user‘);
6. Add Spring DATA JPA
@Repositorytrait UserRepository extends CrudRepository[Users, Long] { def findUserByUsername(username: String): Users}
7. Add an Entity class users
Note that the type of ID here must be Java.lang.Long cannot be a Scala native Long. The reason is that the ID type of crudrepository must be inherited serializable
@Entityclass Users extends Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @BeanProperty var id: Long = _ @BeanProperty @Column(name = "username") var username: String = _ @BeanProperty @Column(name = "password") var password: String = _ @BeanProperty @Column(name = "enabled") var enabled: Boolean = _}
8. Add a data source
- Here is the use of embedded database H2. The following content needs to be configured to Application.properties
spring.h2.console.enabled=true is to allow access to the H2 database through the console
spring.datasource.url=jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSEspring.datasource.driverClassName=org.h2.Driverspring.datasource.username=saspring.datasource.password=saspring.jpa.database-platform=org.hibernate.dialect.H2Dialect# h2spring.h2.console.enabled=true
- Access H2 console by http://localhost:8080/h2-console the default user name and password is SA/SA
9. Configure Swagger
- Swagger is a Rest Web services documentation tool. can be accessed via http://localhost:8080/swagger-ui.html
@Configuration@EnableSwagger2class SwaggerConfig { @Bean def api(): Docket = { new Docket(DocumentationType.SWAGGER_2).select.apis(RequestHandlerSelectors.any).paths(PathSelectors.any).build }}
10. Binding the API's authentication to spring security
@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)class WebSecurityConfig(@Autowired val dataSource: DataSource) extends WebSecurityConfigurerAdapter { override def configure(http: HttpSecurity) = { http.authorizeRequests.antMatchers("/console", "/console/**", "/console/", "/swagger-ui.html", "/**/*.css", "/**/*.js", "/**/*.png", "/configuration/**", "/swagger-resources", "/v2/**").permitAll http.authorizeRequests.anyRequest.authenticated http.csrf.disable http.headers.frameOptions.disable http.httpBasic } @Bean override def userDetailsService: UserDetailsService = { val manager = new JdbcDaoImpl manager.setDataSource(dataSource) manager }}
- @EnableGlobalMethodSecurity (prepostenabled = True) To enable Spring security method level authentication.
11. Testing the Web service with spring test
-Sample Code
@Test def testPostCreateUser() = { val headers = new HttpHeaders headers.add("Authorization", "Basic " + new String(Base64.encodeBase64(("root" + ":" + "root").getBytes))) headers.setContentType(MediaType.APPLICATION_JSON) headers.setAccept(util.Arrays.asList(MediaType.APPLICATION_JSON)) val user = new Users user.setId(101L) user.setUsername("Test") user.setPassword("Test") user.setEnabled(true) val entity = new HttpEntity(user, headers) val result = template.postForObject("/api/users", entity, classOf[String]) println(result) }
12. Reference
Use Scala to build the Spring boot framework