7分钟阅读

用Spring框架构建MVC应用:初学者's Tutorial

Stefan是一个合格的软件开发商,具有计算机科学学位,近十年的技术产业经验。

java.经常说太复杂,需要花费太多,以构建简单的应用程序。尽管如此,Java提供了一个稳定的平台,其周围有一个非常成熟的生态系统,这使其成为开发强大的软件的精彩选择。

春天框架,其中一个强大的框架之一 java. 生态系统,配备了一系列编程和配置模型,目标是简化Java中的表演和可测试应用程序的开发。

春天框架

在本教程中,我们将挑战构建一个作为数据库的简单应用程序 软件开发人员 使用Spring Framework和Java Persistence API(JPA)。

该应用程序遵循标准MVC架构。它将具有一个控制器(ContractScontroller类),视图(基于塔里夫模板)和模型(Java Map对象)。为简单起见,我们将在应用程序运行时使用JPA后面的内存数据库持续数据。

入门春天框架教程

要构建基于Spring的应用程序,我们需要使用以下构建工具之一:

  • Maven.

在本教程中,我们将使用Maven。如果您不熟悉这些工具中的任何一个,那么即将开始的简单方法是下载 弹簧工具套房。该套房专注于春天框架,并拥有自己的 based IDE.

在春季工具套件中,我们通过从“文件”下选择“Spring Starter Project”创建一个新项目> New” menu.

春季框架教程

一旦创建了一个新项目,我们将需要编辑Maven配置文件“pom.xml.“,并添加以下依赖项:

<dependency>
	<groupId>org.springframework.boot..</groupId>
	<artifactId>春天启动 - 起动器网</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot..</groupId>
	<artifactId>春天启动 - 起动器 - 胸部胸部</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot..</groupId>
	<artifactId>Spring-Boot-Starter-Data-JPA</artifactId>
</dependency>
<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.data.</groupId>
	<artifactId>spring-data-commons</artifactId>
</dependency>

这些列出的依赖项将加载Spring Boot Web,Thymeleaf,JPA和H2(它将作为我们的内存数据库)。所有必要的库将自动拉动。

实体课程

为了能够存储有关开发人员和技能的信息,我们需要定义两个实体类:“开发人员“ 和 ”技能“。

这两个都被定义为具有一些注释的普通Java类。通过在类之前添加“@entity”,我们正在为JPA提供实例。这将使在需要时更容易存储和检索持久数据存储中的实例。此外,“@Id”和“@generatedValue”注释允许我们指示实体的唯一ID字段,并在存储在数据库中时自动生成其值。

由于开发人员可以有很多技能,我们可以使用“@manytomany”注释来定义一个简单的多对多关系。

开发人员

@Entity
public class Developer {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private long id;
	private String firstName;
	private String lastName;
	private String email;
	@ManyToMany
	private List<Skill> skills;

	public Developer() {
		super();
	}

	public Developer(String firstName, String lastName, String email,
			List<Skill> 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<Skill> getSkills() {
		return skills;
	}

	public void setSkills(List<Skill> skills) {
		this.skills = skills;
	}

	public boolean hasSkill(Skill skill) {
		for (Skill containedSkill: getSkills()) {
			if (containedSkill.getId() == skill.getId()) {
				return true;
			}
		}
		return false;
	}

}

技能

@Entity
public class Skill {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    private String label;
    private String description;

    public Skill() {
		super();
    }

    public Skill(String label, String description) {
		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;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}
    
}

存储库

使用JPA,我们可以定义一个非常有用的DeveloperRepository界面和技能内容界面,允许简单的Crud操作。这些接口将允许我们通过简单的方法调用访问存储的开发人员和技能,例如:

  • “respository.findall()”:返回所有开发人员
  • “repository.findone(id)”:返回带有给定ID的开发人员

要创建这些接口,我们需要做的就是扩展CrudRepository接口。

开发人员 Repository

public interface DeveloperRepository extends CrudRepository<Developer, Long> {

}

技能存储库

public interface SkillRepository extends CrudRepository<Skill, Long> {
	public List<Skill> 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("开发人员",repository.findone(ID));
		model.addAttribute("技能",skillrepository.findall());
		return "开发人员";
	}

	@RequestMapping(value="/developers",method=RequestMethod.GET)
	public String developersList(Model model) {
		model.addAttribute("开发人员s", repository.findAll());
		return "开发人员s";
	}

	@RequestMapping(value="/developers",method=RequestMethod.POST)
	public String developersAdd(@RequestParam String email, 
						@RequestParam String firstName, @RequestParam String lastName, Model model) {
		Developer newDeveloper = new Developer();
		newDeveloper.setEmail(email);
		newDeveloper.setFirstName(firstName);
		newDeveloper.setLastName(lastName);
		repository.save(newDeveloper);

		model.addAttribute("开发人员", newDeveloper);
		model.addAttribute("技能",skillrepository.findall());
		return "redirect:/developer/" + newDeveloper.getId();
	}

	@RequestMapping(value="/developer/{id}/skills", method=RequestMethod.POST)
	public String developersAddSkill(@PathVariable Long id, @RequestParam Long skillId, Model model) {
		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("开发人员",repository.findone(ID));
			model.addAttribute("技能",skillrepository.findall());
			return "redirect:/developer/" + developer.getId();
		}

