* commit first as binodpanta

* revert test change

* A short example of real-time event streaming using Spring WebFlux

* Code for http://jira.baeldung.com/browse/BAEL-1527

* remove unrelated files

* Apply feedback changes to rename test and remove link from readme file, ongoing work

* Update formatting fixes to code and add pom changes, that partially fix test runnning issues in IDE but not in cmdline

* Apply Eclipse formatter to test code and apply suggested pom fixes

* BAEL-1527 Formatting fix in pom.xml

* Use string.format to cleanup logging code

* BAEL-1527 Changed logging pattern

* Start the spring-boot-vue module, WIP

* some small updates with comments

* Add index html template page

* merge pom.xml fixes

* Add integration test with MockMvc to verify index.html content is rendered correctly

* fix up pom merge issues

* merge issues fix for pom

* pom end of file newline
This commit is contained in:
Binod Pant 2018-07-23 17:00:30 -04:00 committed by maibin
parent 977a92ef0e
commit 896a2d071a
9 changed files with 248 additions and 1 deletions

View File

@ -422,6 +422,7 @@
<module>spring-boot-persistence</module>
<module>spring-boot-security</module>
<module>spring-boot-mvc</module>
<module>spring-boot-vue</module>
<module>spring-boot-logging-log4j2</module>
<module>spring-cloud-data-flow</module>
<module>spring-cloud</module>
@ -1223,4 +1224,5 @@
<maven-pmd-plugin.version>3.8</maven-pmd-plugin.version>
</properties>
</project>
</project>

25
spring-boot-vue/.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

56
spring-boot-vue/pom.xml Normal file
View File

@ -0,0 +1,56 @@
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-boot-vue</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-vue</name>
<description>Demo project for Spring Boot Vue project</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- needed to render html templates in /resources/templates -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package com.baeldung.springbootmvc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@SpringBootApplication
public class SpringBootMvcApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMvcApplication.class, args);
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.springbootmvc.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MainController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model) {
// this attribute will be available in the view index.html as a thymeleaf variable
model.addAttribute("eventName", "FIFA 2018");
// this just means render index.html from static/ area
return "index";
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,98 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Include Bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<h3 class="display-3">This is an example Vue.js application developed with Spring Boot</h3>
<p class="lead">This file is rendered by a Spring built-in default controller for index.html (/) using
Spring's built-in
Thymeleaf templating engine.
Although we don't need it per se, we customized the information passed to this
view from thymeleaf by adding a controller method for "/" route to demonstrate how to pass information from
Thymeleaf to this page.
The combination of template engine and frontend framework like Vue can make this a powerful approach to build
more complex applications while leveraging the benefits of a framework like Vue.js.
You can use thymeleaf features too but this project focuses mainly on using Vue.js on the
frontend as the framework and makes minimal use of Thymeleaf.
Also we don't use any routing and multiple components in this example, so what you see is technically a
Single Page Application (SPA) without any routes configured.
</p>
<div id="contents-main">
<div class="lead">
<strong>Name of Event:</strong>
<span th:text="${eventName}"></span>
</div>
<div id="contents">
<!-- Since we create a Vue component pointing to id=contents,
Vue will generate a unordered list of items such
as this inside this div.
v-for will cause a loop to run over all players
as per the players array found in app.data
<ul>
<li></li>
<li></li>
</ul>
-->
<ul>
<li style="list-style-type:none" v-for="player in players">
<player-card
v-bind:player="player" v-bind:key="player.id">
</player-card>
</li>
</ul>
</div>
</div>
</div>
<!-- include Vue.js -->
<!-- we include babel js so that we can write ES6 code in the browser
for a more production like setup it is recommended to setup a build process
to transpile and minify the code (such as using webpack)
-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<script type="text/babel">
// player-card is now a Vue component that generates a 'card' showing a player
// It can be used
// declaratively like <player-card v-bind:player="someplayer">
Vue.component('player-card', {
props: ['player'],
template: `<div class="card">
<div class="card-body">
<h6 class="card-title">
{{ player.name }}
</h6>
<p class="card-text">
<div>
{{ player.description }}
</div>
</p>
</div>
</div>`
});
var app = new Vue({
el: '#contents',
data: {
players: [
{id: "1", name: "Lionel Messi", description: "Argentina's superstar"},
{id: "2", name: "Christiano Ronaldo", description: "Portugal top-ranked player"}
]
}
});
</script>
</body>
</html>

View File

@ -0,0 +1,35 @@
package com.baeldung.springbootmvc;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import static org.hamcrest.CoreMatchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SpringBootMvcApplicationTests {
@Autowired
private MockMvc mockMvc;
/**
* If this test passes, we got a page with the thymeleaf provided variable
* value for eventName
*/
@Test
public void shouldLoadCorrectIndexPage() throws Exception {
mockMvc.perform(get("/")).andExpect(status().isOk()).
andExpect(MockMvcResultMatchers.content()
.string(containsString("FIFA 2018")));
}
}