Servlet Learner02

容器控制着servlet的一生

它会创建请求和响应对象 为servlet创建或者分配一个容器 调用servlet的service方法 吧HttpservletRequest和HttpservletResponse对象的引用作为参数传递给servlet
service(request, response)

service根据客户发出的HTTP方法 确定要调用哪个servlet方法 客户发出了一个HTTP GET请求 所以
service()方法会调用servlet的doGet()方法 吧请求和响应参数传递给它

servlet使用响应对象将响应写给客户 响应通过容器传回

servlet详细的一生
servlet类什么时候加载 什么时候允许servlet的构造函数 servlet对象能活多久 servlet什么时候初始化资源
又该什么时候清理资源

servlet的生命周期很简单: 只有一个主要的状态---初始化 如果servlet没有初始化 那就是正在初始化(运行
其构造函数或init()方法) 正在撤销(允许destory方法) 要么就是还不存在

WEB 容器 servlet类 servlet对象
|----加载类---------------------------------------->AServlet.class
|----实例化servlet(构造函数运行 servlet的无参构造函数运行)------------------------------->
|----init()---------在servlet的一生中只调用一次 而且容器调用service()之前必须完成-->
|----service()-----------------------servlet的一生都在这里度过------------------------------------->初始化
|----destory()-----在servlet被杀死之前有机会清理资源 与init一样 它也只调用一次---->

重写了service方法之后 doGet或者doPost就不用重写了
任何servlet类都不会有多个实例 容器运行多个线程来处理对一个servlet的多个请求 对应每个用户请求
会生成一对新的请求和响应对象 对应多个线程 但是servlet只会有一个

先找到servlet再分配线程 响应和请求是对应线程的 容器找到servlet类文件是 servlet生命开始
容器启动的时候 会自动寻找已经部署的Web应用 然后开始搜索servlet类文件
                 不存在
                   | |
                   | |
构造函数init() | | destory()
                   | |
service()     初始化
不要izservlet的构造函数中放任何东西 什么都可以放在inti()里面 但是init()只在servlet一生中只运行一次
所以不要浪费了 不要过早的做事

servlet的真正任务是处理请求 这才是servlet存在的意义

请求和响应 这是一切一切的关键
ServletRequest接口
getAttribute(String)
getContenLength()
getinputStream()
getLocalPort()
getParameter(String)
getParameterNames()
...
HttpServletRequest接口//增加了与HTTP协议有关的方法 你得servlet与客户/浏览器通信时需要使用
getContextPath()
getCookies()
getHeader(String)
getQueryString()
getSession()
getMethod()
...

ServletResponse接口
getBufferSize()
setContentType()
getOutputStream()
getWriter()
getContentType()
HttpServletResponse
addCooke()
addHeader()
encodeRedirectURL()
sendError()
setStatus()

GET是幂等的 它只是得到一些东西 它不会修改服务器上的任何内容 它能执行多次 不会产生任何不好的
副作用
POST不是幂等的 POST中提交的数据可能用于不可逆转的事物 所以使用doPost的时候必须特别小心

除了参数(request.getParameter()) 还可以获得

1 String client = request.getHeader("User-Agent");
2 Cookie[] cookies = request.getCookies();
3 HttpSession session = request.getSession();
4 String theMethod = request.getMethod();
5 InputStream input = request.getinputStream();

 

比如说 我想网上下载一个jar文件(这是用servlet发回一个jar 当然也可以静态的让Web服务器把它作为一个资源返回)

public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
//我们希望浏览器看出这是一个JAR而不是HTML 所以把内容设置为"application/jar"
response.setContentType("application/jar");

//这仅表示"为名为bookCode.jar的资源给我一个输入流"
ServletContext ctx = getServletContext();
InputStream is = ctx.getResourceAsStream(" /bookCode.jar");

int read = 0;
byte[] bytes = new byte[1024];

//这是关键部分 bug也只是普通的io而已 读取JAR字节 然后写至我们从响应对象得到的输出流
OutputStream os = response.getOutputStream();
while ((read = is.read(bytes)) != -1)
{
os.write(bytes, 0, read);
}
os.flush();
os.close();
}

 

常用的MIME类型
text/html application/pdf video/quicktime application/java image/jpeg application/jar
application/octet-stream application/x-zip 网上时时有更新

要保证正常工作 有一个需求:
先调用setContentType() 然后获得输出流的方法(getWriter()或者getOutputStream()) 这样能保证不会遭遇
内容类型和输出流之间的冲突

要有你来发回响应 容器更不不知道你在发什么 它只是在发字节流

PrintWriter output1 = response.getWriter();
output1.println("some text and html");//吧文本数据打印到一个字符流 PrintWtiter专门用于打印字符数据

ServletOutputStream output2 = response.getOutputSt();
out.write(aByteArray);

 

PrintWriter output1 = response.getWriter();
output1.println("some text and html");//吧文本数据打印到一个字符流 PrintWtiter专门用于打印字符数据

ServletOutputStream output2 = response.getOutputSt();
out.write(aByteArray);

可以设置响应首部 也可以增加响应首部
response.setHeader("foo", "bar");如果有同名的首部 用这个值替换 没有 就增加一个新的
response.addHeader("foo", "bar");为响应增加一个新首部的值 或者向一个现有的首部增加一个值
response.setIntHeader("foo", "42"); 用提供的整形数值替换现有首部的值或者向响应增加一个新首部的值

setHeader()会覆盖现有的值 addHeader()会增加另外一个值
调用setContentType("text/html")时 就是在设置一个首部 相当于:setHeader("content-type", "text/html");

有时候我们不想自己处理响应
sendRedirect(aString); 要么自己处理请求 要么就是sendRedirect出去 不能在写到响应之后 再调用send
Redirect sendRedirect娶的是一个String 而不是一个URL对象

请求分派是在服务器端做工作 这就是请求分配和重定向之间最大的差异
重定向让客户来工作 请求分派 要求服务器上的某某某来服务 记住 重定向 = 客户 请求分派 = 服务器
重定向用户会在浏览器看到新的URL 这里客户是浏览器 浏览器代表用户再做一个新的调用 因为它原来
调用的servlet说:抱歉 你再打给这个人看看....(浏览器还会重新发送请求)

当servlet完成请求分配的时候 就像要求一位同事 接管一个客户的工作一样 由这个同事最后为客户做出
响应 客户并不关心是谁的响应 对客户是透明的 因为浏览器地址栏上的URL没有任何变化

要点
使用响应向客户发回数据
对响应对象(HttpServletResponse)调用的最常用的方法是setContentType()和getWriter()
利用getWriter()方法可以完成字符I/O 向流写入HTML(或其他内容)
还可以用响应设置首部 发送数据 以及增加cookie
在实际中 大多数HTML响应都可能使用JSP发送 但仍有可能使用一个响应流向客户发送二进制数据
setContentType()方法告诉浏览器如何处理随响应到来的数据 常见的内容类型(MIME)为"text/html"
如果你不想对一个请求做出响应 可以重定向到另一个URL 浏览器负责把新请求发送到你提供的URL
不能在响应以及提交了之后才调用sendRedirect() 换句话说 如果已经在流中写了东西 再想重定向就晚了
请求分配在服务器端发生 重定向是在客户端进行 请求重定向只是告诉浏览器去访问一个URL

posted @ 2015-10-30 15:16  taojiatao  阅读(149)  评论(0编辑  收藏  举报