Spring Boot从Service取数据到Controller展示UI报错求助
Spring Boot数据展示报错修复方案
问题场景
在Spring Boot项目中尝试从Service层读取数据到Controller层,最终在UI展示时出现错误。
错误信息
ERROR 20984 --- [nio-8080-exec-2] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/countries] as the response has already been committed. As a result, the response may have the wrong status code.
数据库数据
mysql> select * from country; +----+-------------+------+---------------+---------------+-------------+ | id | capital | code | continent | description | nationality | +----+-------------+------+---------------+---------------+-------------+ | 1 | Washington | 01 | North America | United States | American | | 2 | Addis Ababa | 01 | Africa | Ethiopia | Ethiopian | +----+-------------+------+---------------+---------------+-------------+
各层代码
实体类(Model)代码
@Entity @Data @NoArgsConstructor @AllArgsConstructor @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class Country { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String code; private String capital; private String description; private String nationality; private String continent; @OneToMany(mappedBy="country") private List<State> states; }
Repository代码
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.kindsonthegenius.FleetApp.models.Country; @Repository public interface CountryRepository extends JpaRepository<Country, Integer> {}
Service代码
@Service public class CountryService { @Autowired private CountryRepository countryRepository; public List<Country> getCountries(){ return countryRepository.findAll(); } }
Controller代码
@Controller public class CountryController { @Autowired private CountryService countryService; @GetMapping("/countries") public String goCountry(Model model) { List<Country> countryList = countryService.getCountries(); model.addAttribute("countries", countryList); return "country"; } }
UI(Thymeleaf)代码
<table class="table"> <thead> <tr> <th scope="col">id</th> <th scope="col">Description</th> <th scope="col">Capital</th> </tr> </thead> <tbody> <tr th:each="country : ${countries}"> <td th:text="${country.id}"></td> <td th:text="${country.description}"></td> <td th:text="${country.capital}"></td> </tr> </tbody> </table>
修复步骤
这个错误核心原因是懒加载导致视图渲染时会话已关闭,引发未捕获异常后,Spring尝试渲染错误页面但响应已提交,最终出现冲突。以下是具体修复方案:
处理懒加载关联问题
@OneToMany默认是懒加载(FetchType.LAZY),Thymeleaf渲染页面时即使未显式调用states,框架可能会触发关联字段的序列化,此时EntityManager已关闭,抛出LazyInitializationException。- 方案一:修改关联为急加载(适合小数据量场景)
在@OneToMany注解中添加加载策略:@OneToMany(mappedBy="country", fetch = FetchType.EAGER) private List<State> states; - 方案二:使用JOIN FETCH提前加载关联数据(性能更优)
在CountryRepository中添加自定义查询:
然后修改Service层方法:@Repository public interface CountryRepository extends JpaRepository<Country, Integer> { @Query("SELECT c FROM Country c JOIN FETCH c.states") List<Country> findAllWithStates(); }public List<Country> getCountries(){ return countryRepository.findAllWithStates(); }
- 方案一:修改关联为急加载(适合小数据量场景)
验证视图文件位置
确保country.html视图文件放在src/main/resources/templates/目录下,文件缺失会触发404,也可能引发类似响应提交冲突。添加异常捕获
在Controller层捕获异常,避免未处理的异常导致响应提交后再触发错误页面渲染:@Controller public class CountryController { @Autowired private CountryService countryService; @GetMapping("/countries") public String goCountry(Model model) { try { List<Country> countryList = countryService.getCountries(); model.addAttribute("countries", countryList); return "country"; } catch (Exception e) { e.printStackTrace(); model.addAttribute("error", "加载数据失败"); return "error"; // 需确保templates目录下有error.html视图 } } }
内容的提问来源于stack exchange,提问作者Tefera Tilaye
相关产品推荐
相关产品推荐

