本文共 4061 字,大约阅读时间需要 13 分钟。
商品详情浏览量比较大,并发高,我们会独立开启一个微服务,用来展示商品详情。
服务:leyou-goods-web,其端口为8084 nginx --port=8084 需要portal服务的9092端口提供图片解析后台接口
使用 thymeleaf修改item.html
我们从leyou-portal中复制item.html模板到当前项目resource目录下的templates中:
nginx反向代理
把以/item开头的请求,代理到我们的8084端口。编写跳转controller
在leyou-goods-web中编写controller,接收请求,并跳转到商品详情页:
@Controller@RequestMapping("item")public class GoodsController { /** * 跳转到商品详情页 * @param model * @param id * @return */ @GetMapping("{id}.html") public String toItemPage(Model model, @PathVariable("id")Long id){ return "item"; }}
商品微服务提供接口
创建FeignClient 我们在leyou-goods-web服务中,创建FeignClient:创建一个GoodsService,在里面来封装数据模型。
商品详情是HTML代码,我们不能使用 th:text
,应该使用th:utext
在页面的第444行左右:
而静态的HTML页面可以部署在nginx中,从而大大提高并发能力,减小tomcat压力。
Thymeleaf除了可以把渲染结果写入Response,也可以写到本地文件,从而实现静态化。
数据详情1.商品详情页 thymeleaf语法 1.引入thymeleaf启动器 2.关闭thymeleaf缓存:spring.thymeleaf.cache=false ctrl+shift+f9 3.th:text th:utext th:each ${ } /*[[${数据模型}]]*/ 4.页面数据的组织2.页面静态化 context:thymeleaf的运行上下文,存放数据模型 TemplateResolver:模板解析器,模板的位置,名称,后缀信息 TemplateEngine:模板解析引擎 templateEngine.process("item", context, printWriter)
@Servicepublic class GoodsHtmlService { @Autowired private GoodsService goodsService; @Autowired private TemplateEngine templateEngine; private static final Logger LOGGER = LoggerFactory.getLogger(GoodsHtmlService.class); /** * 创建html页面 * * @param spuId * @throws Exception */ public void createHtml(Long spuId) { PrintWriter writer = null; try { // 获取页面数据 MapspuMap = this.goodsService.loadModel(spuId); // 创建thymeleaf上下文对象 Context context = new Context(); // 把数据放入上下文对象 context.setVariables(spuMap); // 创建输出流 File file = new File("C:\\project\\nginx-1.14.0\\html\\item\\" + spuId + ".html"); writer = new PrintWriter(file); // 执行页面静态化方法 templateEngine.process("item", context, writer); } catch (Exception e) { LOGGER.error("页面静态化出错:{},"+ e, spuId); } finally { if (writer != null) { writer.close(); } } } /** * 新建线程处理页面静态化 * @param spuId */ public void asyncExcute(Long spuId) { ThreadUtils.execute(()->createHtml(spuId)); /*ThreadUtils.execute(new Runnable() { @Override public void run() { createHtml(spuId); } });*/ }}
优化:新建线程处理页面静态化
线程工具类:public class ThreadUtils { private static final ExecutorService es = Executors.newFixedThreadPool(10); public static void execute(Runnable runnable) { es.submit(runnable); }}
假如大部分的商品都有了静态页面。那么用户的请求都会被nginx拦截下来,根本不会到达我们的leyou-goods-web
服务。只有那些还没有页面的请求,才可能会到达这里。
因此,如果请求到达了这里,我们除了返回页面视图外,还应该创建一个静态页面,那么下次就不会再来麻烦我们了。
所以,我们在GoodsController中添加逻辑,去生成静态html文件:
@GetMapping("{id}.html")public String toItemPage(@PathVariable("id")Long id, Model model){ // 加载所需的数据 Mapmap = this.goodsService.loadModel(id); // 把数据放入数据模型 model.addAllAttributes(map); // 页面静态化 this.goodsHtmlService.asyncExcute(id); return "item";}
注意:生成html 的代码不能对用户请求产生影响,所以这里我们使用额外的线程进行异步创建。
接下来,我们修改nginx,让它对商品请求进行监听,指向本地静态页面,如果本地没找到,才进行反向代理:
server { listen 80; server_name www.leyou.com; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location /item { # 先找本地 root html; if (!-f $request_filename) { #请求的文件不存在,就反向代理 proxy_pass http://127.0.0.1:8084; break; } } location / { proxy_pass http://127.0.0.1:9002; proxy_connect_timeout 600; proxy_read_timeout 600; }}
转载地址:http://nxxab.baihongyu.com/