JSP&Servlet 总结

来源:互联网 发布:win10以太网网络受限 编辑:程序博客网 时间:2024/05/01 22:05

第4章 作为servlet:请求和响应

★ 每个请求都在一个单独的线程中运行!
   容器运行多个线程来处理对一个servlet的多个请求。
   对应每个客户请求,容器会生成一对新的HttpServletRequest和HttpServletResponse对象。
   任何特定servlet类都只有一个实例。(101)

★ 不要在servlet的构造方法中放任何东西!
   初始化工作应放在init()方法中。
   servlet的构造方法只是让它成为一个普通的对象,容器调用它的init()方法后,它才成为了一个servlet
   init()方法使servlet可以访问ServletConfig和ServletContext对象。(103)
   如果在构造器中执行代码,可能会因为WebAPP资源还未初始化完毕而出现错误。

★ 每个servlet有一个ServletConfig对象,每个Web应用有一个ServletContext。(104)
     ServletConfig可以访问部署参数(定义在deployment-descriptor中)
     ServletConfig可以访问ServletContext.
     ServletContext可以访问WebAPP参数(定义在deployment-descriptor中)
     ServletContext当作全局参数使用。
     ServletContext可以获取服务器信息(Name、Version of the container, Version of API)

★ HttpServletRequest和HttpServletResponse接口由容器来实现。
   具体怎么实现的不用我们操心。(107)
   interface javax.servlet http.HttpServletRequest extends javax.servlet.ServletRequest
   class javax.servlet.http.HttpServlet extends javax.servlet.GenericServlet implements javax.servlet.Servlet
   GenericServlet 存在的原因是因为有可能有其他类似http的协议也使用Servlet

★ HTTP请求方法确定究竟是运行doGet()还是doPost()。
   客户的请求总是包括一个特定的HTTP方法。如果这个HTTP方法是GET,service()方法就会调用doGet()。如果这个HTTP方法是POST,service()方法就会调用doPost()。
   当然,还有些其它的HTTP方法,包括HEAD、TRACE、OPTIONS、PUT、DELETE和CONNECT,但对于servlet开发人员,这些方法很少用到。(108)

★ GET和POST的区别除了有参数数据大小、安全性和书签问题外,还有请求是否是幂等的问题。
   GET请求本质上讲(根据HTTP规范)是幂等的。它们应当能多次而不会对服务器产生任何副作用。GET请求不应该修改服务器上的任何东西,但是你也可以写一个非幂等的doGet()方法(不过这是很糟糕的做法)。
   POST本质上讲不是幂等的,所以要由你来适当地设计和编写代码,如果客户错误地把一个请求发送了两次,你也能正确地加以处理。(111)

★ 表单的默认方法是GET。(118)
      提交后信息会在header中。 并且使用ampersan(&)分开多个参数。
      request.getParameter("")返回一个参数值。
      request.getParameterValues(“”)返回一个数组(例如一组名为"sizes"的chechbox)

★ HttpServletRequest的getServerPort()、getLocalPort()和getRemotePort()很容易搞混!
   如果是一个servlet请求,就意味着客户是远程的,所以getRemotePort()是指“得到客户的端口”。
   getServerPort()说“请求原来发送到哪个端口?”,getLocalPort()则是说“请求最后发送到哪个端口?”。尽管请求要发送到一个端口(服务器所监听的端口),但是服务器会为每个线程找一个不同的本地端口。(123)

★ 对于输出,你有两个选择:字符或者字节。
   ServletResponse接口只提供了两个可以选择的流:ServletOutputStream用于输出字节,PrintWriter用于输出字符数据。(132)
   HttpServletResponse常用方法有setContentType(){MIME=text/html, application/pdf, image/jpeg},getWriter(),getOutputStream()

★ setHeader()和addHeader()的区别
   如果响应中还没有某个首部(方法的第一个参数),setHeader()和addHeader()就会增加一个首部和相应的值。
   二者的区别是,如果有这样一个首部,setHeader()会覆盖现有的值,addHeader()会增加另外一个值(addHeader()的API DOC中提到:This method allows response headers to have multiple values)。(133)

★Request Redirect: response.sendRedirect("url")将请求转换给其他的URL
     servlet返回给client, status code=301, Location=url, 然后client重定位到指定位置(client的browser bar改为重定位后的地址)
    
 但是如果response被修改提交后,就不能被sendRedirect了(包括write,setting header, cookie, status code, content-type...)
★Request Dispatch: 
        RequestDispatcher view =  response.getRequestDispatcher("result.jsp");
        view.forward(request, response);
        servlet将request, response对象转给其他的对象(例如jsp)来处理.

第5章 作为Web应用:属性和监听者

★ 覆盖init()方法
   容器调用的是init(ServletConfig)方法,而init(ServletConfig)方法会调用无参数的init()方法,所以如果需要覆盖init()方法,只需覆盖无参数的版本就行了。(151)

