标签:
一、前言和体系结构
一、Web服务器做些什么?
Web服务器接收客户请求,然后返回一些结果。
二、Web客户做些什么?
Web客户(浏览器)允许用户请求服务器上的某个资源,并且向用户显示请求的结果。
三、HTML
当服务器响应客户端的请求时,一般会向浏览器发送一组用HTML编写的指令。HTML告诉浏览器怎样向用户显示内容(根据响应的内容类型)。
四、HTTP
HTTP是web上客户和服务器之间进行通信所用的协议。服务器使用HTTP响应向客户发送HTML。HTML是HTTP响应的一部分。
Http请求分析:http://www.cnblogs.com/RascallySnake/archive/2010/05/05/1728007.html
五、web服务器自己不做的两件的事情
1、动态内容
Web服务器只提供静态页面,但是有一个“辅助”应用(web容器及在其中运行的组件)可以生成非静态的即时页面,而且这个辅助应用能与web服务器通信。
2、在服务器上保存数据
即使用户通过表单提交了数据,web服务器也只是交由辅助应用处理,辅助应用可能会保存到数据库中。
二、高层概述
一、什么是容器?
Servlet没有Main方法。它们受控于另外一个java应用,这个java应用成为容器。Tomcat就是这样一个容器。如果Web服务器(如Apache)得到一个指向某个Servlet的请求,此时服务器不是把这个请求交给Servlet本身,而是交给部署该Servlet的容器。要由容器向Servlet提供HTTP请求和响应,而且要由容器调用Servlet的方法,如doPost或doGet。
二、容器能提供什么?
1.通信支持:负责与web服务器之间的通信。
2.生命周期管理:控制Servlet的生与死。
3.多线程支持:容器会自动地为它接受的每个Servlet请求创建一个新的java线程。
4.声明方式实现安全:利用容器,可以使用XML部署描述文件(DD)来配置安全性,而不必将其硬编码写到Servlet类代码中。
5.JSP支持:负责将JSP代码翻译成真正的java。
P.S:容器如何处理请求?P42
三、一个Servlet可以有3个名字
1.客户知道的URL名
2.部署人员知道的密码内部名
3.实际的完全限定名
建立Servlet名的映射,这样有助于改善应用的灵活性和安全性。
四、使用部署描述文件将URL映射到Servlet
可以使用两个XML元素把URL映射到Servlet,其中一个将客户知道的公共URL名映射到你自己的内部名,另一个元素把你自己的内部名映射到一个完全限定类名。
P48,76
代码示例:
<?xml version="1.0" encoding="UTF-8"?> <web-app …> <servlet> <!-- 元素1:内部名映射到完全限定名 --> <servlet-name>SuiBianQuDe Name</servlet-name> <!-- 这个名字是随便取的,内部名字,客户看不到 --> <servlet-class>com.example.MyServlet</servlet-class> <!-- 在这里放置类的完全限定名(但是不加.class扩展名) --> </servlet> <servlet-mapping> <!-- 元素2:内部名映射到公共URL名 --> <servlet-name>SuiBianQuDe Name</servlet-name> <!-- 和上面的内部名字一致--> <url-pattern>/public.do</url-pattern> <!-- 这个是客户看到(并使用)的Servlet名,这是一个虚构的名字,并不是具体的Servlet类的名字。--!> <!-- 不要忘记最前面的一个斜杠,相当于请求地址为:http://hostname:8080/WebAppName/public.do ,不加斜杠则变成http://hostname:8080/WebAppNamepublic.do --> </servlet-mapping> </web-app>
五、Servlet & JSP世界中的MVC
控制器:从请求获得用户输入,并明确这些输入对模型有什么影响。告诉模型自行更新,并且让视图(jsp)能得到新的模型状态。
模型:包含具体的业务逻辑和状态。换句话说,模型知道用什么规则来得到和更新状态。系统中只有这部分与数据库通信。
视图:负责表示方面。它从控制器得到模型的状态。另外视图还有获得用户的输入,并提交给控制器
六、以下各个任务谁来负责?
任务 |
Web服务器 |
容器 |
Servlet |
创建请求和响应对象 |
|
在开始线程之前创建 |
|
调用service方法 |
|
然后service方法再调用doGet或doPost |
|
开始一个新线程来处理请求 |
|
开始一个Servlet线程 |
|
把响应对象转换为一个HTTp响应 |
|
由响应对象中的数据生成HTTP响应流 |
|
了解HTTP |
用于与客户浏览器对话 |
|
|
把HTML增加到响应对象 |
|
|
提供给客户的动态内容 |
有响应对象的一个引用 |
|
容器把它交给Servlet |
用它打印响应 |
在部署描述文件中查找URL |
|
找到对应请求的适当Servlet |
|
删除请求和响应对象 |
|
Servlet一旦结束就删除请求和响应对象 |
|
协调生成动态内容 |
知道如何转发到容器 |
知道要调用什么方法 |
|
管理生命周期 |
|
调用服务方法 |
|
七、Web服务器与web容器的区别,tomcat到底是web服务器还是web容器?
独立的web容器通常配置为与一个HTTP Web服务器(如Apache)协作。不过Tomcat容器本身就能作为一个基本的HTTP服务器。但是在HTTP服务器功能方面,Tomcat没有Apache那么健壮,所以最常见的非EJB Web应用通常会结合使用Apache和Tomcat,Apache作为HTTP Web服务器,Tomcat作为Web容器。
三、MVC实战
一、请求分派机制
RequestDispatcher rd = request.getRequestDispatcher(“request.jsp”);
Rd.forward(request,response);
getRequestDispatcher的参数,如果不到斜杠,则表示这个jsp和Servlet在同一路径下;如果有斜杠,则代表当前web应用的根路径下的一个jsp页面。”/”表示Web应用的根。
这个应该和getServletContext().getResourceAsStream(“”)类似。
四、请求和响应
一、Servlet GenericServlet HttpServlet之间的关系
Servlet是接口。GenericServlet是一个抽象类,实现了Servlet接口。HttpServlet也是一个抽象类,继承自GenericServlet抽象类。
P98
二、每个请求都在一个单独的线程中运行
在一个JVM中,任何Servlet类都不会有多个实例,只有一种特殊情况除外(称为SingleThreadModel)。容器运行多个线程来处理对一个Servlet的多个请求。对应每个客户请求,会生成一对新的请求和响应对象(HttpServletRequest和HttpServletResponse)。
三、ServletContext
n 每个web应用有一个ServletContext。
n 用于访问web应用参数(这些参数是在部署描述文件中配置的)。
n 用于得到服务器信息,包括容器名和容器版本,以及所支持的API的版本等。
Servlet对象封装了一组上下文初始化参数和一组属性。对于上下文初始化参数,只提供了getter方法,对于属性则提供了getter/setter方法。
四、ServletConfig对象
n 每个Servlet都有一个ServletConfig对象。
n 用于向Servlet传递部署时信息,而你不想把这些信息硬编码到Servlet中。
n 用于访问ServletContext。
n 参数在部署描述文件中配置。
ServletConfig对象只是封装一组string类型的键值对(Servlet初始化参数)。容器从DD读出Servlet初始化参数,并把这些参数封装为一个ServletConfig对象,然后把ServletConfig传递给Servlet的init方法。Servlet初始化参数只能读一次,就是在容器初始化Servlet的时候。所以ServletConfig只提供了getter方法。
P158 Servlet初始化参数和上下文初始化参数之间的区别。
五、ServletRequest接口和ServletResponse接口
HttpServletRequest接口继承自ServletRequest接口。HttpServletResponse接口继承自ServletResponse接口。
HttpServletRequest接口和HttpServletResponse接口都是由容器(Tomcat)实现的。在调用Servlet的service方法时,容器会向该方法传递这两个接口的各自的实现类对象的引用。
六、HTTP的各个方法
GET
POST
HEAD
TRACE
PUT
DELETE
OPTIONS
CONNECT
七、GET和POST的区别
1.数据大小问题。GET方式对参数数据有限制,参数数据只能放在请求行的内容。POST方式则没有限制,参数放在消息体中。
2.安全性问题。使用GET方式时,请求参数会被浏览器放在实际URL的后面(用一个“?”分隔,参数之间以”&”分隔)。
3.书签问题。GET方式可以使最终用户对请求页面建立书签,而POST方式则不行。
4.幂等问题。GET请求是幂等的,只是要得到东西,不会修改服务器上的任何内容。POST是非幂等的,POST体中的提交数据可能用于修改服务器上的某些东西。
幂等:对于HTTP/servlet,这个词表示同一个请求可以做两次,而不会对服务器产生负面作用。并不是说同样的请求总会得到同样的响应,也不是说一个请求没有副作用。
八、除了参数,能从HttpServletRequest得到什么?
1.客户的平台和浏览器信息:String client = httpServletRequest.getHeader("User-Agent");
2.与请求相关的cookie:Cookie[] Cookies = httpServletRequest.getCookies();
3.与客户会话相关(Session):HttpSession session = httpServletRequest.getSession();
4.请求的HTTP方法:String method = httpServletRequest.getMethod();
5.请求的输入流:ServletInputStream inputStream = httpServletRequest.getInputStream();
httpServletRequest.getServerPort();服务器监听的端口
httpServletRequest.getLocalPort();服务器为每个线程找的一个不同的本地端口
httpServletRequest.getRemotePort();获取客户的端口
九、HttpServletResponse的常用方法
httpServletResponse.setContentType(String);
httpServletResponse.getWriter();处理文本数据。
httpServletResponse.getOutputStream();处理其他任何内容。
httpServletResponse.addHeader("key", "value");没有对应的key则新建,否则会覆盖现有的值
httpServletResponse.setHeader("key", "value");没有对应的key则新建,否则会增加另外一个值
十、在sendRedirect()中使用相对URLs
httpServletResponse.sendRedirect("http://www.google.com"); Servlet让浏览器重定向
可以使用相对URL作为sendRedirect()的参数,而不是指定完整的"http://www.... "。相对URL有两种:前面有斜线”/”和没有斜线。
假设客户原来键入的是:http://www.hehe.com/myApp/cool/bar.do
当请求到达名为“bar.do”的Servlet时,这个Servlet会基于一个相对URL来调用sendRedirect(),这个相对URL没有用斜线开头: sendRedirect(“foo/stuff.html”);
容器会新建一个URL:http://www.hehe.com/myApp/cool/ foo/stuff.html
如果sendRedirect()的参数以一个斜线开头:sendRedirect(“/foo/stuff.html”);
则容器会新建一个URL:http://www.hehe.com/ foo/stuff.html
这里的”/”代表web容器的根。
P136
十一、请求分派(转发)和重定向的区别
RequestDispatcher rd = httpServletRequest.getRequestDispatcher(“/request.jsp”);
Rd.forward(request,response);
httpServletResponse.sendRedirect(“/foo/stuff.html”);
1.请求分派中的”/”代表“web应用的根”。重定向中的”/”代表“web容器的根”。如果都不带”/”,则表示相对于当前的Servlet所在目录而言。
2.请求分派发生在服务器端,而重定向在客户端进行。请求分派把请求传递给服务器上的另一个组件。重定向只是告诉浏览器去访问另一个URL。
请求数量 地址栏
转发 1 不变
重定向 2 变化
比如:添加、修改、删除成功后 要重定向到列表功能,这样在刷新页面时才不会出现“又做一次增、删、改”的操作。
五、属性和监听者
一、ServletContextListener
由于上下文参数只能是String。毕竟你不能将一个Dog对象硬塞到XML中。如果希望在ServletContext初始化的时候创建一个供各个Servlet共享的数据库连接对象怎么办呢?
javax.servlet.ServletContextListener这个接口的实现类的对象能监听ServletContext一生中的两个关键事件,初始化和撤销。
适合如下需求场景:希望在ServletContext初始化的时候使用初始化参查找名建立一个数据库连接。把数据库连接存储为一个属性,使得web应用的各部分都能访问。当ServletContext撤销的时候关闭数据库连接。
其他监听者以及应用场景。P182
二、到底什么是属性?
属性就是一个对象,可能设置到另外3个Servlet API对象中的某一个,包括ServletContext、HttpServletRequest或者HttpSession。可以把它简单地认为是一个映射实例对象中的名/值对(名是一个String,值是一个Object)。
三、属性和参数的区别
P186
四、三个作用域:上下文、请求和会话
P187
五、上下文作用域不是线程安全的
P192
解决方案:对ServletContext对象枷锁P197
会话作用域也不是线程安全的
P199
解决方案:对HttpSession对象枷锁P200
实现SingleThreadModel的两种方案:实例池策略和排队策略P201
推荐方案和理由 P202
只有请求属性和局部变量是线程安全的!
变量类型 |
是否线程安全 |
上下文作用域属性 |
否 |
会话作用域属性 |
否 |
请求作用域属性 |
是 |
Servlet中的实例变量 |
否(除非实现了STM) |
Servlet中的静态变量 |
否(实现了STM也是非线程安全的) |
service方法中的局部变量 |
是 |
六、会话管理
一、在响应中发送一个会话cookie与从请求中得到会话id的代码一样
HttpSession session = request.getSession();
二、getSession(boolean)与getSession()的区别
P235
二、客户禁用Cookie,从而导致客户和服务器无法传递sessionid的处理办法
P237
URL重写:httpServletResponse.encodeUrl(“/user.do”)
使用sendRedirect()的URL重写:httpServletResponse.encodeRedirectURL(“/user.do”)
三、HttpSession的生命周期事件
P255
四、会话迁移
P257
七、使用JSP
一、
<% %> scriptlet,这里面声明的变量都是局部变量。
<%@ %>指令,<%@ page import=”com.model.*,java.util.*” %> 这是带有import属性的page指令。
<%= expression%>表达式,不要在表达式后面加上分号。等价于<% out.print(expression) %>
<%! %> JSP声明,可以声明变量和方法。
<%-- --%>JSP注释
<jsp:useBean ... /> 动作
二、JSP的生命周期
P306
三、初始化JSp
配置jsp的初始化参数,覆盖jspInit方法。 P310
四、pageContext
除了标准的Servlet请求、会话和上下文作用域外,jsp还增加了第四个作用域,即页面作用域,可以从pageContext对象得到。pageContext封装了其他隐式对象。P298、311-313
五、在DD中使用<scripting-invalid>标记禁止在页面中使用scriptlet,使用<el-ignored>元素禁用EL。
P321-322
标签:
原文地址:http://www.cnblogs.com/michaellau/p/4593120.html