作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Stefan是一名合格的软件开发人员,拥有计算机科学学位,在科技行业有近十年的经验.
人们常说Java太复杂,构建简单的应用程序需要花费太长时间. Nonetheless, Java提供了一个稳定的平台和一个非常成熟的生态系统, 这使得它成为开发健壮软件的绝佳选择.
Spring框架是众多强大的框架之一 Java ecosystem, 提供了一系列编程和配置模型,旨在简化Java中高性能和可测试应用程序的开发.
In this tutorial, 我们将尝试构建一个简单的应用程序,作为数据库 software developers 使用Spring框架和Java持久化API (JPA).
应用程序遵循标准的MVC体系结构. 它将有一个控制器(ContractsController类), 视图(基于Thymeleaf模板), and a model (a Java map object). For the sake of simplicity, 在应用程序运行时,我们将使用JPA后面的内存数据库来持久化数据.
要构建一个基于Spring的应用程序,我们需要使用以下构建工具之一:
In this tutorial, we will use Maven. 如果您对这两个工具中的任何一个都不熟悉,一个简单的入门方法是下载 Spring Tool Suite. 该套件专门用于Spring框架,并附带了自己的套件 Eclipse based IDE.
In Spring Tool Suite, we create a new project by selecting “Spring Starter Project” from under the “File > New” menu.
一旦创建了新项目,我们将需要编辑Maven配置文件。”pom.xml,并添加以下依赖项:
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-data-jpa
com.h2database
h2
org.springframework.data
spring-data-commons
列出的这些依赖项将加载Spring Boot Web, Thymeleaf, JPA, 和H2(将作为我们的内存数据库). 所有必要的库将被自动拉出.
能够存储有关开发人员及其技能的信息, 我们需要定义两个实体类:Developer” and “Skill”.
它们都被定义为带有一些注释的普通Java类. 通过在类之前添加“@Entity”,我们使它们的实例对JPA可用. 这将使在需要时更容易从持久数据存储中存储和检索实例. Additionally, “@Id”和“@GeneratedValue”注释允许我们为实体指定唯一的ID字段,并在存储在数据库中时自动生成其值.
As a developer can have many skills, 我们可以使用“@ manymany”注释定义一个简单的多对多关系.
@Entity
public class Developer {
@Id
= GenerationType @GeneratedValue(策略.AUTO)
private long id;
private String firstName;
private String lastName;
private String email;
@ManyToMany
private List skills;
public Developer() {
super();
}
public Developer(字符串firstName,字符串lastName,字符串email)
List skills) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.skills = skills;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List getSkills() {
return skills;
}
public void setSkills(List skills) {
this.skills = skills;
}
hashkill(技能技能){
for (Skill containedSkill: getSkills()) {
if (containedSkill.getId() == skill.getId()) {
return true;
}
}
return false;
}
}
@Entity
public class Skill {
@Id
= GenerationType @GeneratedValue(策略.AUTO)
private long id;
private String label;
private String description;
public Skill() {
super();
}
公共技能(字符串标签,字符串描述){
super();
this.label = label;
this.description = description;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLabel() {
return label;
}
公共无效setLabel(字符串标签){
this.label = label;
}
public String getDescription() {
return description;
}
public void setDescription(字符串描述){
this.description = description;
}
}
使用JPA,我们可以定义一个非常有用的DeveloperRepository接口和SkillRepository接口, which allow for easy CRUD operations. 这些接口将允许我们通过简单的方法调用访问存储的开发人员和技能, such as:
要创建这些接口,我们所需要做的就是扩展CrudRepository接口.
public interface DeveloperRepository extends CrudRepository {
}
public interface SkillRepository extends CrudRepository {
public List findByLabel(String label);
}
附加方法的功能findByLabel ,将由JPA自动提供.
接下来,我们可以处理这个应用程序的控制器. 控制器将映射请求uri以查看模板,并在两者之间执行所有必要的处理.
@Controller
public class DevelopersController {
@Autowired
DeveloperRepository repository;
@Autowired
SkillRepository skillRepository;
@RequestMapping("/developer/{id}")
public String developer(@PathVariable Long id, Model Model) {
model.addAttribute("developer", repository.findOne(id));
model.addAttribute (skillRepository“技能”.findAll());
return "developer";
}
@RequestMapping (value = " /开发人员”,方法= RequestMethod.GET)
公共字符串developersList(模型模型){
model.addAttribute(“开发人员”,库.findAll());
return "developers";
}
@RequestMapping (value = " /开发人员”,方法= RequestMethod.POST)
public String developersAdd(@RequestParam String email)
@RequestParam String firstName, @RequestParam String lastName,模型模型){
开发者newDeveloper =新开发者();
newDeveloper.setEmail(email);
newDeveloper.setFirstName(firstName);
newDeveloper.setLastName(lastName);
repository.save(newDeveloper);
model.addAttribute(“开发人员”,newDeveloper);
model.addAttribute (skillRepository“技能”.findAll());
返回"redirect:/developer/" + newDeveloper.getId();
}
@RequestMapping (value = " /开发/ {id} /技能”,= RequestMethod方法.POST)
公共字符串developersAddSkill(@PathVariable长id, @RequestParam长skilid,模型模型){
Skill skill = skillRepository.findOne(skillId);
Developer developer = repository.findOne(id);
if (developer != null) {
if (!developer.hasSkill(skill)) {
developer.getSkills().add(skill);
}
repository.save(developer);
model.addAttribute("developer", repository.findOne(id));
model.addAttribute (skillRepository“技能”.findAll());
返回"redirect:/developer/" + developer.getId();
}
model.addAttribute(“开发人员”,库.findAll());
return "redirect:/developers";
}
}
uri到方法的映射是通过简单的“@RequestMapping”注释完成的. 在这种情况下,控制器的每个方法都映射到一个URI.
这些方法的模型参数允许将数据传递给视图. 本质上,这些是键到值的简单映射.
每个控制器方法返回要用作视图的thymleaf模板的名称, 或特定模式的URL (" redirect:
Within the controller, “@Autowired”注释会在相应的字段中自动分配我们定义的存储库的有效实例. 这允许从控制器内部访问相关数据,而无需处理大量样板代码.
最后,我们需要为要生成的视图定义一些模板. 为此,我们使用Thymeleaf,一个简单的模板引擎. 我们在控制器方法中使用的模型可以直接在模板中使用.e. when we enter a contract into “contract的关键字,我们将能够访问名称字段为“合同.name” from within the template.
Thymeleaf包含一些控制HTML生成的特殊元素和属性. 它们非常直观和直接. For example, 用技能的名称填充span元素的内容, 您所需要做的就是定义以下属性(假设键“skill” is defined in the model):
Similarly to set the “href"锚元素的属性,特殊属性"th:href” can be used.
在我们的应用程序中,我们需要两个简单的模板. For clarity, 我们将跳过嵌入模板代码中的所有样式和类属性(即Bootstrap属性).
Developers database
Developers
Name
Skills
,
view
Developer
Developer
Name:
Email:
Skills:
-
Spring contains a boot module. 这使得我们可以很容易地从命令行启动服务器 a command line Java application:
@SpringBootApplication
应用程序实现CommandLineRunner {
@Autowired
DeveloperRepository DeveloperRepository;
@Autowired
SkillRepository skillRepository;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
因为我们使用的是内存数据库, 在启动时用一些预定义的数据引导数据库是有意义的. 这样,当服务器启动并运行时,数据库中至少会有一些数据.
@Override
public void run(String... args) throws Exception {
技能javascript =新技能(“javascript”,“javascript语言技能”);
技能ruby =新技能(“ruby”,“ruby语言技能”);
技能emberjs =新技能(“emberjs”,“emberjs框架”);
技能angularjs =新技能("angularjs", "angularjs框架");
skillRepository.save(javascript);
skillRepository.save(ruby);
skillRepository.save(emberjs);
skillRepository.save(angularjs);
List developers = new LinkedList();
developers.add(new Developer)(“John”,“Smith”,“John”).smith@example.com",
Arrays.asList(新技能[]{javascript, ruby}));
developers.添加新的开发人员(“Mark”,“Johnson”,“mjohnson@example”).com",
Arrays.asList(new Skill[] {emberjs, ruby}));
developers.add(new Developer)(“Michael”,“Williams”,“Michael .”).williams@example.com",
Arrays.asList(new Skill[] {angularjs, ruby}));
developers.添加新的开发人员(“Fred”,“Miller”,“f”).miller@example.com",
Arrays.asList(new Skill[] {emberjs, angularjs, javascript}));
developers.add(new Developer)(“Bob”,“Brown”,“brown@example .”).com",
Arrays.asList(new Skill[] { emberjs })));
developerRepository.save(developers);
}
Spring是一个允许构建MVC应用程序的通用框架. 用Spring构建一个简单的应用程序既快速又透明. 应用程序还可以使用JPA轻松地与数据库集成.
整个项目的源代码是 available on GitHub.
Stefan是一名合格的软件开发人员,拥有计算机科学学位,在科技行业有近十年的经验.
17
世界级的文章,每周发一次.
世界级的文章,每周发一次.
Join the Toptal® community.