页面渲染,所谓渲染就是将数据和页面相结合,根据用户传送的数据不同,页面渲染后的内容也不同。页面渲染可以在服务器端完成,也可以在客户端完成。服务器渲染是将用户传来的数据在服务器端拼接成HTML后传给客户端,而客户端渲染是在客户端将服务器传来的数据拼接成HTML。
服务器渲染
这篇博客主要介绍一下服务器渲染。
我们可以用字符串拼接的方式,将数据拼接成HTML页面。下面我们用字符串拼接的方式完成一个猜数字web版的小游戏。
首先约定好交互方式。
通过get请求,从服务器得到一个页面响应,同时在服务器生成一个1-100的随机数。
通过post请求,将用户输入的数提交到服务器,在服务器比较用户输入的数和随机数的大小,将比较结果和次数返回。
约定好交互方式后,我们创建一个GuessNumServlet类,关联到/guess路径,用doGet方法实现第一个交互接口,doPost方法实现第二个交互接口。代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| @WebServlet("/guess") public class GuessNumServlet extends HttpServlet { public int num; public int count; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Random random = new Random(); num = random.nextInt(100)+1; resp.setContentType("text/html;charset=utf-8"); StringBuilder html = new StringBuilder(); html.append("<form action=\"guess\" method=\"post\">\n" + " <input type=\"text\" name=\"guessNum\">\n" + " <input type=\"submit\" value=\"确认输入\">\n" + " </form>"); resp.getWriter().write(html.toString()); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); int guessNum = Integer.parseInt(req.getParameter("guessNum")); String result =""; if(guessNum<num){ result="猜小了"; }else if(guessNum>num){ result="猜大了"; }else { result="猜对了"; } count++; StringBuilder html = new StringBuilder(); html.append("<form action=\"guess\" method=\"post\">\n" + " <input type=\"text\" name=\"guessNum\">\n" + " <input type=\"submit\" value=\"确认输入\">\n" + " </form>"); html.append("<div>"+result+"</div>"); html.append("<div>"+"猜的次数:"+count+"</div>"); resp.getWriter().write(html.toString()); } }
|
通过上段代码,我们发现十分简单的页面拼接起来却如此复杂,代码可读性不高。其实我们有一种更好的方式来完成服务器渲染,那就是模板引擎。
模板引擎
上面的代码Java和HTML代码都混在了一起,模板引擎可以将JAVA和HTML代码分离,将HTML放到单独的文件。HTML中需要变动的部分用占位符占位,当服务器计算响应完毕后,将HTML模板中的占位符替换成计算后的内容,返回给客户端。
Java中有很多模板引擎,这里用的是Thymeleaf 。
如何使用Thymeleaf,我们上面的猜数字小游戏为例,将上段代码改成模板引擎版本。
首先需要引入依赖。
1 2 3 4 5 6
| <!-- https: <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.12.RELEASE</version> </dependency>
|
接着创建一个HTML模板,创建路径是webapps/WEB-INF/templates
,
1 2 3 4 5 6 7 8
| <form action="GuessNum" method="post"> <input type="text" name="guessNum"> <input type="submit" value="确认输入"> </form> <div th:if="${!first}"> <div th:text="${result}"></div> <div th:text="${count}"></div> </div>
|
有$符号的地方就是一个占位符,最终会被替换成计算好的结果。
最后创建Servlet类:GuessNumTemplateEngine
。
- 创建一个TemplateEngine的类,这个类是服务器渲染的核心类。
- 初始化模板引擎:创建一个ServletContextTemplateResolver类的解析器,结合ServletContext使用,用来加载要渲染的文件,然后与TemplateEngine相关联。
- 通过WebContext类将模板文件的变量与Java中的变量相关联。
- 通过TemplateEngine的process方法完成渲染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| @WebServlet("/GuessNum") public class GuessNumTemplateEngine extends HttpServlet { public TemplateEngine engine = new TemplateEngine(); public int randomNum; public int count;
public void init() { ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(this.getServletContext()); resolver.setPrefix("/WEB-INF/templates/"); resolver.setSuffix(".html"); resolver.setCharacterEncoding("utf-8"); engine.setTemplateResolver(resolver); System.out.println("初始化完成"); }
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Random random = new Random(); randomNum = random.nextInt(100)+1; WebContext webContext = new WebContext(req,resp,getServletContext()); webContext.setVariable("first",true); resp.setContentType("text/html;charset=utf-8"); engine.process("guessNum",webContext,resp.getWriter()); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html; charset=utf-8"); int num = Integer.parseInt(req.getParameter("guessNum")); String result = ""; if (num < randomNum) { result = "猜低了"; } else if (num > randomNum) { result = "猜高了"; } else { result = "猜对了"; } count++; WebContext context = new WebContext(req,resp,getServletContext()); context.setVariable("first",false); context.setVariable("result",result); context.setVariable("count",count); engine.process("guessNum",context,resp.getWriter()); } }
|