您的位置 首页 java

Java Web轻松学40 – JSP初步使用

本系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考,希望能帮助更多(Java)码农和想成为(Java)码农的人。
 

目录

  1. 介绍
  2. 租房网现状
  3. 思路
  4. 共享模拟数据的 Filter
  5. 房源列表页面 – houses. jsp
  6. 验证
  7. 房源详情页面 – house-details.jsp
  8. 房源编辑表单页面 – house-form.jsp
  9. 处理房源编辑表单的提交 – HouseFormServlet
  10. 进一步改进 – include.jsp
  11. 总结

介绍

介绍了JSP的核心原理,本篇文章准备介绍JSP的初步使用。

大家一定要自己动手编写代码,运行验证,只有这样才能理解的更加透彻,印象也更加深刻。不知道大家有没有这样一种体会,就是明明自己看了不少技术相关的书籍,但是每到用的时候就忘记了相关技术如何使用,还是需要不断的上网搜索。

这还是说明我们动手实践比较少。在我看来,任何一门科学、技术、学问、专业都离不开以下四个环节:

  • 看资料、跟师傅,学习前人发现/发明的正确理论、总结的正确经验,系统化地和碎片化地(比如上课、报班、看书、互联网上的资讯和专栏等等)。
  • 身体力行,动手实践。
  • 经常思考和总结,多问几个为什么,多想想如何能更快更好的解决问题,想想自己是否能发明或发现新概念、新理论、新模型、新体系、新方法等等,可以利用发散思维、逆向思维等等。
  • 不断记录自己的学习体会、实践的过程和结论、思考和总结的过程和成果,可以简单的记录,也可以系统的记录,甚至可以写成书。

任何一门科学、技术、学问、专业都不是一日之功,需要长期的坚持这四个环节,所以必须从小就灌输,养成学、做、思、记的习惯。这四个环节是互相影响、互相交叉、互相促进、需要同时进行,不可偏废的。正所谓“纸上得来终觉浅,绝知此事要躬行”、“学而不思则罔,思而不学则殆”、“好记性不如烂笔头”等等。

虽说这四个环节不可偏废,但各门科学、技术、学问、专业还是有所侧重的,比如科学这个词感觉就偏理论学习和思考多一些,动手实践少一些;而技术这个词就相反。再比如工科偏动手实践多一些,理科偏理论研究多一些等等。

不好意思,又跑题。说那么多无非就是想说我们需要多敲敲代码。软件/编程这一行业被划分到工科,那就说明我们更要多动手实践。话说这应该是实践成本最低的工科行业了,只要一台个人电脑即可,还有各种开源的软件可用,要是建筑、土木、工业制造、各种勘探、化工、电力等等,要么需要去实地、要么需要建个实验室、要么需要买个机床。。。。。。

好了,不说废话了。我们仍然以前面开发的租房网应用(可以参考 和 )为基础,使用JSP技术来改造,至少需要达到的一个目标是让代码看起来更加清爽。

租房网现状

工程结构:

静态资源 – 登录页面login.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网 - 登录</title>
</head>
<body>
<form action="login.servlet" method="post">
<label for="user_name">用户名:</label><input type="text" id="user_name" name="userName" />
<label for="password">密码:</label><input type="password" id="password" name="password" />
<input type="submit" value="登录" />
</form>
</body>
</html>
 

房源实体类 – House.java:

package houserenter.entity;
public class House {
private String id;
private String name;
private String detail;
public House(String id, String name, String detail) {
super();
this.id = id;
this.name = name;
this.detail = detail;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
@Override
public String toString() {
return "House [id=" + id + ", name=" + name + ", detail=" + detail + "]";
}
}
 

处理登录请求的Servlet – LoginServlet.java:

package houserenter.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServlet request ;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/login.servlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = request.getParameter("userName");
String password = request.getParameter("password");

//这里需要验证用户是否已经注册,省略
System.out.println("userName: " + userName + ", password: " + password);

//用户登录成功,重定向到房源列表页面
response.sendRedirect("house.html?userName=" + userName);
}
}
 

处理房源相关请求(房源查找、房源详情、房源编辑)的Servlet – HouseServlet.java:

package houserenter.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Http Servlet ;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import houserenter.entity.House;
@WebServlet("/house.html")
public class HouseServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

