· Java 8已安裝。css
· 任何Java IDE(最好是STS或IntelliJ IDEA)。html
· 使用HTML,CSS和JavaScript,基本瞭解基於Java和Spring的Web開發和UI開發。java
在本文中,我將嘗試使用Java 8和Spring Boot建立一個小型端到端Web應用程序。web
我選擇了SpringBoot,由於它更容易配置而且能夠很好地與其餘技術堆棧配合使用。我還使用了REST API和SpringData JPA以及H2數據庫。spring
我使用 Spring Initializer 添加全部依賴項,並使用個人全部配置建立一個空白的工做項目。數據庫
我使用Maven做爲構建工具,但也可使用Gradle。apache
<?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.example</groupId>
<artifactId>bootdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>bootDemo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.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-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>複製代碼
複製代碼
在UI部分,我使用了AngularJS和BootStrap CSS以及基本的JS,CSS和HTML。json
這是一個很是簡單的可用於建立Web應用程序的項目,。bootstrap
讓咱們從SpringBootApplication類開始。瀏覽器
@SpringBootApplication
public class BootDemoApplication {
@Autowired
UserRepository userRepository;
public static void main(String[] args) {
SpringApplication.run(BootDemoApplication.class, args);
}
}複製代碼
咱們如今建立Controller。
@Controller
public class HomeController {
@RequestMapping("/home")
public String home() {
return "index";
}
}複製代碼
這將做爲咱們SPA的主頁。如今咱們建立一個Controller來處理一些REST調用。
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
UserService
userService;
@RequestMapping(Constants.GET_USER_BY_ID)
public UserDto getUserById(@PathVariable Integer userId) {
return userService.getUserById(userId);
}
@RequestMapping(Constants.GET_ALL_USERS)
public List < UserDto > getAllUsers() {
return userService.getAllUsers();
}
@RequestMapping(value = Constants.SAVE_USER, method =
RequestMethod.POST)
public void saveUser(@RequestBody UserDto userDto) {
userService.saveUser(userDto);
}
}複製代碼
在這裏,咱們有不一樣的方法來處理來自客戶端的不一樣測試調用。
我在Controller中安裝了一個Service類 UserService。
public interface UserService {
UserDto
getUserById(Integer userId);
void saveUser(UserDto userDto);
List < UserDto
> getAllUsers();
}
@Service
public class UserServiceimpl implements
UserService {
@Autowired
UserRepository
userRepository;
@Override
public UserDto getUserById(Integer userId) {
return
UserConverter.entityToDto(userRepository.getOne(userId));
}
@Override
public void saveUser(UserDto userDto) {
userRepository.save(UserConverter.dtoToEntity(userDto));
}
@Override
public List < UserDto > getAllUsers() {
return
userRepository.findAll().stream().map(UserConverter::entityToDto).collect(Collectors.toList());
}
}複製代碼
在典型的Web應用程序中,一般有兩種類型的數據對象:DTO(經過客戶端進行通訊)和實體(經過DB進行通訊)。
public class UserDto {
Integer userId;
String userName;
List<SkillDto> skillDtos= new ArrayList<>();
public UserDto(Integer userId, String userName, List<SkillDto> skillDtos) {
this.userId = userId;
this.userName = userName;
this.skillDtos = skillDtos;
}
public UserDto() {
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<SkillDto> getSkillDtos() {
return skillDtos;
}
public void setSkillDtos(List<SkillDto> skillDtos) {
this.skillDtos = skillDtos;
}
}
public class SkillDto {
Integer skillId;
String SkillName;
public SkillDto(Integer skillId, String skillName) {
this.skillId = skillId;
SkillName =
skillName;
}
public SkillDto() {
}
public Integer getSkillId() {
return skillId;
}
public void setSkillId(Integer skillId) {
this.skillId = skillId;
}
public String getSkillName() {
return SkillName;
}
public void setSkillName(String skillName) {
SkillName =
skillName;
}
}複製代碼
@Entity
public class User implements Serializable{
private static final long serialVersionUID = 0x62A6DA99AABDA8A8L;
@Column
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Integer userId;
@Column
private String userName;
@OneToMany(cascade = CascadeType.ALL, fetch =
FetchType.EAGER)
private List<Skill> skills= new LinkedList<>();
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<Skill> getSkills() {
return skills;
}
public void setSkills(List<Skill> skills) {
this.skills = skills;
}
public User() {
}
public User(String userName, List<Skill> skills) {
this.userName = userName;
this.skills = skills;
}
}
@Entity
public class Skill {
@Column
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Integer skillId;
@Column
private String skillName;
@ManyToOne
private User user;
public Skill(String skillName) {
this.skillName = skillName;
}
public Integer getSkillId() {
return skillId;
}
public void setSkillId(Integer skillId) {
this.skillId = skillId;
}
public String getSkillName() {
return skillName;
}
public void setSkillName(String skillName) {
this.skillName = skillName;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Skill() {
}
public Skill(String skillName, User user) {
this.skillName = skillName;
this.user = user;
}
}複製代碼
對於數據庫操做,咱們使用SpringData JPA:
@Repository
public interface UserRepository extends
JpaRepository<User, Integer>{
}
@Repository
public interface SkillRepository extends
JpaRepository<Skill, Integer>{
}複製代碼
在默認狀況下,擴展JpaRepository
提供了大量的CRUD操做,也可使用它來建立本身的查詢方法。
爲了轉換DTO - >Entity和Entity - > DTO,我建立了一些基本的轉換器類。
public class UserConverter {
public static User dtoToEntity(UserDto userDto) {
User user = new User(userDto.getUserName(), null);
user.setUserId(userDto.getUserId());
user.setSkills(userDto.getSkillDtos().stream().map(SkillConverter::dtoToEntity).collect(Collectors.toList()));
return user;
}
public static UserDto entityToDto(User user) {
UserDto userDto =
new UserDto(user.getUserId(),
user.getUserName(), null);
userDto.setSkillDtos(user.getSkills().stream().map(SkillConverter::entityToDto).collect(Collectors.toList()));
return userDto;
}
}
public class SkillConverter {
public static Skill dtoToEntity(SkillDto SkillDto) {
Skill Skill = new Skill(SkillDto.getSkillName(), null);
Skill.setSkillId(SkillDto.getSkillId());
return Skill;
}
public static SkillDto entityToDto(Skill skill) {
return new SkillDto(skill.getSkillId(), skill.getSkillName());
}
}複製代碼
如今讓咱們關注UI部分。
使用Angular時,咱們須要遵循一些指導原則。
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Main Page</title>
</head>
<body ng-app="demo">
<hr/>
<div class="container" ng-controller="UserController">
<div class="row">
<label>User</label> <input type="text" ng-model="userDto.userName" class="input-sm spacing"/>
<label>Skills</label> <input type="text" ng-model="skills" ng-list class="input-sm custom-width spacing"
placeholder="use comma to separate skills"/>
<button ng-click="saveUser()" class="btn btn-sm btn-info">Save User</button>
</div>
<hr/>
<div class="row">
<p>{{allUsers | json}}</p>
</div>
<hr/>
<div class="row" ng-repeat="user in allUsers">
<div class="">
<h3>{{user.userName}}</h3>
<span ng-repeat="skill in user.skillDtos" class="spacing">{{skill.skillName}}</span>
</div>
</div>
</div>
</body>
<script src="js/lib/angular.min.js"></script>
<script src="js/lib/ui-bootstrap-tpls-2.5.0.min.js"></script>
<script src="js/app/app.js"></script>
<script src="js/app/UserController.js"></script>
<script src="js/app/UserService.js"></script>
<link rel="stylesheet" href="css/lib/bootstrap.min.css"/>
<link rel="stylesheet" href="css/app/app.css"/>
</html>複製代碼
在建立HTML時,不要忘記導入所需的JS和CSS文件。
'use strict'
var demoApp = angular.module('demo', ['ui.bootstrap', 'demo.controllers',
'demo.services'
]);
demoApp.constant("CONSTANTS", {
getUserByIdUrl:
"/user/getUser/",
getAllUsers: "/user/getAllUsers",
saveUser: "/user/saveUser"
});複製代碼
'use strict'
var module = angular.module('demo.controllers', []);
module.controller("UserController", ["$scope", "UserService",
function($scope, UserService) {
$scope.userDto = {
userId:
null,
userName: null,
skillDtos: []
};
$scope.skills = [];
UserService.getUserById(1).then(function(value) {
console.log(value.data);
}, function(reason) {
console.log("error occured");
}, function(value) {
console.log("no callback");
});
$scope.saveUser = function() {
$scope.userDto.skillDtos = $scope.skills.map(skill => {
return {
skillId: null,
skillName: skill
};
});
UserService.saveUser($scope.userDto).then(function() {
console.log("works");
UserService.getAllUsers().then(function(value) {
$scope.allUsers = value.data;
}, function(reason) {
console.log("error occured");
}, function(value) {
console.log("no callback");
});
$scope.skills = [];
$scope.userDto = {
userId: null,
userName: null,
skillDtos: []
};
}, function(reason) {
console.log("error occured");
}, function(value) {
console.log("no callback");
});
}
}
]);複製代碼
'use strict'
angular.module('demo.services', []).factory('UserService', ["$http", "CONSTANTS", function($http, CONSTANTS) {
var service = {};
service.getUserById = function(userId) {
var url = CONSTANTS.getUserByIdUrl + userId;
return $http.get(url);
}
service.getAllUsers = function() {
return $http.get(CONSTANTS.getAllUsers);
}
service.saveUser = function(userDto) {
return $http.post(CONSTANTS.saveUser, userDto);
}
return service;
}]);複製代碼
body{
background-color: #efefef;
}
span.spacing{
margin-right: 10px;
}
input.custom-width{
width: 200px;
}
input.spacing{
margin-right: 5px;
}複製代碼
可使用如下方法構建應用程序
mvn clean install
或者java -jar bootdemo-0.0.1-SNAPSHOT.jar
打開瀏覽器並點擊 http:// localhost:8080 / home
在打開一個簡單的頁面以後,輸入名稱和技能,輸入的數據將保留在數據庫中。
本人創業團隊產品MadPecker,主要作BUG管理、測試管理、應用分發,網址:www.madpecker.com,有須要的朋友歡迎試用、體驗!本文爲MadPecker團隊技術人員編寫,轉載請標明出處