
在spring boot开发中,我们经常会遇到这样的场景:后端服务从数据库获取一个包含多个字段的完整实体对象(例如adventureholidays),但前端页面(html)或特定的api接口只需要其中的部分字段(例如title和description)。直接将完整实体暴露给前端可能导致不必要的数据传输、安全隐患,并增加前端解析的复杂性。我们的目标是实现一个spring boot控制器,当被调用时,能够返回一个只包含所需特定字段的html页面。
原始的AdventureHolidays实体定义如下:
@Document("adventureholidays")
public class AdventureHolidays {
@Id
private String id;
private String title;
private String description;
private String typeOfAdventureHolidays;
// Getter方法
public String getId() { return id; }
public String getTitle() { return title; }
public String getDescription() { return description; }
public String getTypeOfAdventureHolidays() { return typeOfAdventureHolidays; }
// Setter方法(如果需要)
public void setId(String id) { this.id = id; }
public void setTitle(String title) { this.title = title; }
public void setDescription(String description) { this.description = description; }
public void setTypeOfAdventureHolidays(String typeOfAdventureHolidays) { this.typeOfAdventureHolidays = typeOfAdventureHolidays; }
}一个典型的控制器可能返回完整的JSON列表:
@RestController
public class AdventureApiController {
@Autowired
private AdventureHolidaysService adventureHolidaysService;
@GetMapping("/getRandomSummerCamps")
public List<AdventureHolidays> getRandomSummerCamps() {
return adventureHolidaysService.getRandomSummerCamps();
}
}当访问/getRandomSummerCamps时,会得到类似以下包含所有字段的JSON响应:
[{"id":"123","title":"Raquette Lake Camp","description":"Founded in 1916...","typeOfAdventureHolidays":"summerCamps"}]而我们的目标是,在HTML页面中只显示title和description。
立即学习“前端免费学习笔记(深入)”;
数据传输对象(DTO)是解决此类问题的最佳实践。DTO是一个简单的Java对象,其主要目的是在应用程序的不同层之间传输数据。它只包含前端或特定服务所需的数据字段,从而将领域模型与表示层解耦。
DTO的优势:
针对我们的需求,创建一个只包含title和description的AdventureSummaryDTO:
// src/main/java/com/example/demo/dto/AdventureSummaryDTO.java
package com.example.demo.dto;
public class AdventureSummaryDTO {
private String title;
private String description;
// 构造函数
public AdventureSummaryDTO(String title, String description) {
this.title = title;
this.description = description;
}
// Getter 方法
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
// Setter 方法 (如果需要,但对于DTO通常不需要)
public void setTitle(String title) {
this.title = title;
}
public void setDescription(String description) {
this.description = description;
}
}为了返回HTML页面,我们需要将控制器类型从@RestController改为@Controller,并使用Spring MVC的Model对象将数据传递给视图模板。
// src/main/java/com/example/demo/controller/AdventureWebController.java
package com.example.demo.controller;
import com.example.demo.dto.AdventureSummaryDTO;
import com.example.demo.model.AdventureHolidays;
import com.example.demo.service.AdventureHolidaysService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
import java.util.stream.Collectors;
@Controller // 注意这里是 @Controller,用于返回视图
public class AdventureWebController {
@Autowired
private AdventureHolidaysService adventureHolidaysService;
@GetMapping("/summerCampsHtml") // 定义一个新的URL路径用于HTML页面
public String getSummerCampsHtml(Model model) {
// 1. 从服务层获取完整的实体列表
List<AdventureHolidays> summerCamps = adventureHolidaysService.getRandomSummerCamps();
// 2. 将实体列表转换为DTO列表
List<AdventureSummaryDTO> summaryCamps = summerCamps.stream()
.map(camp -> new AdventureSummaryDTO(camp.getTitle(), camp.getDescription()))
.collect(Collectors.toList());
// 3. 将DTO列表添加到Model中,以便在HTML模板中使用
model.addAttribute("camps", summaryCamps);
// 4. 返回视图名称。Spring Boot将根据配置查找对应的HTML模板
return "summerCampsView"; // 假设存在一个名为 summerCampsView.html 的模板
}
}说明:
在src/main/resources/templates/目录下创建summerCampsView.html文件:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>夏令营列表</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.camp-item { border: 1px solid #ddd; padding: 15px; margin-bottom: 10px; border-radius: 5px; }
h2 { color: #333; margin-top: 0; }
p { color: #666; }
</style>
</head>
<body>
<h1>随机夏令营</h1>
<div th:if="${#lists.isEmpty(camps)}">
<p>没有找到任何夏令营信息。</p>
</div>
<div th:each="camp : ${camps}" class="camp-item">
<h2 th:text="${camp.title}">营地标题占位符</h2>
<p th:text="${camp.description}">营地描述占位符</p>
<!-- 如果需要更多字段,只需在DTO中添加并在模板中引用 -->
</div>
</body>
</html>说明:
虽然DTO是处理特定字段展示的最佳实践,但在某些情况下,Spring Boot也提供了其他控制JSON序列化的方法。
@JsonIgnore 是Jackson库提供的注解,用于在对象序列化为JSON时忽略某个字段。
示例: 如果你希望AdventureHolidays实体在任何JSON输出中都忽略typeOfAdventureHolidays字段,可以在该字段上添加@JsonIgnore:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document("adventureholidays")
public class AdventureHolidays {
@Id
private String id;
private String title;
private String description;
@JsonIgnore // 该字段在JSON序列化时将被忽略
private String typeOfAdventureHolidays;
// Getter/Setter...
}注意事项:
@JsonView 允许你定义不同的“视图”,并根据请求选择性地序列化实体字段。这适用于同一个实体需要在不同场景下暴露不同字段集合的情况。
示例 (简要介绍):
定义视图接口:
public class Views {
public static class Public {}
public static class Internal extends Public {}
}在实体字段上标记视图:
public class AdventureHolidays {
@JsonView(Views.Public.class)
private String title;
@JsonView(Views.Public.class)
private String description;
@JsonView(Views.Internal.class) // 只有Internal视图才能看到
private String typeOfAdventureHolidays;
// ...
}在控制器方法上指定视图:
@RestController
public class AdventureApiController {
@GetMapping("/publicCamps")
@JsonView(Views.Public.class)
public List<AdventureHolidays> getPublicCamps() {
return adventureHolidaysService.getRandomSummerCamps();
}
@GetMapping("/internalCamps")
@JsonView(Views.Internal.class)
public List<AdventureHolidays> getInternalCamps() {
return adventureHolidaysService.getRandomSummerCamps();
}
}注意事项:
在Spring Boot中,当需要将后端实体中的特定字段渲染到HTML页面时,使用DTO(数据传输对象)是推荐的最佳实践。它通过将数据模型与视图表示分离,提供了清晰的结构、增强了安全性,并提高了代码的可维护性。
关键步骤:
对于JSON序列化场景,@JsonIgnore适用于永久性地排除字段,而@JsonView则提供了更灵活的视图管理功能,但它们都与直接渲染HTML页面的需求有所不同。理解这些工具的用途和局限性,有助于开发者根据具体业务需求选择最合适的解决方案。
以上就是Spring Boot中将特定字段映射到HTML页面:DTO与视图渲染实践的详细内容,更多请关注php中文网其它相关文章!
HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号