private List<House> mockHouses;
@Override
public void init() {
mockHouses = new ArrayList<House>();
mockHouses.add(new House("1", "金科嘉苑3-2-1201", "详细信息"));
mockHouses.add(new House("2", "万科橙9-1-501", "详细信息"));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = request.getParameter("userName");
PrintWriter writer = response.getWriter();

writer.println("<!DOCTYPE html>");
writer.println("<html>");
writer.println("<head>");
writer.println("<meta charset="UTF-8">");
writer.println("<title>租房网</title>");
writer.println("</head>");
writer.println("<body>");

writer.println("<h1>你好,"+userName+"!欢迎来到租房网! <a href="login.html">退出</a></h1>");
writer.println("<br><br>");

String houseId = request.getParameter("houseId");
String editHouse = request.getParameter("editHouse");

if (houseId == null || houseId.isEmpty()) {
//查找该用户感兴趣的房源,这里省略
System.out.println("userName: " + userName + " access house.html!");
writer.println("<h6>共找到你感兴趣的房源 "+mockHouses.size()+" 条</h6>");
writer.println("<ul>");
for (House house : mockHouses) {
writer.println("<li><h2><a href="house.html?userName="+userName+"&houseId="+house.getId()+"">"+house.getName()+"</a></h2></li>");
}
writer.println("</ul>");
} else if (editHouse == null) {
//根据houseId查找该房源的详细信息
System.out.println("userName: " + userName + " access house.html for house detail!");
House target = null;
for (House house : mockHouses) {
if (houseId.equals(house.getId())) {
target = house;
break;
}
}

writer.println("<h2>"+target.getName()+"<a href="house.html?userName="+userName+"&houseId="+houseId+"&editHouse=true">编辑</a></h2>");
writer.println("<h3>"+target.getDetail()+"</h3>");
writer.println("<h4><a href="house.html?userName="+userName+"">回到列表</a></h4>");
} else {
//存在editHouse参数,返回指定房源的编辑页面
System.out.println("userName: " + userName + " access house.html to edit house!");
House target = null;
for (House house : mockHouses) {
if (houseId.equals(house.getId())) {
target = house;
break;
}
}
//writer.println("<form action="house.html?userName="+userName+"&houseId="+houseId+"" method="post">");
writer.println("<form action="house.html" method="post">");
writer.println("<input type="hidden" name="userName" value=""+userName+""/>");
writer.println("<input type="hidden" name="houseId" value=""+houseId+""/>");
writer.println("<label for="house_name">房源名字:</label><input type="text" id="house_name" name="houseName" value=""+target.getName()+"" />");
writer.println("<label for="house_detail">房源详细信息:</label><input type="text" id="house_detail" name="houseDetail" value=""+target.getDetail()+"" />");
writer.println("<input type="submit" value="提交" />");
writer.println("</form>");
}

writer.println("</body>");
writer.println("</html>");
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = request.getParameter("userName");
String houseId = request.getParameter("houseId");

//获取提交的房源信息,并保存
System.out.println("userName: " + userName + " access house.html to save house detail!");
String houseName = request.getParameter("houseName");
String houseDetail = request.getParameter("houseDetail");
for (House house : mockHouses) {
if (houseId.equals(house.getId())) {
house.setName(houseName);
house.setDetail(houseDetail);
break;
}
}

response.sendRedirect("house.html?userName="+userName+"&houseId="+houseId);
}
}
 

设置请求响应编码、登录验证的Filter – MyFirstFilter.java:

package houserenter.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebFilter("/house.html")
public class MyFirstFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;

String userName = httpServletRequest.getParameter("userName");

if (userName == null || userName.isEmpty()) {
System.out.println("invalid user!");
httpServletResponse.sendRedirect("login.html");
} else {
chain.doFilter(request, response);
}
}
}
 

思路

登录页面和LoginServlet目前还算简单,暂时可以不用改造。

HouseServlet的代码量稍微有点多(也不过一百多行),且夹杂着输出HTML内容,看着比较乱。从功能上来说虽然都与房源有关,但实际上动态生成的呈现给浏览器的是三个页面(房源列表、房源详情、房源编辑),所以可以考虑用三个JSP页面代替,咱就命名为:

  • houses.jsp
  • house-details.jsp
  • house-form.jsp

另外,因为涉及到一个房源编辑的表单,所以需要一个Servlet来处理表单的提交,就叫HouseFormServlet吧。

