临渊羡鱼,不如退而结网!是时候动手搞事情了!
我们的四大步骤:
①分析用户的视图(也就是浏览器要显示的东西),以及高层体系结构;
(这个就是所谓的前端吧?用JSP?JSP可以当成Html来用吧?高层体系结构,这个没听过)
②创建用于开发这个项目的开发环境;
(这个说简单也简单,说难也难啊!不少好汉被这个难住了)
③创建用于部署这个项目的部署环境;
(同②)
④对Web应用的各个组件完成迭代式的开发和测试。
(好高深。。。好学术。。。迭代式?)
我们的Web应用是一个啤酒顾问(Beer Advisor)。尽管这是一个非常小的应用,但我们要使用一个简单的MVC体系结构来构建(原来高层体系结构说的就是MVC体系结构)。
应用内部的具体流程:
1.客户请求得到form.html页面。
2.容器获得form.html页面。
3.容器把这个页面返回给浏览器,用户再在浏览器上回答表单上的问题。
4.用户问题回答完毕点击提交,浏览器把请求数据发送到容器。
5.容器根据URL找到正确的Servlet,并把请求传递给这个Servlet。
6.Servlet调用模型BeerExpert,寻求模型的帮助。
7.模型BeerExpert返回一个回答,Servlet把这个回答增加到请求对象。
8.Servlet把请求转发给JSP。(不理解,不懂是怎么转发的?)
9.JSP从请求对象得到回答。(不理解)
10.JSP为容器生成一个页面。(不理解,JSP怎么生成一个页面的?)
11.容器把这个页面返回给客户。
书中使用的是Tomcat5,由于第一章中的小例子在部署Web应用中就遇到了问题,这次还是先暂时跟着书来,如果还是不行就按照自己的方式进行修改。
前面的四大步骤先不管①②③,直接看④。第④步又分为5个小步骤:
④a:构建和测试用户最初请求的Html表单;④b:构建控制器Servlet的第一个版本;④c:为模型类构建一个测试类,然后构建模型类本身;④d:把Servlet升级到版本2,这个版本增加一个功能,可以调用模型类来得到啤酒建议; ④e:构建JSP,把Servlet升级到版本3,再增加一个功能,可以把表示分配到JSP完成,然后再测试整个应用。
④a:第一个表单页面的html
(保存为from.html,保存到F:/Beer/web目录下,这个是开发环境,然后再把这个文件复制到tomcat/webapps/Beer中,这个是部署环境)(部署环境的tomcat目录就是你安装的Tomcat的根目录,下面有webapps目录)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>Beer Selection</title> 6 </head> 7 <body> 8 <h1 style="text-align:center">Beer Selection Page</h1> 9 <form style="text-align:center" method="post" action="SelectBeer.do"> //anction表示表单数据提交到SelectBeer.do这个Servlet,这个名字只是一个逻辑名字,不是Servlet的真正名字,也不是Servlet类的类名 10 <p>Select beer characteristics</p> 11 <span>Color:</span> 12 <select name="color" size="1"> 13 <option value="light">light</option> 14 <option value="amber">amber</option> 15 <option value="brown">brown</option> 16 <option value="dark">dark</option> 17 </select> 18 <br /><br /> 19 <input style="text-align:center" type="submit" value="提交" /> 20 </form> 21 </body> 22 </html>
在开发环境中创建DD(部署描述文件——web.xml)
将其保存到F:/Beer/etc目录下,然后再复制到tomcat/webapps/Beer/WEB-INF目录下,这个是部署环境
<?xml version="1.0" encoding="utf-8"?> <web-app> <servlet> <servlet-name>Ch3 Beer</servlet-name> <servlet-class>com.example.web.BeerServlet</servlet-class> //Servlet真正的名字,com.example.web是包名 </servlet> <servlet-mapping> <servlet-name>Ch3 Beer</servlet-name> //Servlet的内部名字 <url-pattern>/SelectBeer.do</url-pattern> //Servlet的逻辑名字,对用户名字 </servlet-mapping> </web-app>
测试form.html页面:
上面做好后,启动Tomcat,在浏览器地址栏输入:http://127.0.0.1:8080/Beer/form.html,应该能正常显示form.html页面。
Servlet版本一:
(保存到开发环境:F:/Beer/src/com/example/web/BeerServlet.java)
package com.example.web; //包名 import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class BeerServlet extends HttpServlet{ //继承了HttpServlet public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ //将异常抛出 response.setContentType("text/html; charset=utf-8"); //设置响应对象的编码 PrintWriter out = response.getWriter(); out.println("Beer Selection Advice<br />"); //简单地输出一段信息 String c = request.getParameter("color"); //获取请求中的color属性 out.println("<br />Got beer color " + c); //把选中的颜色输出 } }
编译Servlet:
(先在F:/Beer文件夹中新建一个classes目录,用来存放.class文件)
win + r + cmd进入windows命令行,依次输入如下命令:
1 F: //先进入F盘 2 cd Beer //再进入Beer目录 3 javac -classpath F:/tomcat/common/lib/servlet-api.jar;classes -d classes -encoding utf8 src/com/example/web/BeerServlet.java //编译BeerServlet.java,其中tomcat/com/lib前面的盘根据自己的情况来写,我自己是F盘
编译成功后,会发现F:/Beer/classes目录下有com/example//web/BeerServlet.class文件,它编译的时候把包目录也自动生成了。(但是如果没有一开始的classes目录就会编译错误)
部署Servlet:
(复制F:Beer里面的classes目录,将其复制到部署目录F:/tomcat/webapps/Beer/WEB-INF目录下,所以部署目录会是:F:/tomcat/webapps/Beer/WEB-INF/classes/com/example/web/BeerServlet.class。部署完成之后,就测试Servlet。重启Tomcat,在浏览器地址栏中输入:http://127.0.0.1:8080/Beer/form.html 然后选择一个颜色,点击提交按钮,会看到一个新的页面,其中显示了你选择的颜色!
构建和测试模型
(模型,大多数情况下只是普通的Java代码,根本不知道自己会被Servlet调用。编写完后保存到开发环境:F:/Beer/src/com/example/model/BeerExpert.java)
1 package com.example.model; //包名 2 3 import java.util.*; 4 5 public class BeerExpert{ 6 public List getBrands(String color){ //返回一个List列表 7 List<String> brands = new ArrayList<>(); 8 if(color.equals("amber")){ 9 brands.add("Jack Amber"); 10 brands.add("Red Moose"); 11 }else{ 12 brands.add("Jail Pale Ale"); 13 brands.add("Gout Stout"); 14 } 15 return brands; 16 } 17 }
编译BeerExpert.java:
win + r + cmd 进入windows命令行,依次输入如下命令:
1 F: 2 cd Beer 3 javac -d classes -encoding utf8 src/com/example/model/BeerExpert.java
改进Servlet,版本2:
(调用模型来得到建议。在开发环境,F:/Beer/src/com/example/web/BeerServlet.java,修改版本1中的Servle)
1 package com.example.web; 2 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import java.io.*; 6 import java.util.*; //新增 7 import com.example.model.BeerExpert; //新增 8 9 public class BeerServlet extends HttpServlet{ 10 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ 11 response.setContentType("text/html; charset=utf-8"); 12 13 PrintWriter out = response.getWriter(); 14 out.println("Beer Selection Advice<br />"); 15 16 String c = request.getParameter("color"); 17 List result = new BeerExpert().getBrands(c); //新增 18 19 Iterator it = result.iterator(); //新增 20 while(it.hasNext()){ 21 out.print("<br />try: " + it.next()); 22 } 23 } 24 }
到这里还是没有理解前面具体流程中8、9、10。因为JSP还没有发挥作用。
重新编译BeerServlet.java
win + r + cmd ,进入命令行,和第一次编译BeerServlet的命令一样:
1 F: 2 cd Beer 3 javac -classpath F:/tomcat/common/lib/servlet-api.jar;classes -d classes -encoding utf8 src/com/example/web/BeerServlet.java //-classpath用来指定类路径,当指定多个类路径时,用“;”分号进行分隔,例如这句命令就指定了两个
把重新编译生成的BeerServlet.class复制到部署环境:F:/tomcat/webapps/Beer/WEB-INF/classes/com/example/web目录下,替换之前的版本1的BeerServlet.class。
部署模型的类文件:
把上面编译好的BeerExpert.class复制到的部署环境:F:/tomcat/webapps/Beer/WEB-INF/classes/com/example/model目录下,没有就自己新建一个model文件夹。
关闭Tomcat并重启,验证模型:
在浏览器地址栏输入http://127.0.0.1:8080/Beer/form.html,可以发现选择“amber”这个颜色时,会推荐Jack Amber 、Red Moose这两种酒,选择其他颜色时,会推荐Jail Pale、 AleGout Stout,说明模型成功运行了。
创建JSP,再部署JSP:
一个非常简单的JSP,命令为result.jsp,先保存在开发环境F:/Beer/web 文件夹中。然后复制这个result.jsp到部署环境:F:/tomcat/webapps/Beer 文件夹中,和上面的form.html同级。
1 <%@ page import="java.util.*" %> 2 <!doctype html> 3 <html> 4 <head> 5 <meta charset="utf-8" /> 6 <title>result_jsp</title> 7 </head> 8 <body> 9 <h1 style="text-align:center">Beer Recommendations JSP</h1> 10 11 <% 12 List<String> styles = (List)request.getAttribute("styles"); 13 Iterator it = styles.iterator(); 14 while(it.hasNext()){ 15 out.print("<br />try: " + it.next()); 16 } 17 %> 18 </body> 19 </html>
继续改进Servlet,得到版本3:
这一步,要把Servlet修改为“调用”JSP来生成输出(视图)。容器提供了一种称为“请求分派”的机制,允许容器管理的一个组件调用另一个组件。我们就会使用这种机制,Servlet从模型中得到消息,把它保存在请求对象中,然后把请求对象分派给JSP。
1 package com.example.web; 2 3 import javax.servlet.*; 4 import javax.servlet.http.*; 5 import java.io.*; 6 import java.util.*; 7 import com.example.model.BeerExpert; 8 9 public class BeerServlet extends HttpServlet{ 10 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ 11 //response.setContentType("text/html; charset=utf-8"); 12 //既然要由JSP来生成输出,Servlet的测试输出就没用了 13 //PrintWriter out = response.getWriter(); 14 //out.println("Beer Selection Advice<br />"); 15 16 String c = request.getParameter("color"); 17 List result = new BeerExpert().getBrands(c); 18 19 request.setAttribute("styles", result); //为请求对象设置一个属性,供JSP使用 20 21 request.getRequestDispatcher("result.jsp").forward(request, response); 22 // 为JSP实例化一个请求分派器(这不就是服务器端的跳转嘛?) 23 //forward(request, response),这个是使用请求分派器要求容器准备好JSP,并向JSP发送请求和响应 24 } 25 }
编译、部署和最后的测试:
1 F: 2 cd Beer 3 javac -classpath F:/tomcat/common/lib/servlet-api.jar;classes -d classes -encoding utf8 src/com/example/web/BeerServlet.java
把新的BeerServlet.class文件复制到部署环境中,替换掉之前的。
然后关闭Tomcat并重启,在浏览器中输入http://127.0.0.1:8080/Beer/form.html
选择颜色“amber”点击“提交”后,出现Beer Recommendations JSP页面,建议Jack Amber 和 Red Moose;
选择颜色“light”,建议 Jail Pale Ale 和 Gout Stou。说明JSP生成视图成功。
总结:
这一章学习了简单的MVC设计模式,写了一个BeerExpert类作为模型,这个模型的作用是根据控制器传给它的颜色,来做出酒的推荐;写了一个result.jsp来作为视图,这个视图的使用方式是:Servlet把用户提交的颜色参数传给模型,模型给出建议,建议保存在List列表中,Servlet根据生成的建议,对请求对象增加一个属性styles,这个属性styles中肯定要么指向建议,要么就保存着建议,然后Servlet在进行服务器端的跳转,跳转到result.jsp页面(书上说是实例化一个请求分派器,并向JSP发送请求和响应);然后JSP页面上有一段Java代码,这段代码获取请求上的属性styles,并把styles中的内容打印出来。