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

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

看资料、跟师傅,学习古人创造/发明的精确理论、总结的精确履历,系统化地和碎片化地(比如上课、报班、看书、互联网上的资讯和专栏等等)。
身体力行,动手实践。
常常思考和总结,多问几个为什么,多想想如何能更快更好的办理问题,想想自己是否能发明或创造新观点、新理论、新模型、新体系、新方法等等,可以利用发散思维、逆向思维等等。
不断记录自己的学习体会、实践的过程和结论、思考和总结的过程和成果,可以大略的记录,也可以系统的记录,乃至可以写成书。

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

jsp截取节点我的Java Web之路40  JSP初步应用 Python

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

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





好了,不说废话了。
我们仍旧以前面开拓的租房网运用(可以参考这篇文章和这篇文章)为根本,利用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;}@Overridepublic 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.HttpServletRequest;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.HttpServlet;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;@Overridepublic 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.jsphouse-details.jsphouse-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;@Overridepublic 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容器天生并传进来的;要有蜕变思维,或迭代思维,或最小可用产品思维;再次利用肃清重复思维,重复的地方总是可以改进的。