还有一个要提的是HouseServlet初始化了一些模拟数据,那这部分应该放在哪呢?因为一个JSP页面就相当于一个Servlet,所以原来的HouseServlet现在要改造成三个JSP页面,感觉模拟数据放在哪个JSP页面都不太合适,因为三个JSP页面都要访问同一份模拟数据才行。

于是问题变为:如何在多个JSP页面之间共享访问同一份数据?我先想到的是能不能在一个Filter中初始化模拟数据,然后让它拦截到这三个JSP页面的请求,然后在请求中使用setAttribute()方法将模拟数据挂上去,最后在JSP页面中使用请求的getAttribute()方法取出来。

好了,既然思路有了,那我们就大刀阔斧的干吧。

不过我们可以把之前的代码都保留着,另外编写新添加的JSP页面和Filter即可,当然也可以把之前的都删掉。

共享模拟数据的Filter

这次我们先编写我们的Filter。

在Filter中初始化模拟数据跟之前在HouseServlet中是类似的。Filter也有一个相同的生命周期方法init()(另一个相同的是destroy()方法),大家可以直接看看Filter的源码(如何查看源码可以参考 )。

不过Filter的这个init()方法是Servlet容器初始化Filter的时候就调用,与Servlet的init()方法在第一个请求到来时才调用是不同的。

Filter的doFilter()方法还是可以跟之前的Filter一样设置请求响应的编码以及进行登录验证,但最主要的是调用请求的setAttribute()方法把模拟数据挂载到该请求中。

在Eclipse中创建Filter还是可以使用New工具(可以参考 中的新建Java类部分),大家应该很容易知道该怎么填写相关信息,比如Filter的类名、初始化参数、映射(即拦截何种请求)。当然,你也可以新建空白的文件手动敲写所有代码。

package houserenter.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import houserenter.entity.House;
@WebFilter(
urlPatterns = { 
"/houses.jsp", 
"/house-details.jsp", 
"/house-form.jsp",
"house-form.servlet"
})
public class MySecondFilter implements Filter {
private List<House> mockHouses;
@Override
public void init(FilterConfig filterConfig) {
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
mockHouses = new ArrayList<House>();
mockHouses.add(new House("1", "金科嘉苑3-2-1201", "详细信息"));
mockHouses.add(new House("2", "万科橙9-1-501", "详细信息"));
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("BBBBBBBBBBBBBBBBBBBBBBBBBBBB");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;

Object obj = httpServletRequest.getAttribute("mockHouses");
if (obj == null) {
httpServletRequest.setAttribute("mockHouses", mockHouses);
}

String userName = httpServletRequest.getParameter("userName");

if (userName == null || userName.isEmpty()) {
System.out.println("invalid user!");
httpServletResponse.sendRedirect("login.html");
} else {
chain.doFilter(request, response);
}
}
}
 

上面的代码是我用New工具生成之后,把无用的注释、成员方法删掉之后,再加上初始化模拟数据的逻辑、doFilter的逻辑。

因为Filter接口的init()方法和destroy()方法是default的(JDK8才支持),因此可以不必实现。

注意,此Filter拦截的有哪些资源的访问请求!

doFilter的逻辑跟之前的相比,多了一个把mockHouses挂载到请求上去的部分。经过测试,不用强制转换成HttpServletRequest也是可以的。

对了,我在init()方法和doFilter()方法中都加了打印日志的部分,便于调试。

房源列表页面 – houses.jsp

现在开始编写我们的JSP页面,第一个是房源列表。

编写房源列表页面,实际上就是编写Servlet,只不过它们的HTML和Java内容是反着来的。所以你可以参照原来的HouseServlet中是怎样输出HTML的,你就可以把它们拷贝过来,然后把writer.println(“”)这种去掉,把HTML标签拿出来,而需要Java代码的地方就用JSP语法中的<%和%>括起来即可。

即编写JSP页面时,你就可以想象着这是在编写Servlet的service()方法(除去JSP的声明,即 <%! %> 括起来的,和page指令中的import部分以外),只不过HTML内容直接写,而Java代码需要 <% (或 <%= )和 %> 括起来。

但实际上,我们仍然可以使用New工具,从而生成通用的JSP模板页面(工具中可以选择是HTML 5、HTML 4.01、XHTML等等,我选的是HTML5)。

我们把这几个JSP页面都直接放在WebContent节点下,这样跟MySecondFilter的映射配置是一致的。