★ 要把初始化参数认为是部署时常量!
   可以在运行时得到这些初始化参数,但是不能设置。根本没有setInitParameter()。(160)

★ 上下文属性和会话属性都不是线程安全的。
   可以对上下文或会话同步来保护它们的属性。
   servlet的实例变量也不是线程安全的,所以一般servlet中不要放实例变量。
   只有请求属性和servlet服务方法中的局部变量是线程安全的。(192-202)

★ 如果已经提交了响应,就不能再转发请求或重定向了!(205)

 

第6章 会话管理

★ 会话有3种死法:超时;调用会话对象的invalidate()方法;应用结束。
   在web.xml中指定超时是以分为单位,而在程序中调用会话对象的setMaxInactiveInterval()方法设置超时是以秒为单位!(243)

★ cookie.setMaxAge(-1)表示浏览器退出时cookie就会消失。
   而session.setMaxInactiveInterval(负数)表示session永远不会到期。(249)

★ HttpSessionBindingListener不用在web.xml中注册。
   如果一个类实现了HttpSessionBindingListener,当这个类的一个实例增加到一个会话或从会话删除时,容器就会调用事件处理回调方法(valueBound()和valueUnbound())。(254)

★ 在分布式Web应用中,除了HttpSession对象外,所有其它对象都会在另一个VM上复制!
   会话对象不会复制,而只是移动。
   当会话对象从一个VM移动到另一个VM时,如果某个会话属性不是Serializable(或属性对象的某个实例变量不是Serializable),可以让属性对象类实现HttpSessionActivationListener,并使用激活/钝化回调方法来解决会话属性的串行化问题。(255-258)

 

第7章 使用JSP

JSP元素:
   scriptlet: <% %>  
   表达式:    <%= %>
   声明:      <%! %>
   指令:      <%@ %>
   注释:      <%-- --%>
   动作:      标准动作如<jsp:include>,其它动作如<c:set>
   EL表达式:  ${}     (286,292,302,321)

JSP指令有3种:page、include和taglib。(285)

JSP隐式对象:
           out --- JspWriter
   pageContext --- PageContext (封装了其它隐式对象,可以得到其它隐式对象的引用)
       request --- HttpServletRequest
      response --- HttpServletResponse
       session --- HttpSession
   application --- ServletContext
        config --- ServletConfig
     exception --- JspException (只有指定为“错误页面”的页面才能使用)
          page --- Object     (296)

★ 容器将JSP转换成一个servlet,这个servlet实现了HttpJspPage接口。
   这个servlet中有3个关键方法:
   jspInit() -- 这个方法在servlet的init()方法中调用。可以覆盖jspInit()。
   jspDestroy() -- 这个方法在servlet的destroy()方法中调用。可以覆盖jspDestroy()。
   _jspService() -- 这个方法在servlet的service()方法中调用。不能覆盖_jspService()。(303)

★ 在JSP页面中禁用scriptlet或EL表达式:
   禁用scriptlet:在web.xml中设置<scripting-invalid>。
   禁用EL表达式:在web.xml中设置<el-ignored>或在JSP页面中设置page指令的isELIgnored属性。(319-320)

 

第8章 无脚本的JSP

★ EL隐式对象:
   pageScope
   requestScope
   sessionScope
   applicationScope   (这4个是作用域属性的Map)
   param
   paramValues        (这2个是请求参数的Map)
   header
   headerValues       (这2个是请求首部的Map)
   cookie             (cookie的Map)
   initParam          (上下文初始化参数的Map)
   pageContext        (pageContext对象的实际引用,不是Map)
   除了pageContext外,其它都是Map。(381)

★ EL运算符和保留字:
   算术运算符:
     加法:   +
     减法:   -
     乘法:   *
     除法:   /和div
     取模:   %和mod
   逻辑运算符:
     与:   &&和and
     或:   ||和or
     非:    !和not
   关系运算符:
     等于:     ==和eq
     不等于:   !=和ne
     小于:      <和lt
     大于:      >和gt
     小于等于: <=和le
     大于等于: >=和ge
   其它保留字:
     true
     false
     null
     instanceof
     empty     (392)

★ EL能妥善地处理null值
   如果找不到EL表达式中指定名的属性/性质/键,也会显示页面,而不会抛出异常。
   在算术表达式中,EL把null值看作是0。
   在逻辑表达式中,EL把null值看作是false。(395)

★ “[]”操作符比“.”操作符更强大
   “.”的左边只能是Map或bean,“[]”左边除了可以是Map或bean外,还可以是List或数组;
   “[]”里可以包含命名变量的表达式,而且可以做任意层次的嵌套,即如果中括号里的内容没有用引号引起来,容器就会进行计算;
   “[]”里的Map键可以是不遵循正常的Java命名规则的String,如包含点号的String。(370-376,396)

