· Java 8已安装。
· 任何Java IDE(最好是STS或IntelliJ IDEA)。
· 使用HTML,CSS和JavaScript,基本了解基于Java和Spring的Web开发和UI开发。
在本文中,我将尝试使用Java 8和Spring Boot创建一个小型端到端Web应用程序。
我选择了SpringBoot,因为它更容易配置并且可以很好地与其他技术堆栈配合使用。我还使用了REST API和SpringData JPA以及H2数据库。
我使用 Spring Initializer 添加所有依赖项,并使用我的所有配置创建一个空白的工作项目。
我使用Maven作为构建工具,但也可以使用Gradle。
<?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。
这是一个非常简单的可用于创建Web应用程序的项目,。
让我们从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团队技术人员编写,转载请标明出处