Tag Archive for WEB

温故知新-web应用中的Session机制

目录:

一、术语session

二、HTTP协议与状态保持

三、理解cookie机制

四、理解session机制

五、理解javax.servlet.http.HttpSession

六、HttpSession常见问题

七、跨应用程序的session共享

八、总结

一、术语session

在我的经验里,session这个词被滥用的程度大概仅次于transaction,更加有趣的是transaction与session在某些语境下的含义是相

同的。

Read more

Servlet相关

这个东西是现在J2EE下的基础component了~
作为一个开发者~其实非常容易的使用~但是只是停留在开发的层面上还是远远不够的~
之前开发过很多servlet的程序。~我甚至不知道:
他的架构里主要类是啥?他和WEB容器的调优解决方案都有哪些?SessionId是怎么生成的?
其实这些都是基础 呜呜~我之前不重视~~不过还来得及~我慢慢加强基础。。。。。 :|
现在有空稍微整理下~

老生常谈之servlet生命周期~

其实servlet本质是多线程~为了解决内存资源不够的问题。对比于CGI可以说明问题。

Servlet的生命周期分为5个阶段:
实例化:Servlet容器创建Servlet类的实例。
初始化:该容器调用init()方法,通常会申请资源。
服务:由容器调用service()方法,(也就是doGet()和doPost())。
破坏:在释放Servlet实例之前调用destroy()方法,通常会释放资源。
不可用:释放内存的实例。

CGI(Common Gateway Interface通用网关接口)程序来实现数据在Web上的传输,使用的是如Perl这样的语言编写的,它对于客户端作出的每个请求,必须创建CGI程序的一个新实例,这样占用大量的内存资源。由此才引入了Servlet技术。

Servlet是一个用java编写的应用程序,在服务器上运行,处理请求信息并将其发送到客户端。对于客户端的请求,只需要创建Servlet的实例一次,因此节省了大量的内存资源。Servlet在初始化后就保留在内存中,因此每次作出请求时无需加载。
JSP 的执行过程
(1) 客户端发出Request (请求);
(2) JSP Container 将JSP转译成Servlet的源代码;
(3) 将产生的Servlet 的源代码经过编译后,并加载到内存执行;
(4) 把结果Response (响应)至客户端。
在执行 JSP 网页时,通常可分为两个时期:转译时期(Translation Time)和请求时期(Request Time)
转译时期:JSP网页转译成Servlet类。
请求时期:Servlet类执行后,响应结果至客户端。
注:
转译期间主要做了两件事情:将JSP网页转译为 Servlet 源代码(.java),此段称为转译时期(Translation time);将Servlet源代码(.java)编译成 Servlet 类(.class),此段称为编译时期(Compilation time)。

Servlet 的生命周期
1) 产生 Servlet,加载到Servlet Engine中,然后调用 init()这个方法来进行初始化工作。
2) 以多线程的方式处理来自Client 的请求。 service()
3) 调用 destroy()来销毁Servlet,进行垃圾收集 (garbage collection)。
Servlet 从产生到结束的流程
1. 加载和实例化
当Container一开始启动, 或是客户端发出请求服务时, Container会负责加载和实例化一个Servlet。
2. 初始化
Servlet 加载并实例化后,再来Container必须初始化 Servlet。初始化的过程主要是读取配置 信息(例如JDBC连接)或其他须执行的任务。我们可以借助 ServletConfig 对象取得 Container的 配置信息,例如:
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>tw.com.javaworld.CH2.HelloServlet</servlet-class>
<init-param>
<param-name>user</param-name>
<param-value>browser</param-value>
</init-param>
</servlet>
其中user为初始化的参数名称;browser 为初始化的值。因此,可以在 HelloServlet程序中使用ServletConfig 对象的getInitParameter(“user”)方法来取得 browser。
3. 处理请求
Servlet被初始化后,就可以开始处理请求。每一个请求由 ServletRequest 对象来接收请求;而ServletResponse对象来响应该请求。
4. 服务结束
当 Container 没有限定一个加载的 Servlet 能保存多长时间,因此,一个 Servlet 实例可能只在Container中存活几毫秒,或是其他更长的任意时间。一旦 destroy( )方法被调用时,Container将移除该 Servlet,那么它必须释放所有使用中的任何资源,若 Container 需要再使用该 Servlet时,它必须重新建立新的实例。
1. Servlet的生命周期?
Servlet是一种可以在Servlet容器中运行的组件,那么理所当然就应该有一个从创建到销毁的过程,这个过程我们可以称之为 Servlet生命周期Servlet的生命周期可以分为加载、实例化、初始化、处理客户请求和卸载五个阶段,体现在方法上主要是init()、 service()和destroy()三个方法。生命周期的具体说明如下:

Servlet容器完成加载Servlet类和实例化一个Servlet对象
init()方法完成初始化工作,该方法由Servlet容器调用完成
service()方法处理客户端请求,并返回响应结果
destroy()方法在Servlet容器卸载Servlet之前被调用,释放一些资源
2. Servlet的实例是在生命周期什么时候创建的? 配置servlet最重要的是什么?
Servlet实例是在servlet第一次在容器中被加载的是时候创建的, Init()方法是用来配置这个servlet实例的,这个方法在servlet的生命周期中只被调用一次,所以应该把所有servlet生命周期中的配置操作都写在这个方法法里面。
3. 为什么不在Servlet中写一个构造(Contructor)方法?
容器会自动为Servlet写一个无参的构造方法
4.  我们没有写servlet的构造方法,那么容器是怎么创建servlet的实例呢?
容器会自动为Servlet写一个无参的构造方法,容器是用Class.forName(className).newInstance()来创建servlet的实例的。
5. 当容器调用servlet的destory()方法的时候,servlet会马上销毁么? 如果当时这个servlet正在执行其他任务或者线程呢?
是的, 当容器调用servlet的destory()方法的时候,servlet会马上销毁,但是容器在调用destory()方法之前,会等servlet的service()方法结束剩余的任务。
6. 用ServletRequest和ServletContext调用ReqestDispatcher有什么区别?
在用ServletRequest调用RequestDispatcher的时候可以用相对URL, 但是ServletContext不行。
7. 为什么在用ServletRequest.getRequestDispatcher()的时候可以用相对URL而用ServletContext.getRequestDispatcher()的时候不可以?
因为ServletRequest包含当前的request path,可以用当前的request path去计算URL,但是ServletContext不包含当前的request path。
例如:

Java代码
  1. RequestDispatcher rd = request.getRequestDispatcher(“\error.jsp”);
  2. rd.forward(request, response);
  • 关于Session的持久化
  • 作用:
    提高服务器内存利用率,保持会话
    集群系统中session对象的复制
    Web应用程序关闭后重启,会话继续
    背景:如果内存中大量HttpSession对象堆积,会造成大量的内存消耗~毕竟session不是cookie那样,大小限制的很死。
    解决方案:Web服务器将暂时不活动但未超时的HttpSession对象转移到文件系统或DB中保存,一旦需要他们是,再从File system活DB中装载进内存;
    应用:Tomcat的Session持久化管理
    Tomcat使用Session Manager类来管理Session的持久化
    StandardManager:
    默认的方法。当Tomcat服务器重启或重载的时候,会把Session对象保存到 <%CATALINA_HOME%>/work/Catalina/honstname/applicatonname/SESSIONS.ser
    PersitentManager
    更加灵活的管理方式,配置性强
    可以存储在本地文件( (节点下添加如下节点)和数据库中(配置store节点 )

    sessions.ser的生成和加载:
    形式一:存储在本地文件中:配置conf目录里的context.xml文件 在节点下添加如下节点:

         debug=0     saveOnRestart="true"     maxActiveSession="-1"     minIdleSwap="-1"     maxIdleSwap="-1"     maxIdleBackup="-1"       
    

    形式二:存储在数据库中 配置store节点

    Tomcat在启动时加载,并不是需要时加载.

  • Servlet容器如何处理多个请求?
  • Servlet采用多线程来处理多个请求

    当容器收到一个访问Servlet的请求,调度者线程从线程池中选出一个工作者线程,将请求传递给该线程,然后由该线程来执行Servlet的service方法。 当这个线程正在执行的时候,容器收到另外一个请求,调度者线程将从池中选出另外一个工作者线程来服务新的请求,容器并不关系这个请求是否访问的是同一个Servlet还是另外一个Servlet。 当容器同时收到对同一Servlet的多个请求,那这个Servlet的service方法将在多线程中并发的执行。 (这里容易出问题,所以在servlet尽量减少成员变量(实例变量)的声明,如果必须使用 ,那么需要加上同步操作,保持同步。见下)
    线程池实际上是等待执行代码的一组线程叫做工作者线程(Worker Thread),Servlet容器使用一个调度线程来管理工作者线程(Dispatcher Thread)。 )

    变量的线程安全:
    实例变量是线程不安全的
    解决:
    实例变量—-》局部变量(方法级变量 每次方法调用的时候构造~结束的时候销毁)
    同步doXXX()方法
    (本地变量:每个线程都将拥有user变量的拷贝,线程在对自己栈中的本地变量的改变不会影响其他线程本地变量的拷贝)
    Servlet容器对它所接收到的每一个请求,都创建一个新的ServletRequest对象,所以ServletRequest对象只在一个线程中被访问。
    在这些窗口的访问请求,属于同一个session,为了同时处理多个这样的请求,Servlet容器会创建多个线程,而在这些线程中,就可以同时访问到Session对象的属性。

    JAVA WEB 系统设计开发知识体系

    JAVA WEB 系统设计开发知识体系
    1.1 Browser
    1.1.1 HTML
    1.1.2 CSS
    1.1.3 JavaScript
    1.1.4 AJAX

    1) DWR
    2) Jquery
    1.2 Presentation Layer
    1.2.1 Servlet/Filter/Listener/JSP
    1.2.2 Struts
    1.2.3 JSF

    1.3 Business Logic layer
    1.3.1 BO/Service/DomainObject
    1.3.2 Spring

    1.3.2.1 为什么需要Spring?

    为什么要用spring,我们可以几个非常常用的方面来分析一下.
    Spring是基于j2ee框架. 他站在非常实用的角度帮助程序员解决了很多不需要程序员搞和程序员一直重复搞的问题. 下面我只讲能节省我们工作的地方以使得大家对spring有足够的兴趣.

    1, 松耦合问题. loose coupled IOC
    这个问题我不费太多笔墨. 因为太多的文章解释这个问题. 大名叫:依赖注入. 说白了就是根据配置文件动态组装复杂对象. 或许有人又问, 我就是用程序组合也很简单啊. 是的, 你程序组装简单业务的是很简单. 如果组装的对象里面包含了Ejb, 包含了JMS, 包含了远程RMI那就没有这样组装简单了. 就说到这里.不说那么多废话.

    2, AOP, 面向切面编程. 这个功能我们自己是不好设计的. 这个功能大家也都知道是干什么的, 例如方法的事务管理, 用户安全验证, 日志记录, 等等. 为了避免将更多的代码放进方法中去.spring使用这个AOP来监控符合你配置的正则表达式的方法名字. 并允许在执行这个方法的前后执行你的方法. 这个是建立在spring上下文框架下的一个功能. 原理是映射机制. 如果没有上下文是不好搞的.
    虽然spring AOP对于大多程序员就足够了. 但与AspectJ相比, 他只能是功能比较弱的解决方案. AspectJ提供了SpringAOP不可能实现的多种切点类型. 如果不够用,你可以引入AspectJ. 来帮助你做更多的工作.

    上面两个是大的方面的一个简单的说明. Spring在更多细节中方便了大家的工作. 下面我继续依次给以说明.

    3, Bean工厂节省了.
    你不用再自己构造工厂了. 不用再用自己构造单例模式了(原来我用hibernate做项目的时候,就有自己写的构造单例模式 好像是public static sessionFactory…). 不用自己再关心对象的创建了. 不用new对象了. 一切都直接从 上下文的框架中取就行了. 框架会帮助你构造你需要的对象. 你只需要跟上下文打交道就可以了. 当然,你多出了装配的工作. 但这是必须要付出的代价. 因为复杂性被集成在了配置里面. 使得你在开发层面只关心业务. 要是配置有可视化的工具就太好了. 但别着急, 找找, 现在只有想不到,没有找不到.

    4, 集成Hibernate使用节省了事务的显式代码.
    这个其实还是切面的一个好处应用. 配置进去是很简单. 既然能节省工作, 我就给你说一下.
    (额 记得之前用hibernate做项目要加commit 而结合了spring之后就不用了 啥原因捏?是spring的哪个特性所导致的呢?恩 要好好思考下。╮(╯▽╰)╭)

    5, Spring 针对不同的数据库访问模式提供了不同的模板. 分别适用于不同的持久机制.
    包括: 针对JCA CCI的链接, 针对JDBC的, 支持命名参数的JDBC的链接, Hebernate的,针对iBATIS sqlMap的, Oraclede TopLink的. 这些模板使用方式的统一降低了程序员使用不同数据库的成本.模板的使用让你只关心数据的准备, 而看不到那些样板代码, 其实那些样板代码都还在, 只是被巧妙的隐含到了template中了.
    例如: List list = jdbcTemplate.query(“select * from table1”,new Object[]{“a”,”b”},new RowMapper(){…..}); 意思表达到了.
    其中对数据源的引用可以配置使用JNDI以从应用服务器中获取数据库的连接. 这样程序就可以集中处理业务逻辑而不必关心数据库的具体情况 .
    如果不能从JNDI中取得, 那就必须在spring中配置一个连接池. 可以使用开源的DBCP. 这个支持多种数据库连接.

    6, 数据库层面的缓存的使用.
    Spring并不提供实际的缓存解决方案, 而是要以来第三方的缓存方案. 包括: EHcache,Gigaspaces, JBoss Bache, JCS, OSCache, Coherence .无论采用哪种缓存方案, 对于spring的配置都是一样的. 但缓存的配置文件都是要分开的. 简化了使用缓存的成本.

    7. 安全验证方面节省的工作.
    基于多种方式的用户验证. 都节省了很多工作.

    8, 访问 RMI , 访问 Http Invoker, 访问Web Service
    如果要穿越防火墙最后是后两种. 但httpInvoder局限于spring的对象. webService 可以多种.平台. 不管使用哪种, spring都为他们的配置提供了统一简单的配置. 使用起来非常方便. Xfire协助你访问webService简单易用.

    9, JMS的访问. 大量冗余的代码被节省了. 配置好了即可使用. 当然你需要使用activeMQ第三方的队列服务器来接受消息.

    10 , 访问EJB.. JNDI都非常简单了. 所有额外的工作,你配置好之后, spring都帮你做了. 你要做的就是: 使用

    为什么不选择EJB呢?

    打个比方吧,spring就像银行为我们提供很多的服务,以前有个叫ejb的银行,但是服务态度不好,学院派的风格,程序员快疯了。Johnson这位程序员很愤怒,新开了这家spring银行,非常的友善,于是很快地流行起来。感觉中型项目比较适合,几百块钱就不必麻烦去找银行了。大型项目估计还要找Ejb这家大型银行。

    1.3.2.2 Spring 简介和使用范围

    Spring使用基本的 JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。它是一个基于IoC和AOP(Aspect Oriented Programming 面向方面编程)的构架多层j2ee系统的框架,但它不强迫你必须在每一层中必须使用Spring,因为它模块化的很好,允许你根据自己的需要选择使用它的某一个模块;它实现了很优雅的MVC,对不同的数据访问技术提供了统一的接口,采用IoC使得可以很容易的实现bean的装配,提供了简洁的AOP并据此实现Transcation Managment,等等。 从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。

    ◆目的:解决企业应用开发的复杂性

    ◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能

    ◆范围:任何Java应用

    简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

    ◆轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。

    ◆控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

    ◆面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务()管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

    ◆容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。

    ◆框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。

    所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

    让我们明确Spring范围。尽管Spring覆盖了许多方面,但我们已经有清楚的概念,它什么应该涉及和什么不应该涉及。

    Spring的主要目的是使J2EE易用和促进好编程习惯。

    Spring不重新开发已有的东西。因此,在Spring中你将发现没有日志记录的包,没有连接池,没有分布事务调度。这些均有开源项目提供(例如 CommonsLogging用来做所有的日志输出,或CommonsDBCP用来作数据连接池),或由你的应用程序服务器提供。因为同样的的原因,我们没有提供O/Rmapping层,对此,已有有好的解决办法如Hibernate和JDO。

    Spring的目标是使已存在的技术更加易用。例如,尽管我们没有底层事务协调处理,但我们提供了一个抽象层覆盖了JTA或任何其他的事务策略。

    Spring没有直接和其他的开源项目竞争,除非我们感到我们能提供新的一些东西。例如,象许多开发人员,我们从来没有为Struts高兴过,并且感到在MVCwebframework中还有改进的余地。在某些领域,例如轻量级的IoC容器和AOP框架,Spring有直接的竞争,但是在这些领域还没有已经较为流行的解决方案。(Spring在这些区域是开路先锋。)

    1.3.2.3 Spring 带来的好处

    ◆方便解耦,简化开发

    通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

    ◆AOP编程的支持

    通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP(Object Oriented Programming 面向对象的程序设计)实现的功能可以通过AOP轻松应付。

    ◆声明式事务的支持

    在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

    ◆方便程序的测试

    可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。

    ◆方便集成各种优秀框架

    Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hession、Quartz)等的直接支持。

    ◆降低JavaEEAPI的使用难度

    Spring对很多难用的JavaEEAPI(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些JavaEEAPI的使用难度大为降低。

    ◆Java源码是经典学习范例

    Spring的源码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。

    下面的一些描述,可能跟上边有重叠, 列在这里做为参考:

    ◆Spring能有效地组织你的中间层对象,无论你是否选择使用了EJB。如果你仅仅使用了Struts或其他的包含了J2EE特有APIs的framework,你会发现Spring关注了遗留下的问题,。

    ◆Spring能消除在许多工程上对Singleton的过多使用。(Singleton的过多使用,会减少系统的可测试性和面向对象特性。)

    ◆Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。

    ◆使用Spring构建的应用程序易于单元测试。

    ◆Spring使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或localEJBs来实现业务接口,却不会影响调用代码。

    ◆Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适于许多web应用。例如,Spring能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。

    ■Spring为数据存取提供了一致的框架,不论是使用JDBC或O/Rmapping产品(如Hibernate)。

    Spring确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。

    1.3.2.4 Spring 的一些细节问题?
    1) 事务控制的粒度/范围问题:详细信息有待补充
    2) … …

    1.3.2.5 Spring + Struts + Hibernate 的Sample Project

    1.3.3 EJB

    1.4 Data Layer
    1.4.1 标准 SQL 语言
    1.4.2 Hibernate
    Hibernate 的设计思想
    Hibernate 为我们解决了那些问题?
    1.4.3 Oracle
    1.4.4 Mysql
    1.4.5 H2

    1.5 其他

    1.5.1 Cache的应用与设计
    1.5.1.1 设计原理/原则
    1.5.1.2 JCS cache
    1.5.1.3 EH cache
    1.5.1.4 Jboss cache
    1.5.2 SOA
    1.5.3 WebService
    1.5.4 集群
    1.5.5 负载均衡
    1.5.6 SAP

    无觅相关文章插件,快速提升流量