Java Spring中如何从RestController直接获取WebController渲染后的模板字符串
实现方案
存在无需发起内部网络调用的实现方案,直接通过Thymeleaf模板引擎主动渲染模板即可,性能和可维护性都优于同服务内部发HTTP请求的实现。
核心实现思路
Spring集成Thymeleaf后会自动装配SpringTemplateEngine实例,我们可以直接注入该实例,手动传入模板所需参数渲染指定模板,直接得到渲染完成的HTML字符串。
具体实现步骤
- 注入Thymeleaf模板引擎并改造InvoiceController
删除原有的RestHelper依赖,改为注入SpringTemplateEngine直接渲染模板:
import org.springframework.beans.factory.annotation.Autowired; import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.context.Context; @RestController @RequestMapping(path = "/invoice") public class InvoiceController { @Autowired private S3Service s3Service; // 注入Thymeleaf模板引擎 @Autowired private SpringTemplateEngine templateEngine; @PostMapping public ResponseEntity<String> getInvoiceUrl(@RequestBody InvoiceRequest request) { // 构造Thymeleaf上下文对象,用来存储模板渲染所需参数 Context context = new Context(); // 填充模板参数,和原有往Model里塞参数的逻辑完全一致 context.setVariable("labDetails", request.getLabDetails()); context.setVariable("order", request.getOrder()); context.setVariable("orderItems", request.getOrderItems()); // 直接渲染名为invoice的模板,得到完整HTML字符串 String invoicePage = templateEngine.process("invoice", context); String invoiceUrl = s3Service.uploadToS3AndGetUrl(invoicePage); return new ResponseEntity<>(invoiceUrl, HttpStatus.OK); } }
- 可选优化(避免重复代码)
如果需要复用原有InvoicePageController的参数填充逻辑,可以把参数填充逻辑抽为公共方法,两个控制器共用即可:
// 抽离公共的模板参数填充逻辑 @Service public class InvoiceTemplateService { public void fillContext(InvoiceRequest request, Context context) { context.setVariable("labDetails", request.getLabDetails()); context.setVariable("order", request.getOrder()); context.setVariable("orderItems", request.getOrderItems()); } // 适配Model类型,供原InvoicePageController使用 public void fillModel(InvoiceRequest request, Model model) { model.addAttribute("labDetails", request.getLabDetails()); model.addAttribute("order", request.getOrder()); model.addAttribute("orderItems", request.getOrderItems()); } }
该方案完全跳过了网络请求环节,不需要处理HTTP调用的超时、异常等问题,执行效率和可维护性都更高。
内容的提问来源于stack exchange,提问作者Abhishek kumar singh
相关产品推荐
相关产品推荐