这里有一个小诀窍,就是写一部分代码验证一部分代码,不必整个页面编写完毕才验证,当然我们这几个页面都比较简单,也可以全部编写完毕再验证。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="houserenter.entity.House" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网</title>
</head>
<body>
<h1>你好,${param.userName}!欢迎来到租房网! <a href="login.html">退出</a></h1>
<br><br>
<%
List<House> mockHouses = (List<House>) request.getAttribute("mockHouses");
System.out.println(mockHouses);
%>
<h6>共找到你感兴趣的房源 <%=mockHouses.size() %> 条</h6>
<ul>
<%for (House house : mockHouses) { 
System.out.println(house); %>
<li><h2><a href="house-details.jsp?userName=${param.userName}&houseId=<%=house.getId() %>"><%=house.getName() %></a></h2></li>
<%} %>
</ul>
</body>
</html>
 

需要提一下:

  • 我把编码格式都改成了UTF-8,此文件一共三处地方。
  • page指令中导入Java类的部分可以在需要的时候编写,因为开始你也不知道需要什么类啊,后面不能解析类型的变量Eclipse会有提示。
  • 可以看到我用了三种元素: JSP脚本 <% %> )、 JSP表达式 <%= %> )、 EL表达式 ${ } ),这回总算清楚它们的基本用法了。
  • 比较奇葩的是for循环部分,尽然可以将前半部分用 <% %> 括起来、中间部分直接写HTML代码、最后一个花括弧也用 <% %> 括起来。不过也容易理解,这些都要被Servlet容器转换成Java代码的。可能看起来有点怪,但你要适应这种风格。
  • JSP表达式可以用在HTML标签的内容上,还可以用在HTML标签属性值的双引号中。EL表达式也是如此。
  • EL表达式的基本语法是用 ${ } 把内容括起来,内容一般是访问某个对象的属性,使用 点表达式 方括号表达式 均可,也支持一般的算术运算符、关系运算符、逻辑运算符等等。
  • JSP脚本中的request是 JSP的隐式对象 ,EL表达式中的param是 EL中的隐式对象 ,不过你都可以理解为Servelt容器在转换成Servlet代码时帮你定义的对象。param实际上就等价于request.getParameter()方法,也可以理解为param就是一个包括请求中所有参数的Map。
  • 加了一些打印日志的代码,便于调试。
  • 最后,<a>标签的跳转页面是房源详情页面house.jsp,URL中也可以携带参数。
  • URL中携带的参数与表单中提交的参数,都是使用request.getParameter()来访问的。
  • request.getAttribute()只能访问服务端添加的数据,而不是浏览器端用户发送过来的数据。

验证

我们可以一边开发JSP页面一边进行验证了,Eclispe中启动Tomcat之后也不用关闭,它会自动检测JSP页面和Java代码的变化,进行重新编译和发布,不过有时候修改代码后还是重新发布应用比较踏实。

先别忘了修改我们的LoginServlet重定向的地址:

response.sendRedirect("houses.jsp?userName=" + userName);
 

OK,从浏览器中访问租房网的登录页面login.html:

随便输入用户名和密码,点击登录:

耶,完全没有问题!继续编写其他两个JSP页面。

房源详情页面 – house-details.jsp

有了前面的分析,相信大家都能够理解一般的JSP代码了,那就直接上代码吧。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="houserenter.entity.House" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网</title>
</head>
<body>
<h1>你好,${param.userName}!欢迎来到租房网! <a href="login.html">退出</a></h1>
<br><br>
<%
List<House> mockHouses = (List<House>) request.getAttribute("mockHouses");
String houseId = request.getParameter("houseId");
House target = null;
for (House house : mockHouses) {
if (houseId.equals(house.getId())) {
target = house;
break;
}
}
%>
<h2><%=target.getName() %><a href="house-form.jsp?userName=${param.userName }&houseId=<%=target.getId() %>">编辑</a></h2>
<h3><%=target.getDetail() %></h3>
<h4><a href="houses.jsp?userName=${param.userName }">回到列表</a></h4>
</body>
</html>
 

还是主要用了JSP脚本、JSP表达式和EL表达式三个技术。

不过,JSP脚本看着似乎有点长。

房源编辑表单页面 – house-form.jsp