		model.addAttribute("开发人员s", repository.findAll());
		return "redirect:/developers";
	}

}

通过简单的“@RequestMapping”注释来完成URI的映射。在这种情况下,控制器的每个方法都映射到URI。

这些方法的模型参数允许数据传递给视图。从本质上讲,这些是对值的简单键映射。

每个控制器方法要么返回要用作视图的塔里夫模板的名称,或者以特定模式(“重定向:“)重定向到。例如,“Developer”和“_DevelopersList_”方法返回模板的名称,而“developersadd”和“developersaddskill”返回URL以重定向到。

在控制器中,“@autowired”注释会自动为相应字段中的已定义存储库的有效实例分配。这允许从控制器内访问相关数据,而无需处理大量的样板代码。

意见

最后,我们需要为要生成的视图定义一些模板。为此,我们正在使用百里香,简单的模板发动机。我们在控制器方法中使用的模型直接在模板中,即当我们输入合同时“ 合同“模型中的键,我们将能够从模板中访问名称字段为”契约“。

胸部素包含一些特殊的元素和属性,控制HTML的生成。它们非常直观,直截了当。例如,要使用技能名称填充跨域元素的内容,您需要做的就是定义以下属性(假设键“技能“在模型中定义):

<span th:text="${skill.label}"></span>

类似地设置“HREF.“锚元素的属性,特殊属性”th:href.“可以使用。

在我们的应用程序中,我们需要两个简单的模板。为清楚起见,我们将在嵌入式模板代码中跳过所有风格和类属性(即“overstrap Inter)。

开发人员 List

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head> 
	<title>Developers database</title> 
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
	<h1>Developers</h1>
	<table>
		<tr>
			<th>Name</th>
			<th>Skills</th>
			<th></th>
		</tr>
		<tr th:each="开发人员 : ${developers}">
			<td th:text="${developer.firstName + ' ' + developer.lastName}"></td>
			<td>
				<span th:each="技能,iterStat : ${developer.skills}">
					<span th:text="${skill.label}"/><th:block th:if="${!iterStat.last}">,</th:block>
				</span>
			</td>
			<td>
				<a th:href="@{/developer/{id}(id=${developer.id})}">view</a>
			</td>
		</tr>
	</table>
	<hr/>
	<form th:action="@{/developers}" method="post" enctype="multipart/form-data">
		<div>
			First name: <input name="firstName" />
		</div>
		<div>
			Last name: <input name="lastName" />
		</div>
		<div>
			Email: <input name="email" />
		</div>
		<div>
			<input type="submit" value="Create developer" name="button"/>
		</div>
	</form>
</body>
</html>

开发人员 Details

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>Developer</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
	<h1>Developer</h1>
	Name: <b th:text="${developer.firstName}" /> <b th:text="${developer.lastName}" /><br/>
	Email: <span th:text="${developer.email}" /><br/>
	Skills:
		<span th:each="技能 : ${developer.skills}">
			<br/>&nbsp;&nbsp;<span th:text="${skill.label}" /> - <span th:text="${skill.description}" />
		</span>
	<form th:action="@{/developer/{id}/skills(id=${developer.id})}" method="post" enctype="multipart/form-data" >
		<select name="技能Id">
			<option th:each="技能 : ${skills}" 
				th:value="${skill.id}" 
				th:text="${skill.description}">Skill</option>
		</select>
		<input type="submit" value="Add skill"/>
	</form>
</body>
</html>

运行服务器

春天包含启动模块。这允许我们轻松地从命令行启动服务器 命令行Java应用程序:

@SpringBootApplication
public class Application implements 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 {
	Skill javascript = new Skill("javascript", "java.script language skill");
	Skill ruby = new Skill("ruby", "Ruby language skill");
	Skill emberjs = new Skill("emberjs", "Emberjs framework");
	Skill angularjs = new Skill("angularjs", "Angularjs framework");

	skillRepository.save(javascript);
	skillRepository.save(ruby);
	skillRepository.save(emberjs);
	skillRepository.save(angularjs);

	List<Developer> developers = new LinkedList<Developer>();
	developers.add(new Developer("John", "Smith", "[email protected]", 
			Arrays.asList(new Skill[] { javascript, ruby })));
	developers.add(new Developer("Mark", "Johnson", "[email protected]", 
			Arrays.asList(new Skill[] { emberjs, ruby })));
	developers.add(new Developer("Michael", "Williams", "[email protected]", 
			Arrays.asList(new Skill[] { angularjs, ruby })));
	developers.add(new Developer("Fred", "Miller", "[email protected]", 
			Arrays.asList(new Skill[] { emberjs, angularjs, javascript })));
	developers.add(new Developer("Bob", "Brown", "[email protected]", 
			Arrays.asList(new Skill[] { emberjs })));
	developerRepository.save(developers);
}

结论

春天是一种多功能框架,允许构建MVC应用程序。用弹簧构建简单的应用是快速透明的。应用程序也可以使用JPA轻松与数据库集成。

整个项目的源代码是 在GitHub上提供.