图源:
就像在上篇中展示的那样,要向客户端输出一个页面,最简单的方式是直接用Java代码向输出流写入Html代码。这样的方式虽然简单直观,但存在很多隐患,而且很难用于编写复杂的Html代码。
此时我们就需要其他技术来输出Html页面,JSP就是早期的其中一种方式。
基础
JSP是Java Server Pages的缩写,是Java服务器用于“组装”和生成Html页面的技术。其写法和作用与其它语言中常见的模版语言类似。利用JSP,我们可以很容易地将Java代码嵌入静态的Html代码中。
下面我们利用JSP编写一个简单的示例,在页面上显示当前时间,以及一个随机的欢迎语。
<%page import="java.time.format.DateTimeFormatter" %>
<%page import="java.time.LocalDateTime" %>
<%page import="java.util.Random" %><%--
Created by IntelliJ IDEA.
User: 70748
Date: 2023/3/30
Time: 10:49
To change this template use File | Settings | File Templates.
--%>
<%page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>now time is <%= LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")) %></h1>
<div>
<%
String[] messages = {"今天天气不错","你吃了吗","没吃"};
Random random = new Random();
int i = random.nextInt(messages.length);
out.print(messages[i]);
%>
</div>
</body>
</html>
简单介绍一下示例中的JSP简单语法:
-
<%@ page import="xxx" %>
可以向当前JSP中导入Java的包和类。 -
<%-- xxx --%>
是JSP的注释。 -
<%= xxx %>
可以将一个Java变量直接输出到最终的Html中。 -
<% xxx %>
可以在JSP中嵌入Java代码。
此外,JSP还包含一些预定义局部变量:
-
out
:代表输出响应报文的输出流,即HttpServletResponse.getWriter()
返回的对象。 -
session
:代表当前Http请求关联的Session,即HttpServletRequest.getSession()
返回的对象。 -
request
:代表HttpServletRequest
对象。
这里的JSP命名为time.jsp
,并保存到项目的/src/main/webapp/
目录下。之后打包成war后由Tomcat加载,通过http://localhost:8081/hello/time.jsp
访问就能看到效果。
JSP是一个古早技术,现在已经被各种新的模版语言代替了,所以只需要了解即可。
MVC
MVC是一种网络技术从Web1.0到Web2.0演进后自然而然产生的一种朴素想法,越来越复杂的动态网页需求导致我们需要将Web应用的不同部分尽可能解耦,以更灵活地构建和修改应用。
利用JSP和Servlet,也可以演示一些很简单的体现了MVC核心概念的示例,比如可以将之前应用中以纯字符串输出方式构建的用户主页修改为用Servlet和JSP组装而成:
package cn.icexmoon.java.note.ch28;
// ...
urlPatterns = "/home")
(public class HomeServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ...
//已经登录
// resp.setContentType("text/html; charset=UTF-8");
// PrintWriter writer = resp.getWriter();
//显示天气
// writer.print(String.format("<div>%s</div>", nowWeather));
// writer.print("<h1>This is your home page</h1>");
// writer.print(String.format("<div>hello, %s</div>", name));
// writer.print("<div><a href=\"/hello/exit\">注销</a></div>");
// writer.flush();
req.setAttribute("nowWeather", nowWeather);
req.setAttribute("name", name);
req.getRequestDispatcher("/WEB-INF/home.jsp").forward(req, resp);
}
private static String getWeather() {
String[] weathers = {"天气晴 15度~20度", "天气阴 10度~20度", "多云转阴 15度~22度"};
Random random = new Random();
int i = random.nextInt(weathers.length);
return weathers[i];
}
private String getWeatherFromCookie(HttpServletRequest req) {
Cookie[] cookies = req.getCookies();
if (cookies == null) {
return null;
}
for (Cookie c : cookies) {
if (c.getName().equals("weather")) {
String weather = c.getValue();
weather = new String(Base64.getDecoder().decode(weather), Charset.forName("UTF-8"));
return weather;
}
}
return null;
}
// ...
}
对应的JSP:
<%--
Created by IntelliJ IDEA.
User: 70748
Date: 2023/3/30
Time: 14:08
To change this template use File | Settings | File Templates.
--%>
<%page contentType="text/html;charset=UTF-8" language="java" %>
<% String nowWeather = (String) request.getAttribute("nowWeather"); %>
<% String name = (String) request.getAttribute("name"); %>
<html>
<head>
<title>Title</title>
</head>
<body>
<div><%= nowWeather %></div>
<h1>This is your home page</h1>
<div>hello, <%= name %></div>
<div><a href="/hello/exit">注销</a></div>
</body>
</html>
这个JSP文件保存到/src/main/webapp/WEB-INF/home.jsp
,这样做的目的是为了不让浏览器直接访问到该JSP页面(/webapp/WEB-INF/
目录受到保护,Tomcat不会允许客户端直接访问)。
在Servlet类中,以HttpServletRequest.getRequestDispatcher().forward()
的方式加载Jsp页面并输出到客户端。组装Jsp时需要从服务端加载的对象,可以通过HttpServletRequest.setAttribute()
方法添加到HttpServletRequest
对象,该对象会传递给JSP,并且可以通过JSP的预定义局部对象request
访问。
这个简单的示例可以看到将Controller(Servlet)和Viewer(JSP)分离有以下好处:
-
Controller中的代码更简洁,不需要包含拼装Html之类的视图相关代码,仅包含关键的业务代码。
-
Viewer的代码更直观和简洁,主体是Html代码,只需要嵌入部分Java代码。
MVC本身是一个很宏大的命题,这里只是展示了如何结合Servlet和JSP以体现一些MVC的思想,不做更深入的探讨。
谢谢阅读,本文的完整示例代码可以通过获取。
文章评论