还是直接上代码。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="houserenter.entity.House" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网</title>
</head>
<body>
<h1>你好,${param.userName}!欢迎来到租房网! <a href="login.html">退出</a></h1>
<br><br>
<%
List<House> mockHouses = (List<House>) request.getAttribute("mockHouses");
String houseId = request.getParameter("houseId");
House target = null;
for (House house : mockHouses) {
if (houseId.equals(house.getId())) {
target = house;
break;
}
}
%>
<form action="house-form.servlet" method="post">
<input type="hidden" name="userName" value="${param.userName}"/>
<input type="hidden" name="houseId" value="<%=target.getId() %>"/>
<label for="house_name">房源名字:</label><input type="text" id="house_name" name="houseName" value="<%=target.getName() %>" />
<label for="house_detail">房源详细信息:</label><input type="text" id="house_detail" name="houseDetail" value="<%=target.getDetail() %>" />
<input type="submit" value="提交" />
</form>
</body>
</html>
 

注意,此时表单的提交路径是:house-form.servlet

所以,后面编写HouseFormServlet时,配置其URL映射模式要与此一致。

处理房源编辑表单的提交 – HouseFormServlet

无非就是提取表单提交的数据,然后保存到我们的模拟数据中,最后重定向回该房源的详情页面。

package houserenter.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import houserenter.entity.House;
@WebServlet("/house-form.servlet")
public class HouseFormServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<House> mockHouses = (List<House>) request.getAttribute("mockHouses");
String houseId = request.getParameter("houseId");
House target = null;
for (House house : mockHouses) {
if (houseId.equals(house.getId())) {
target = house;
break;
}
}

String houseName = request.getParameter("houseName");
target.setName(houseName);

String houseDetail = request.getParameter("houseDetail");
target.setDetail(houseDetail);

String userName = request.getParameter("userName");
response.sendRedirect("house-details.jsp?userName=" + userName + "&houseId=" + houseId);
}
}
 

至此,全部JSP页面和Servlet代码已经编写完毕,大家可以自行验证,应该没有问题。

进一步改进 – include.jsp

虽然已经完成了全部工作,运行也没有问题,但是很明显,三个JSP页面中开头的很大一部分都是重复的,这时候JSP中的include指令就排上用场了。

我们把这部分重复的提取出来,形成一个独立的JSP文件:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.List" %>
<%@ page import="houserenter.entity.House" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>租房网</title>
</head>
<body>
<h1>你好,${param.userName}!欢迎来到租房网! <a href="login.html">退出</a></h1>
<br><br>
 

然后改造三个JSP页面,比如房源列表页面houses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="include.jsp"%>
<%
List<House> mockHouses = (List<House>) request.getAttribute("mockHouses");
System.out.println(mockHouses);
%>
<h6>共找到你感兴趣的房源 <%=mockHouses.size() %> 条</h6>
<ul>
<%for (House house : mockHouses) { 
System.out.println(house); %>
<li><h2><a href="house-details.jsp?userName=${param.userName}&houseId=<%=house.getId() %>"><%=house.getName() %></a></h2></li>
<%} %>
</ul>
</body>
</html>
 

直接使用include指令:

<%@ include file="include.jsp"%>
 

但是,要注意,房源列表页面houses.jsp中仍然需要下面的page指令,否则会有中文乱码:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
 

实际上,include指令也是由Servlet容器在将JSP页面生成Servlet代码的过程中解析,并用包含的JSP页面的内容替换该指令,完全是解析阶段发生的故事。

最后,我们的租房网的工程结构变成:

总结

虽然我们的租房网还不够完美,但总算比之前纯粹使用Servlet的时候干净清爽多了,页面结构也比较清晰合理。

当然,还有很多需要改进的地方,读者朋友们自己可以思考思考。

  • 养成学、做、思、记的习惯;我写这些文章,也就是记,鼓励大家也多记;
  • JSP的本质就是由Servlet/JSP容器转换成Servlet代码;
  • Servlet代码中HTML内容需要writer括起来;而JSP页面中Java代码需要<%%>括起来;
  • 加打印日志的代码,便于调试;
  • 一边开发、一边测试/验证;
  • EL表达式的基本语法是用 ${ } 把内容括起来;
  • JSP和EL都有隐式对象,实际上是Servlet/JSP容器生成并传进来的;
  • 要有演化思维,或迭代思维,或最小可用产品思维;
  • 再次运用消除重复思维,重复的地方总是可以改进的。

文章来源:智云一二三科技

文章标题:Java Web轻松学40 – JSP初步使用

文章地址:https://www.zhihuclub.com/188334.shtml

关于作者: 智云科技

热门文章

网站地图