★ include指令在转换时发生,<jsp:include>标准动作在运行时发生。(402)

 

第9章 使用JSTL

★ <c:set>有两种不同的设置:var和target。
   var“版本”用于设置作用域属性,target“版本”用于设置作用域属性的字段或Map值。(445)

★ 容器会在4个位置查找TLD:
   直接在WEB-INF目录中查找
   直接在WEB-INF的一个子目录中查找
   在WEB-INF/lib下的JAR文件中的META-INF目录中查找
   在WEB-INF/lib下的JAR文件中的META-INF目录的子目录中查找     (476)

 

第10章 定制标记开发

★ 容器会在4个位置查找.tag标记文件:
   直接在WEB-INF/tags目录中查找
   在WEB-INF/tags的子目录中查找
   在WEB-INF/lib下的JAR文件的META-INF/tags目录中查找
   在WEB-INF/lib下的JAR文件的META-INF/tags的子目录中查找
   如果标记文件部署在一个JAR中,这个标记文件必须有一个TLD,相应的TLD项只描述具体标记文件的位置。(499)

 

第11章 Web应用部署

★ 要成功地部署一个Web应用,必须遵循以下目录结构:
   WEB-INF一定要直接放在应用上下文之下;
   classes目录必须直接放在WEB-INF目录中,classes目录中必须是该类的包结构;
   lib目录要直接置于WEB-INF目录下,JAR文件必须放在lib中;
   META-INF目录必须是JAR中的顶级目录;
   不在JAR中的TLD必须放在WEB-INF下的某个位置,JAR中的TLD文件要放在META-INF目录下的某个位置(可以在任何子目录中,目录名不必是TLDs);
   不在JAR中的标记文件(扩展名为.tag或.tagx的文件)必须放在WEB-INF/tags下的某个地方,JAR中的标记文件必须放在META-INF/tags下的某个地方;
   web.xml必须直接放在WEB-INF目录下。(576)

★ 在META-INF/MANIFEST.MF文件中指定库依赖性
   将Web应用打包成WAR文件后,会生成这个文件。你的容器的类路径(不是应用的类路径)上可能有一些可选的包,你也许会依赖于其中某些包,或者你可能会依赖某个特定版本的库!有了MANIFEST.MF文件,就能告诉容器你必须访问哪些可选的库。如果容器无法提供这些库,就不能成功地部署应用。(583)

★ 在web.xml中配置servlet时,根据每个servlet加载所需的时间和使用的频度来决定是否使用<load-on-startup>元素。(596)

 

第12章 Web应用安全

servlet安全的4大要素:认证、授权、机密性和数据完整性。(621,630)

★ 4种认证类型:基本(BASIC)、摘要(DIGEST)、客户证书(CLIENT-CERT)、表单(FORM)。(645)



第14章 企业设计模式 模式和Struts



★business delegate
    业务代表模式保护你的web层controller不需要面对Remote Model component.
    特色:担当代理,调用远程服务接口(包括初始化通讯,传输,以及传输异常处理)
              从controller接收request,转换request并且转发给业务服务(stub),将response返回给control.
              通过处理远程调用,从而允许controller更加灵活。

★Service Locator
    封装远程调用,优化远程调用的性能(Cache)
    可以通过JNDI,RMI,UDDI,COS来实现.


★使用Transfer Object来避免JSP通过EL调用stub的属性,而导致与服务器频繁通讯的问题。
    Transfer Object被序列化,传送,反序列化后,被Client(如JSP)来调用,这牺牲了一些数据的实时性做为一种trade-off

★Intercepting Filter
    拦截过滤器可以修改request(发往servlet之前)和response(发往用户前)
    定义在DD文件中,其生命周期是有容器控制的,过滤器是模的,所以可以串行使用.
    过滤器实体必须实现callback方法。

★MVC模式最早出现在Web之前,用来简化复杂的GUI设计(最早应用在Smalltalk项目中),作为在GUI项目中的 MVC,其试图View是可以被通知的(当Model发生任何变化时)。现今MVC大多应用在Web项目中,其试图是无法获知Model的变化的。
   MVC模式可以提高组件的复用度(尤其是Modle组件),VIEW层可定义到GUI或J2ME.
   将业务层与控制层分开,可以将业务层部署在远程服务器中。
   增加了软件的复杂度。

★作为一个典型的MVC应用,应用拥有比较多的use-case,则可能会产生较多的Control,Model,View的实例,而其中Control则会产生duplicate Code,并且Control只做handle request, forwarding, dispatch, dealing model这些简单而又重复的工作吗?

Struct是一个Framework(不是container)

★Front Controller
     使用前端控制器,可以将常用的,经常发生的,请求处理的代码放进一个单独的组件,可以使应用控制器更加简单。
     Struts使用ActionServlet作为其前端控制器,可以增加代码的可维护性。
 

原创粉丝点击