这本书总体上比较简单,主要用来梳理一下基本知识内容。关于servlet更详细的内容可以参考servlet规范。
?
一、web应用程序简介
1、http协议2大特性,一个是基于请求/响应模型,另一个http是无状态协议。关于http的资料,有本书Web Protocols and Practice值得阅读
2、http有很多请求方法,比如get, post, put, delete。其中有人会问get与post的区别,其中一个区别是get处理应该是等幂的,就是说多次发送返回的结果应该是一样的,而post不是。get是用来获取资源,而post通常是提交资源,比如创建或者修改。
3、mvc模式与model 2:
? ? controller:处理请求,调用模型进行处理,转发请求或者响应请求结果
? ? model:接受控制器的请求调用,处理业务逻辑,更新自身数据
? ? view:接受控制器的调用,从模型中取得数据,根据要求渲染页面。
?
二、编写与设置servlet
1、HttpServlet类,HttpServletResponse与HttpServlerRequest。关于这几个重要为类,我做了一个uml图,帮助记忆与理解。见附图1
2、@WebServlet注解用来标明这个Servlet的一些参数,比如name,urlPatterns, loadOnStartup,其中loadOnStartup如果值大于0,表明应用程序启动后就加载这个servlet
3、一个URI请求分为三部分:requestURI = contextPath + servletPath + pathInfo,可以通过HttpServletRequest的getRequestURI, getContextPath, getServletPath, getPathInfo方法来获取
4、web-fragment.xml,一个jar文件除了可以使用标的servlet, filter, listener外,也可以有自己的部署描述文件,即web-fragment.xml,存放于META-INF中。顶层标签 <web-app> 有一个 metadata-complete 属性,该属性指定当前的部署描述文件是否是完全的。如果设置为 true,则容器在部署时将只依赖部署描述文件,忽略所有的注解,同时也会跳过 web-fragment.xml 的扫描。
?
第三章、请求与响应
1、关于编码,对于post请求,如果客户端没有在content-type中设置编码,此时使用HttpServletRequest的getCharacterEncoding会返回null,这时容器会使用默认的编码处理,如果客户端发送非ascii码就会产生乱码。解决办法一个是可以使用HttpServletRequest的setCharacterEncoding来设置正确的编码。但setCharacterEncoding通常只对post起作用,比如tomcat中对get就不起作用。这时可以使用另一个方法,类似代码:String result = new String(param.getBytes("iso-8859-1"), "utf-8");
2、关于HttpServletRequest及RequestDispatcher,通过HttpServletRequest可以取得,从而进行include()或者forward()操作,把其它servlet纳入当前处理或者转向其它servlet进一步处理。可以通过setAttribute, getAttribute进行参数传递。
3、关于HttpServletResponse,通过setHeader设置响应标头、设置缓冲区,缓冲区未满之前不会传送至客户端。通过setCharacterEncoding, setContentType设置编码、内容类型等。sendRedirect重定向, sendError设置错误响应,比如sendError(HttpServlerResponse.SC_NOT_FOUND)
?
第四章、会话管理
1、会话管理实现方式:隐藏域、cookie、及Url重写,书中提到的url重写,其实是在url后面添加请求参数。比如我们有时会看到在地址栏中的jsessionid这个东东。
2、servlet 3.0中cookie类添加了setHttpOnly方法,如果设置为true,那么这个值就只用于http,其它像客户端的javascript无法读取。
3、HttpSession,使用HttpSession的invalidate方法,可以让目前的会话失效。HttpSession不是线程安全的,这个要注意。Servlet容器取得HttpSession的一个图例如下:
?
4、servlet 3.0中添加了一个新的接口SessionCookieConfig,用于设置Session Cookie
5、HttpServletResponse的encodeURL方法在浏览器禁用cookie后,会在url后面加上jsessionid,这是使用url重写方式来实现会话管理机制。
?
第五章、Servlet进阶API、过滤器与监听器
1、每个servlet设置信息会产生一个ServletConfig对象,web容器会将这个对象通过servlet的init()传入其中。
2、每个web应用程序都会有一个ServletContext,它定义了Servlet与应用程序环境的一些行为和观点。其getRequestDispatcher可以进行请求的转发或包含, getResourcePaths可以知道web应用程序某个目录下的文件,getResourceAsStream可以读取web应用程序下的文件的内容。
3、servletcontext事件、监听器:ServletContextListener是生命周期监听器,可以用@WebListener这个annotation标注。ServletContextAttributeListener用于监听属性改变
4、HttpSession事件、监听器:HttpSessionListener是生命周期监听器,HttpSession创建或者结束时可以做些相关动作。HttpSessionAttributeListener用于监听属性改变。HttpSessionBindingListener是对象绑定监听器,当一个对象实现这个监听器时,如果这个对象加入或者移除session时就会触发valueBound和valueUnbound方法。HttpSessionActivationListener是对象“迁移”监听器,这个迁移名称不是很合适,主要是在分布式的环境中,对象分布在不同的jvm上,当httpsession要从一个jvm迁移至另一个jvm时,如果属性对象有实现这个监听器,那么就会调用sessionWillPassivate()方法,而迁到另一个虚拟机后,会调用sessionDidActivate()方法。
5、HttpServletRequest事件、监听器:ServletRequestListener是生命周期监听器。ServletRequestAttributeListener是属性改变监听器,在请求对象中加入、移除、或者改变属性时,会调用相应的方法。AsyncListener是servlet3.0中增加的监听器。
6、过滤器:过滤器的调用返回是以堆栈的形式。所以在运行servlet的service方法之后还要返回filter进行后续处理。相关注解:@WebFilter,filter的过滤类型是REQUEST,即dispatcherTypes.REQUEST,所以如果是forward或者include的话,需要更改设置。如果某个Servlet或者url有多个filter对应,会以它们在web.xml中出现的先后顺序进行处理。
7、ServletRequestWrapper:请求封装器,可以帮助实现HttpServletRequest,并结合filter实现定制能力。书中介绍了一个过滤请求自符串的例子。如果要对响应做定制封装处理,可以继承HttpServletResponseWrapper
8、异步处理:通常情况下,web为每个请求分配一个线程,响应完成前,该线程的资源不会释放。如果请求长时间处理,会占用很多的系统资源。所以servlet 3.0开始支持异步servlet。将Servlet的asyncSupported标识为true即可支持异步,如果有相关的filter,也需要设置filter的asyncSupported为true。
?
第六章、使用JSP
1、从JSP到Servlet。见图2。
2、Jsp生命周期,转译后的servlet继承自HttpJspBase,这个servlet中有_jspInit()、_jspDestroy、_jspService方法,代表jsp的初始化、服务、以及销毁处理时相关调用。
3、从servlet到jsp,servletcontext对应jsp中隐式对象application。
4、指示类型:page、include、taglib。其中page include是静态包含,最终会生成一个servlet,而jsp:include是动态包含,每个jsp页面独立生成一个servlet。
5、<%! //这里是类成员变量和方法声明 %>,使用这种方式声明变量,要注意线程安全问题。可以定义jspInit()和jspDestroy()方法,来进行一些初始化和销毁工作。如果是<%%>,没有感叹号,那么其中的语句会被放入service方法中。<%= %>其中的内容直接变成out.println()。
6、jsp中的隐式对象:有out(JspWriter,内部关联PrintWriter)、request(HttpServletRequest)、response(HttpServletResponse)、config(ServletConfig)、application(ServletContext)、session(HttpSession)、pageContext(PageContext,封装所有jsp页面信息,可以通过它获取隐式对象、设置页面范围属性)、exception(Throwable)、page(this)。隐式变量是_jspService中的局部变量。
7、异常处理。在以下几个地方可能产生异常,一个是把jsp转译成servlet的时候,另一个是把servlet编译成class文件的时候如果语法不正确也会出错。第3个可能是servlet运行时发生错误。
8、标准标签,现在有用的也许就是jsp:include了,至于jsp:forward, jsp:useBean, jsp:setProperty, jsp:useProperty等等在jstl之后不再推荐使用
9、EL(表达式语言):param是EL的隐式对象,pageContext也是。如果不指定属性的范围,默认会按照page, request, session, application顺序来获取。
10、EL运算符:+ , -, *, /, %,逻辑运算符有and, or, not,比较运算符有>, <, >=, <=, ?==, !=
11、自定义函数:定义一个public 类,并定义public static函数,然后编写.tld文件, 将tld文件放置于WEB-INF下,这样容器可以自已找到
12、使用JSTL:JSTL分为5个大类,核心标签库提供条件判断、属性访问、URL处理及错误处理等标签;I18N兼容格式标签库提供数字、日期等的格式化功能以及区域信息、编码处理等国际化功能标签;SQL标签库;XML标签库提供XML解析、流程控制、转换等功能的标签;函数标签库提供常用字符串处理的自定义EL函数标签库。
13、核心标签库:c:if; c:forEach; c:catch(捕获异常);c:import可以视为jsp:include的加强版;c;redirect进行重定向;c:url等同于response的encodeURL;c:set设置属性;c:remove移除属性;c:param用于传递参数;c:out输出值,c:out可以转义html字符, c:out还可以设置默认值,这个很有用。
14、I18N兼容格式标签库:java的字符串是Unicode编码,如果编辑器的编码是utf-8,而操作系统默认编码是gb2312,那么使用javac的时候需要指定-encoding参数,来指明编码,否则会出现乱码。ResourceBundle可以用来处理国际化。这个里面的标签主要有:fmt:bundle及fmt:message, fmt:setBundle(设置全局), fmt:param, fmt:formatNumber, fmt:parseNumber, fmt:formatDate, fmt:parseDate, fmt:timeZone,fmt:setTimeZone(设置全局时区)等
15、xml标签库:XPath是用于寻找xml文件中特定信息的语言,它使用路径表示来取得想要的信息。XSLT是指XSL转换,主要是将xml文件转换为另一份xml文件、HTML或者XHTML的语言。xml标签实际使用不是很多,就略过吧,有需要的再看书。
16、函数标签库:fn:length取得数组、集合或者字符串的长度,还有很多和字符串处理相关的函数,像replace, substring, toLowerCase, trim, startWith, indexOf等等。
17、自定义标签:tag file文件,tag文件会被容器转译为SimpleTagSupport的子类。tag file中可以使用out, config, session, request, response, application, jspContext这些隐式对象,这些隐式对象存在于转译后的java文件的doTag方法中。在tag file中可以使用jsp:doBody取得使用标签时的Body内容。
18、TLD文件:如果要将tag file打包成jar文件,需要编写tld文件,同时把tag file放置在META-INF/tags文件夹或子文件夹下面,tld文件要放置在META-INF/tlds下面。
19、Simple Tag:如果想要复杂的功能,可以编写java,继承自SimpleTagSupport,重定义doTag方法。然后定义tld文件。页面遇到自定义标签时有一套处理步骤,具体参见书本296页
?
第9章、整合数据库
1、JDBC是JAVA连接数据库的标准规范。它定义了一组标准API
2、数据库连接必须的几个操作:a.注册Driver实现对象,b.通过DriverManager取得Connection实现对象, c.关闭Connection
3、使用Statement, ResultSet
4、使用PrepareStatement, CallableStatement:PrepareStatement可以重复使用一段SQL,只要重新设置参数即可。如果编写数据库存储过程,并想使用JDBC来调用,就可以使用CallableStatement。
5、BLOB与CLOB:BLOB全名是Binary Large Object,用于存储大量的二进制数据;CLOB全名是Character Large Object,用来存储大量的文字数据。
6、事务的特性:原子性、一致性、隔离性与持续性。
7、事务的隔离级别:read uncommitted就是A事务已更新但未提交的数据,B事务可以读取但不可以更新;Dirty read是指两个事务同时进行,其中一个事务更新数据但没有确认,另一个事务就读取就有可能发生脏读。read committed是指事务读取的数据必须是其它事务已确认的数据。unrepeatable read就是无法重复读,某个事务两次读取同一个字段的数据不一致。可以设置repeatable read这样在同一事务内2次读取的数据必须相同。幻读是指同一事务期间,读取到的数据笔数不一致。设置隔离级别为Serializable,可以避免幻读。
隔离级别 | 更新遗失 | 脏读 | 无法重复读 | 幻读 |
读未确认 | 预防 | ? | ? | ? |
读已确认 | 预防 | 预防 | ? | ? |
可重复读 | 预防 | 预防 | 预防 | ? |
序列化读 | 预防 | 预防 | 预防 | 预防 |
?
第十章、web容器安全管理
第11章、JavaMail入门
第12章、从模式到框架
1、template method模式:servlet其实就采用了模板方法设计模式,它在service中定义了服务流程。流程中调用的方法通常是无实现或者简单实现,希望子类可以自行重新定义。如下图
?
2、Intercepting Filter模式(jee 设计模式)
3、MVC模式(架构模式):mvc设计模式最早始于桌面应用程序。
?
在web环境中演化为Model 2模型:
?
4、重构、模式与框架
a、Bussiness delegate模式:现在流行的service, dao就是属于这种模式的一种,当Business delegate接受客户端请求,它会委托Business Service运行后回传结果给客户端。
?
b、Service Locator模式:举例来说,当需要dataSource的时候,通过jndi来查找获取对象,并返回给使用者,从而将这些操作对使用者隐藏起来,这是一种service locator模式。
?
c、Transfer Object模式:
d、Front Controller模式:
?
?
附:
图1:
?
图2:
?