前三章内容
为什么使用Servlet & JSP
我们只说明要点,因为第一章的内容重点并不是Servlet与JSP。此后我们将重点介绍这两种技术,而不是现在。
要点:
- HTTP代表超文本传输协议(HyperText Transfer Protocol),这是Web上使用的网络协议。HTTP运行在TCP/IP之上。
- HTTP使用一种请求/响应模型,客户做出一个HTTP请求,Web服务器返回一个HTTP响应,再由浏览器(根据响应内容类型)确定如何进行处理。
- 如果来自服务器的响应是一个HTML页面,就会把HTML增加到HTTP响应中。
- HTTP请求包括请求URL(客户想要访问的资源)、HTTP方法(GET、POST等),以及(可选)表单参数数据(也称为”查询串”)。
- HTTP响应包括一个状态码、内容类型(也称为MIME类型),以及响应的实际内容(HTML、图像等)。
- GET请求会把表单数据追加到URL的最后。
- POST请求将表单数据包括在请求的体中。
- MIME类型告诉浏览器要接收哪一类数据,一遍浏览器知道如何加以处理(呈现HTML、显示图片、播放音乐等)。
- URL代表同意资源定位符(Uniform Resource Locator)。Web上的每个资源都有自己的唯一地址,都采用这种URL格式。首先是一个协议,然后是服务器名以及一个可选的端口号,再后面通常是一个特定的路径和资源名。如果URL对应一个GET请求,那么它还可能包含一个可选的查询串。
- Web服务器擅长提供静态HTML页面,但是如果需要页面中有动态创建(如当前时间),就需要某种辅助应用于服务器协作。如果不用Java术语来说,这些辅助应用(大多数用Perl编写)通常称为CGI,这代表公共网关接口(Common Gateway Interface)。
- 把HTML放在println()语句中的做法很糟糕,也很容易出错,不过JSP可以解决这个问题,它允许把Java放在HTML页面中,而不是把HTML放在JAVA代码中。
Web 应用体系结构
高层Web应用体系结构
- 对于每一种HTTP方法(如get、post、head等),描述该方法的用途,以及该HTTP方法协议的技术特性,并列出客户(通常是一个Web浏览器)会因为哪些原因使用这种方法,明确对应这种HTTP方法的相应HttpServlet方法。
- 描述Servlet生命周期的作用和实践序列:
- servlet类的加载
- servlet实例化
- 调用init方法
- 调用service方法
- 调用destroy方法
- 构建Web应用的文件和目录结构,可能包含:
- 静态内容
- JSP页面
- servlet类
- 部署描述文件
- 标记库
- JAR文件
- Java类文件并描述如何保护资源文件避免HTTP访问
- 描述一下各个部署描述文件元素的作用和语义:
- servlet实例
- servlet名
- servlet类
- servlet初始化参数
- URL与servlet的映射
什么是容器?
Servlet没有main()方法。它们受控于另一个Java应用,这个Java应用称为容器(比如Tomcat,PS:Apache是Web服务器。这两者是有区别的)。
容器能什么?
- 通信支持,无需我们自己建立ServerSocket、监听端口、创建流等。我们只需要实现自己的业务逻辑即可。
- 生命周期管理,容器控制着servlet的生与死。它会负责加载类、实例化和初始化servlet、调用servlet方法,并使servlet实例能够被垃圾回收。
- 多线程支持,容器会自动地为它接收每个servlet请求创建一个新的线程。针对客户的请求,如果servlet已经运行完相应的HTTP服务方法,这个线程就会死掉。这并不是说不用考虑线程安全,还是会遇到同步问题。
- 声明方式实现安全,利用容器,可以使用XML部署描述文件来配置(和修改)安全性,而不必将其硬编码写到servlet(或其他)类代码中。
- JSP支持,容器负责把JSP代码翻译成真正的Java。
容器如何处理请求?
- 用户点击一个URL链接
- 容器创建两个对象:HttpServletResponse、HttpServletRequest对象
- 容器根据URL找到正确的servlet,并将响应和请求对象传递给servlet线程
- 容器调用servlet的service()方法,根据不同的请求调用不同的方法(如doGet()、doPost()方法)
- doGet()、doPost()做完事情后,将生成一个动态页面填入到HttpServletResponse对象中
- 线程结束,容器将响应对象转换为一个HTTP响应,把它发回给客户,然后删除请求和响应对象。
MVC模式
- M=model模型
- V=view视图
- C=console控制器
MVC 迷你教程
Web 应用部署
- 构建一个Web应用的文件和目录结构可能包含
- 静态内容
- JSP页面
- servlet类
- 部署描述文件
- 标记库
- JAR文件
- Java类文件
- 描述一下各个部署描述文件元素的作用和语义:
- error-page
- init-param
- mime-mapping
- servlet
- servlet-class
- servlet-mapping
- servlet-name
- welcome-file
- 为以下各个部署描述文件元素构造正确的结构
- error-page
- init-param
- mime-mapping
- servlet
- servlet-class
- servlet-name
- welcome-file
构建一个真正的Web应用
我们的4大步骤:
- 分析用户的视图,以及高层体系结构。
- 创建用于开发这个项目的开发环境。
- 创建用于部署这个项目的部署环境。
- 对Web应用的各个主键完成的开发和测试(迭代式的开发和测试)。
用户视图:
开发环境
部署环境
构建应用的路线图
- 构建和测试用户最初请求的HTML表单。
- 构建控制器servlet第一个版本,并且用HTML表单测试这个控制器。这个版本通过HTML表单来调用,并打印出它接收的参数。
- 为专家/模型类构建一个测试类,然后构建并测试专家/模型类本身。
- 把servlet升级到第2版。这个版本增加了一个功能,可以调用模型类来得到啤酒建议。
- 构建JSP,把servlet升级到第3版本(再增加一个功能,可以把表示分派到JSP完成),然后再测试整个应用。
版本1
前端代码:
<!DOCTYPE html>
<html>
<head>
<title>form.html</title>
</head>
<body>
<h1 align="center">
Beer Selection Page
</h1>
<form action="SelectBeer.do" method="post">
<span>Select beer characteristics</span>
<br/>
<span>Color:</span>
<select name="color" size="1">
<option value="light">light</option>
<option value="amber">amber</option>
<option value="brown">brown</option>
<option value="dark">dark</option>
</select>
<br/>
<br/>
<br/>
<center>
<input type="submit" value="Submit">
</center>
</form>
</body>
</html>
将其放至部署环境中,并且启动tomcat。(启动tomcat可以进入到tomcat的/bin目录下,启动start.bat,以上都是通过DOS来操作)
这样,我们的网页就放在服务器上面了。可以试试局域网能够访问你的网站,不过记住,让局域网的8080端口处于可以转发的状态。
控制器servlet的第1版(注意:如果报GBK错,就把注释去掉)
servlet代码:
package com.example.web;
//servlet接口的包
import javax.servlet.*;
//httpservlet的包
import javax.servlet.http.*;
//io流的包
import java.io.*;
//几乎大部分的servlet都需要继承HttpServlet类
public class BeerSelect extends HttpServlet {
//重写了HttpServlet的doPost方法
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
//这个方法来自ServletResponse接口
response.setContentType("text/html");
//获取响应的输出流
PrintWriter out = response.getWriter();
out.println("Beer Selection Advice<br/>");
//这个方法来自于ServletRequest接口
String color = request.getParameter("color");
out.println("<br/>Got beer color "+ color);
}
}
编写完代码后,进行编译和连接,并将其放置开发环境和部署环境的classes目录下。
上图只是把class放置开发环境中,还需要复制一份class到tomcat的WEB-INF中(注意命令中的分号有2个)。
创建DD放至开发环境的/beerV1/etc/目录下(注意:如果报错就把注释去掉)
<!-- 这段照着敲就行了,以后再知道意思 -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>Ch3 Beer</servlet-name>
<servlet-class>com.example.web.BeerSelect</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Ch3 Beer</servlet-name>
<url-pattern>/SelectBeer.do</url-pattern>
</servlet-mapping>
</web-app>
将上面的xml文件复制到部署环境。
重启tomcat:
点击submit后:
至此,第1版完成。
我们发现在servlet中处理表单,这样不是很好,所以我们出现第2版
工具代码如下:
import java.lang.*;
import java.util.*;
public class BeerExpert{
public List<String> getBrands(String color){
List<String> list = new ArrayList<String>();
if(color.equals("light")){
list.add("Jail Pale Ale");
list.add("Gout Stout");
}
return list;
}
}
第2版servlet代码:
package com.example.web;
import com.example.model.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class BeerSelect extends HttpServlet {
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
String color = request.getParameter("color");
BeerExpert be = new BeerExpert();
List<String> result = be.getBrands(color);
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Beer Selection Advice<br/>");
Iterator it = result.iterator();
while(it.hasNext()){
out.print("<br/>try: "+it.next());
}
}
}
编译连接后,将classes的文件复制到部署环境下,并且运行tomcat。
成功!
这里我们发现,视图部分由servlet来写又太麻烦了!于是第3版本出来了。
第3版视图result.jsp:
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<h1 align="center">Beer Recommendations JSP</h1>
<p>
<%
List<String> styles = (List<String>) request.getAttribute("styles");
Iterator it = styles.iterator();
while(it.hasNext()){
out.print("<br/>try: "+it.next());
}
%>
</body>
</html>
将其放置开发环境的web目录下,并复制到部署环境的WEB-INF中。
第3版BeerSelect:
package com.example.web;
import com.example.model.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class BeerSelect extends HttpServlet {
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
String color = request.getParameter("color");
BeerExpert be = new BeerExpert();
List<String> result = be.getBrands(color);
request.setAttribute("styles",result);
RequestDispatcher view = request.getRequestDispatcher("result.jsp");
view.forward(request, response);
}
}
编译连接后,将其放置部署环境的classes的相关目录下。
显示结果如下:
抓包分析发现,并无发现有3**的转发状态,也就是说JSP和servlet之间的转发,用户是不可见的。