Head First Servlet & JSP读书笔记
本书内容:Servlet和JSP
Servlet和JSP的关系分析:Servlet接受来自用户浏览器发送的请求,并最终返回响应;JSP根据Servlet的请求(request)内容创造动态网页作为相应。JSP优化了Servlet中out.println输出html的繁琐,利用请求转发将请求交给JSP,作出响应。
MVC思想:M(model):可复用的处理业务的类文件;V(version):JSP;C(controller):servlet
第一章:为什么使用Servlet和JSP
1.GET和POST请求的区别:安全性、数据量、幂等性(一般来说GET是幂等的,POST不是幂等的,即你可以一遍一遍反复做同一件事,而不会产生意想不到的结果,例子:网络卡的时候多次付款操作应视为只有一次。这是一般的规范,由程序员自己注意并实现),而且一般来说,GET不对服务器的内容进行修改
2.MIME类型:Content-Type(内容类型)响应首部的值称为MIME类型,一般使用:
response.setContentType("text/html");
response.setContentType("application/jar");
除此之外还有文件类型
3.Servlet的部署(初步)
方法一:使用备注,即在创建Servlet的时候将support asyxxxx打勾,使用该servlet的时候使用对应url
方法二:在web.xml中部署
方法一的优先级高于二(?)
4.使用JSP的必要性
在Servlet中利用输出流输出html十分繁琐,例子:
out.println("<a href=\""+response.encodeURL("/BeerTest.do")+"\">click me</a>");
所以使用JSP,Servlet接收浏览器请求(request)和业务层的信息(?),将请求转发给JSP,产生动态页面
注意:请求转发操作前不能响应输出,否则会报illegal的错,即不能out.flush(),输出由JSP产生返回
第二三四五章
1.使用web.xml的好处
对web应用进行修改而不必修改源文件,其次Listener等也只能在web.xml中部署(?)
2.请求转发:在服务器端做工作,用户发送一次请求
RequestDispatcher view = request.getRequestDispachter("result.jsp");
3.重定向:在客户端做工作,用户发送两次请求
response.sendRedirect("http://hfajkfhkajl.com");
4.ServletConfig和ServletContext,及作用域
每个Servlet只有一个ServletConfig,里面可设置servlet作用域的属性(setAttribute)
每个web应用只有一个ServletContext,web作用域
注意:
5.Servlet和JSP的数据传输一般通过在request上添加属性
Servlet和java模型(pojo)是Servlet获得java类的实例对象
6.初始化参数
1)servlet的初始化参数:
对于可能修改的参数可设置为servlet的初始化参数,在web.xml中修改
部署:
<servlet>
<init-param>
<param-name>name</param-name>
<param-value>xiaoxue</param-value>
</init-param>
</servlet>
读取(返回参数):
getServletConfig().getInitParameter("name");
2)Web应用的初始化参数
对于web应用公用的参数,为避免固定servlet初始化顺序,在context中设置初始化参数
部署:(在web-app内,servlet外)
<context-param>
<param-name>name</param-name>
<param-value>xiaoxue</param-value>
</context-param>
读取:
getServletContext().getInitParameter("name");
7、Listener
上述可实现对初始化字符串参数的引入,那对类对象呢,例如数据库连接?
为避免固化Servlet的初始化顺序,使用Listener类(监听者)
ServletContextListener例子
/*Listener项目运行思路:
* 首先Listener获得serveltcontext对象,通过web.xml中的inti参数构造对象(或直接构造对象,如数据库连接)
* 最后在context的attribute里面添加
* 然后servlet获得context中的属性,即测试完毕
*/
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import wyn.Dog;
public class MyServletContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
}
public void contextInitialized(ServletContextEvent arg0) {
ServletContext sc = arg0.getServletContext();
String dogBreed = sc.getInitParameter("breed");
Dog d = new Dog(dogBreed);
sc.setAttribute("dog", d);
}
}
对应servlet的注意点:
`Dog d = (Dog)getServletContext().getAttribute("dog");
部署:
<listener>
<listener-class>wyn.MyServletContextListener</listener-class>
</listener>
完整的故事:
容器读取部署描述文件(web.xml)
创建servletcontext对象
将读取的初始化参数交给servletcontext
创建ServletContextListener对象
容器调用contextInitialized()方法,该方法接收ServletContextEvent参数,实际上有ServletContext的一个引用
Listener请求一个ServletContext的一个引用,并获得初始化参数
利用初始化参数构造一个Dog对象
将Dog对象设置为ServletContext中的一个属性
Servlet读取对象,完成(注意类型转换)
8、Listener类型了解(待)
9、属性与参数的区别:属性的值是Object类型,参数是String类型
10、线程安全问题(重点)
1)上下文属性不是线程安全的,每个Servlet都可以修改ServletContext的内容,如果考虑线程安全一定要使用ServletContext的情况的话,使用:
synchronized(getServletContext()){
//对上下文的操作
}
但同步就意味着妨碍并发性,开发必须尽量让同步时间最短
2)会话属性(session)也不是线程安全的,一个用户也可能打开两个不同的浏览器,而容器还是以为用户使用相同的会话,用户的多个同时的请求可能会影响安全。
关键是让用户在同一个会话内只能同时发送一个请求,或者将请求同步执行
可以对HttpSession同步:
synchronized(session){
//对session的操作
}
3)只有请求属性和局部变量是线程安全的
一般来说,不使用对实例变量的同步(sychronized),这一方面影响效率并一方面设计与考虑也很麻烦(如serlvet计数器的例子,不能使用实例池的解决方案,尽管可能实现singleThreadModel也可能事与愿违),
所以一个好的servlet不会看到任何实例变量
另一方面也要加强的作用域的利用
第六章、会话状态(request)
1、request.getSession()(用的多)
使用一个会话,在响应中发送一个cookie
1)如果没有会话则创建会话,因此需要对会话进行检验:
HttpSession session = request.getSession();
if(session.isNew()){//如果客户使用该session做过响应则返回false
pass
}
2)只想要一个已经有的会话使用request.getSession(false)
如果没有匹配的会话则返回null,(session==null)检验
2、禁用cookie的话常用URL重写(不是很理解)
必须显式进行URL编码,如:response.encodeURL("/BeerTest.do")
3、会话设置
servlet内:略
DD:<session-config><session-time>15</session-time></session-config>
注意:程序中以秒为单位,部署文件中以分钟为单位
4、直接使用cookie(如使用表单提供的用户名使用cookie存起来,而非仅仅jsession编号)
//p252
5、HttpSessionBindingListener
无需在DD中部署,仅用来告诉类本身什么时候加入一个会话
public class Dog implements HttpSessionBindingListener{
pass
}
6、会话迁移
只有HttpSession对象会从一个VM移动到另一个VM
可以使用HttpSessionActivationListener来监听激活和钝化
会话计数器:p261
至多后天写完全书读后感,jsp部分略看,大后天开始JavaScript高级设计及锋利的jquery
第一次写文章,请多多指教