深刻理解java:4. 框架编程

了解 Servlet 和 Filtercss

Servlet(即servlet-api.jar) 是 J2EE 最重要的一部分,有了 Servlet 你就是 J2EE 了,J2EE 的其余方面的内容择需采用。html

而 Servlet 规范你须要掌握的就是 servlet 和 filter 这两项技术。java

绝大多数框架不是基于 servlet 就是基于 filter,若是它要在 Servlet 容器上运行,就永远也脱离不开这个模型。linux

Servlet容器,大一点就是应用服务器,推荐 Tomcat 、或者 Jetty 这些轻量级的产品。web

SpringMVC的入口是servlet:servlet是一种运行服务器端的java应用程序,具备独立于平台和协议的特性,而且能够动态的生成web页面,它工做在客户端请求与服务器响应的中间层。
Struts2的入口是filter:filter是一个能够复用的代码片断,能够用来转换HTTP请求、响应和头信息。Filter不像Servlet,它不能产生一个请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应。filter可以在一个请求到达servlet以前预处理用户请求,也能够在离开servlet时处理http响应。spring

 

为何 Servlet 规范会有两个包,javax.servlet 和 javax.servlet.http ?sql

早先设计该规范的人认为 Servlet 是一种服务模型,不必定是依赖某种网络协议之上,所以就抽象出了一个 javax.servlet ,同时再提供一个基于 HTTP 协议上的接口扩展。数据库

可是从实际运行这么多年来看,彷佛没有发现有在其余协议上实现的 Servlet 技术。apache

javax.servlet 和 javax.servlet.http 这两个包总共加起来也不过是三十四个接口和类。你须要经过 J2EE 的 JavaDoc 文档 熟知每一个类和接口的具体意思。编程

特别是下面几个接口必须熟知每一个方法的意思和用途:

  • HttpServlet
  • ServetConfig
  • ServletContext
  • Filter
  • FilterConfig
  • FilterChain
  • RequestDispatcher
  • HttpServletRequest
  • HttpServletResponse
  • HttpSession
  • 一些 Listenser 类

再次强调 HttpServletRequestHttpServletResponse 这两个接口更应该是烂熟于心。

由于 Web 开发是离不开 HTTP 协议的,而 Servlet 规范其实就是对 HTTP 协议作面向对象的封装,HTTP协议中的请求和响应就是对应了 HttpServletRequest 和 HttpServletResponse 这两个接口。

你能够经过 HttpServletRequest 来获取全部请求相关的信息,包括 URI、Cookie、Header、请求参数等等,别无它路。

所以当你使用某个框架时,你想获取HTTP请求的相关信息,只要拿到 HttpServletRequest 实例便可。

 

再谈谈 Session

HTTP 协议里是没有关于 Session 会话的定义,Session 是各类编程语言根据 HTTP 协议的无状态这种特色而产生的。

其实现无非就是服务器端的一个哈希表,哈希表的Key就是传递给浏览器的名为 jsessionid 的 Cookie 值。

当须要将某个值保存到 session 时,容器会执行以下几步:

a. 获取 jsessionid 值,没有的话就生成一个,也就是 request.getSession() 这个方法
b. 拿到的 HttpSession 对象实例就至关于一个哈希表,你能够往哈希表里存放数据(setAttribute)
c. 你也能够经过 getAttribute 来获取某个值

而这个名为 jsessionid 的 Cookie 在浏览器关闭时会自动删除。

把 Cookie 的 MaxAge 值设为 -1 就能达到浏览器关闭自动删除的效果。

 

关于 JSP

任何一个 JSP 页面在执行的时候都会编译成一个 Servlet 类文件,

若是是 Tomcat 的话,这些生成的 java 文件会放置在 {TOMCAT}/work 目录下对应项目的子目录中。

在 servlet 中有一个包 javax.servlet.jsp 是跟 JSP 相关的一些接口规范定义。

JSP 比 Servlet 方便的地方在于可直接修改当即生效,不像 Servlet 修改后必须重启容器才能生效。

所以 JSP 适合用来作视图,而 Servlet 则适合作控制层。

 

struts不过是对servlet、filter的封装而已,

hibernate也不过是对jdbc的封装而已。

框架解决的是解耦的问题,复用的问题,分工的问题。

 

SSI框架总结

专一于控制层的Struts2

专一于业务逻辑方面的spring框架

专一于持久层的 iBatis

Struts2主要来源于webwork框架,在数据传递方面,Struts2提供了更增强大OGNL标签功能,使其可以经过在action中定义变量来直接与jsp页面中的数据进行相互传值,省去了Struts1中的formbean。

Spring功能很是的强大,好比它的控制反转/依赖注入机制,省去了咱们本身书写工厂模式的工做;Spring对AOP支持使咱们在用户权限控制、事务处理方面节省了不少工做量;

iBatis则是一种轻量级的ORM框架,与Hibernate相比,iBatis提供了半自动化对象关系 映射的实现,开发人员须要编写具体的sql语句,提供了更大的自由空间,为sql语句优化提供了便利。

下面这张图就是咱们所用到的这三种框架的结合体,下面对其做以简单介绍。

 


在控制层,利用Strtus2标签功能,在Action中直接与jsp页面上的数据进行交互。

在调用业务逻辑层应用时,Struts2提供了对Sping的支持。

开发人员须要完成对struts.xml的配置工做和对各个Action类的编写。

 

在业务逻辑层,利用Spring框架的依赖注入实现对业务逻辑类和DAO类的实例托管;

在事务处理方面,利用Spring提供的面向切面的事务处理功能,使对数据的事务控制脱离于数据访问接口实现;

在对象关系映射方面,利用Spring对数据库链接池的托管和对iBatis框架的支持。

开发人员须要完成对数据源的配置、对不一样模块所对应的Application*.xml文件的配置,以及对业务逻辑接口的定义和业务逻辑实现的编写。

 

在持久层,利用iBatis提供的半自动化对象关系映射的实现,开发人员须要编写具体的sql语句,为系统设计提供了更大的自由空间。

另外,开发人员须要完成对SqlMapConfig.xml和*SqlMap.xml的配置,以及对DAO接口的定义和DAO接口的实现。

 

在各层之间进行交换的过程当中,利用数据传输类进行数据的传递和交互。其中,数据传输类与数据库表一一对应。

SSI框架可以下降咱们代码的耦合度,加强了代码的健壮性和可重用性,加快了开发速度,

可是也有一些不足之处,好比因为三种框架的配置文件较多,也给咱们带来了一些不便,特别是对于较小的应用来讲更是如此。

 

SSI开发过程:

一:首先引入struts2 spring ibatis 各自的jar包 在此就不一一罗列了。

二:添加配置文件

   咱们首先从web.xml文件提及

   web.xml加载过程:
   1 启动WEB项目的时候,容器(如:Tomcat)会读他的配置文件web.xml读两个节点
         <context-param></context-param>和<listener></listener>
    2 紧接着,容器建立一个ServletContext(上下文) 这个WEB项目全部部分都将共享这个上下文
    3 容器将<context-param></context-param>转化为键值对并交给ServletContext
    4 容器建立<listener></listener>中的类的实例,即建立监听
    5 在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中得到:
              ServletContext = ServletContextEvent.getServletContext();  
              context-param的 = ServletContext.getInitParameter("context-param的");

     web.xml节点加载顺序
     节点的加载顺序与它们在web.xml文件中的前后顺序无关。即不会由于filter写在listener的前面而会先加载filter。

     最终得出的结论是:listener->filter->servlet
     同时还存在着这样一种配置节点:context-param,它用于向 ServletContext 提供键值对,即应用程序上下文信息。

     咱们的 listener, filter 等在初始化时会用到这些上下文 的信息,那么context-param 配置节是否是应该写在 listener 配置节前呢?实际上 context-param 配置节可写在任意位置,所以真正的加载顺序为:
     context-param -> listener -> filter -> servlet

    加载spring
     <listener> 
             <listener-class> 
               org.springframework.web.context.ContextLoaderListener  
            </listener-class> 
       </listener>
     最终结论:

     web.xml 的加载顺序是:[context-param -> listener -> filter -> servlet -> spring] ,而同类型节点之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调  用的。

    打开web.xml文件,根据实际须要添加以下内容

<!--上下文参数用于log4j以及spring中使用-->
<context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>/WEB-INF/log4j.properties</param-value>
</context-param>

<!--应用程序上下文参数,指定spring配置文件位置-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/beans.xml</param-value>
</context-param> 

<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

<!--监听器 用于初始化spring框架-->
<listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

 
在这说说SSI整合时的一些配置文件:

 1,contextConfigLocation:Spring容器启动时须要加载Spring的配置文件。默认是/WEB-INF目录下的applicationContext.xml文件

   固然也能够放在classpath下,能够包括多个spring配置文件,这就得依靠contextConfigLocation

<!-- 加载spring的配置文件 若是文件名为applicationContext.xml而且是在WEB-INF目录下 则无需此配置 -->
    <context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/beans.xml</param-value>
    </context-param> 

若是web.xml中没有配置context-param,spring的配置就像如上这段代码示例一下,自动去WEB-INF目录下寻找applicationContext.xml。此时,若是你修改applicationContext.xml的名称,或者移除它,再启动服务器,你会获得以下异常信息:

1.nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]  

这证明了其默认配置。默认配置状况下spring只会去WEB-INF目录下寻找配置文件,而不会去classpath下寻找。
若是咱们不想将配置文件放在WEB-INF目录下呢?开发中常常在src下面建立一个config目录,用于存放配置文件。此时,对应的param-value改成:classpath:config/applicationContext.xml。
必定要加上classpath,这告诉spring去class目录下的config目录下面寻找配置文件。

2,如何启动Spring容器

两种方法,一种以listener启动  一种以load-on-startup Servlet。

<!-- 配置spring监听器 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

 

第二种

<servlet>
 <servlet-name>context</servlet-name>
 <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>


 

 

 3,整合Struts2

        <filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


4,Spring整合ibatis配置文件

       <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
		<property name="configLocation"> 
			<value>classpath:SqlMapConfig.xml</value>
		</property>
	</bean>

5,Struts.xml

<constant name="struts.objectFactory" value="spring" />

constant配置struts的常量(也可在struts.properties)文件中配置,将struts的对象工厂托由spring管理。

SSM框架总结

SpringMVC能够彻底替代Struts,配合注解的方式,编程很是快捷,并且经过restful风格定义url,让地址看起来很是优雅。
另外,MyBatis也能够替换hibernate,正由于MyBatis的半自动特色,咱们程序猿能够彻底掌控SQL,这会让有数据库经验的程序猿能开发出高效率的SQL语句,并且XML配置管理起来也很是方便。

  1. SpringMVC:它用于web层,至关于controller(等价于传统的servlet和struts的action),用来处理用户请求。举个例子,用户在地址栏输入http://网站域名/login,那么springmvc就会拦截到这个请求,而且调用controller层中相应的方法,(中间可能包含验证用户名和密码的业务逻辑,以及查询数据库操做,但这些都不是springmvc的职责),最终把结果返回给用户,而且返回相应的页面(固然也能够只返回json/xml等格式数据)。springmvc就是作前面和后面过程的活,与用户打交道!!

  2. spring:太强大了,以致于我没法用一个词或一句话来归纳它。但与咱们平时开发接触最多的估计就是IOC容器,它能够装载bean,有了这个机制,咱们就不用在每次使用这个类的时候为它初始化,不多看到关键字new。另外spring的aop,事务管理等等都是咱们常常用到的。

  3. MyBatis:若是你问我它跟鼎鼎大名的Hibernate有什么区别?我只想说,他更符合个人需求。第一,它能自由控制sql,这会让有数据库经验的人编写的代码能搞提高数据库访问的效率。第二,它可使用xml的方式来组织管理咱们的sql,由于通常程序出错不少状况下是sql出错,别人接手代码后能快速找到出错地方,甚至能够优化原来写的sql。

SpringMVC与Struts2区别与比较总结

一、Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,因此说从架构自己上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,由于Struts2中Action的一个方法能够对应一个url,而其类属性却被全部方法共享,这也就没法用注解或其余方式标识其所属方法了。

二、由上边缘由,SpringMVC的方法之间基本上独立的,独享request response数据,请求数据经过参数获取,处理结果经过ModelMap交回给框架,方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间也是独立的,但其全部Action变量是共享的,这不会影响程序运行,却给咱们编码 读程序时带来麻烦,每次来了请求就建立一个Action,一个Action对象对应一个request上下文。
三、因为Struts2须要针对每一个request进行封装,把request,session等servlet生命周期的变量封装成一个Map,供给每一个Action使用,并保证线程安全,因此在原则上,是比较耗费内存的。

四、 拦截器实现机制上,Struts2有以本身的interceptor机制,SpringMVC用的是独立的AOP方式,这样致使Struts2的配置文件量仍是比SpringMVC大。

五、SpringMVC的入口是servlet,而Struts2是filter(这里要指出,filter和servlet是不一样的。之前认为filter是servlet的一种特殊),这就致使了两者的机制不一样,这里就牵涉到servlet和filter的区别了。

六、SpringMVC集成了Ajax,使用很是方便,只需一个注解@ResponseBody就能够实现,而后直接返回响应文本便可,而Struts2拦截器集成了Ajax,在Action中处理时通常必须安装插件或者本身写代码集成进去,使用起来也相对不方便。

七、SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感受太烦乱。

八、spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(固然Struts2也能够经过不一样的目录结构和相关配置作到SpringMVC同样的效果,可是须要xml配置的地方很多)。

九、 设计思想上,Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。

十、SpringMVC开发效率和性能高于Struts2。
十一、SpringMVC能够认为已经100%零配置。

mybatis和ibatis区别

ibatis本是apache的一个开源项目,2010年这个项目由apache software foundation 迁移到了google code,而且更名为mybatis。

一、Mybatis实现了接口绑定,使用更加方便。
在ibatis2.x中咱们须要在DAO的实现类中指定具体对应哪一个xml映射文件,
而Mybatis实现了DAO接口与xml映射文件的绑定,自动为咱们生成接口的具体实现,使用时不须要经过SqlMapClient去指定namespace 和 sql statement id, 只须要在 sql map config 文件中指定接口的 namespace, 而且sql statement id 和 接口的名字意义对应,而后调用对一个接口便可。
注意:
虽然Mybatis支持在接口中直接使用annotation的配置方式来简化配置,
不过强烈建议仍然使用xml配置的方式。毕竟annotation的配置方式功能有限且代码入侵性太强。使用xml配置方式才能体现出Mybatis的优点所在
二、对象关系映射的改进,效率更高
相信不少在使用ibatis2.x的朋友并无经过ibatis的xml映射文件来实现对象间的关系映射。其实也确实没有必要那么作,由于ibatis2.x采用的是“嵌套查询”的方式将对象之间的关系经过查询语句的直接拼装来实现,其效果和在DAO或Service中自行封装是同样的。
不过这种方式存在“N+1查询问题”。
归纳地讲,N+1查询问题能够是这样引发的:
? 你执行了一个单独的SQL语句来获取结果列表(就是+1)。
? 对返回的每条记录,你执行了一个查询语句来为每一个加载细节(就是N)。
这个问题会致使成百上千的SQL语句被执行。这一般不是指望的。

而在Mybatis中,除了兼容ibatis2.x中的“嵌套查询”方式外,还提供了直接“嵌套结果”的方式,其效果至关于直接经过一句sql将查询出的dto对象自动封装成所需的对象。
具体实现方法请自行参考Mybatis官方使用手册,不在此累述.

不过实际上这一改进所带来的好处也是颇有限的。由于这一方式在使用分页的时候并不起做用,或者说嵌套对象的结果集是不容许进行分页的。这一点在Mybatis框架中已经作出了明确的限制(org.apache.ibatis.executor.resultset.NestedResultSetHandler里34行),而实际项目中须要分页的状况又特别多……
仔细一想,一对多映射确实不能经过配置文件来分页,由于这时查询出的记录数并不等于实际返回对象的size,不过一对一映射为何也不容许就不太明白了。多是由于一对一是一对多的特例,而在设计框架的时候并无考虑去处理或是难于处理这一特例吧。
三、MyBatis采用功能强大的基于OGNL的表达式来消除其余元素。
熟悉struts2的人应该对OGNL表达式不会感到陌生,
MyBatis采用OGNL表达式简化了配置文件的复杂性,使用起来更简洁。
补充:比较遗憾的是,Mybatis的分页继续沿用ibatis2.x的逻辑分页方式,依赖于JDBC的规范。大数据量时会出现性能问题,要想实现物理分页还得本身想办法改了。

SSM开发过程:

第一步:先在spring文件夹里新建spring-dao.xml文件,由于spring的配置太多,咱们这里分三层,分别是dao service web。

    1. 读入数据库链接相关参数(jdbc.properties
    2. 配置数据链接池
      1. 配置链接属性,能够不读配置项文件直接在这里写死
      2. 配置c3p0,只配了几个经常使用的
    3. 配置SqlSessionFactory对象(mybatis-config.xml
    4. 扫描dao层接口,动态实现dao接口,也就是说不须要daoImpl,sql和参数都写在xml文件上

第二步:接下来到service层了。在spring文件夹里新建spring-service.xml文件。

  1. 扫描service包全部注解 @Service
  2. 配置事务管理器,把事务管理交由spring来完成
  3. 配置基于注解的声明式事务,能够直接在方法上@Transaction

第三步:配置web层,在spring文件夹里新建spring-web.xml文件。

  1. 开启SpringMVC注解模式,可使用@RequestMapping,@PathVariable,@ResponseBody等
  2. 对静态资源处理,如js,css,jpg等
  3. 配置jsp 显示ViewResolver,例如在controller中某个方法返回一个string类型的”login”,实际上会返回”/WEB-INF/login.jsp”
  4. 扫描web层 @Controller

第四步:最后就是修改web.xml文件了,它在webappWEB-INF下。

web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <!-- 若是是用mvn命令生成的xml,须要修改servlet版本为3.1 --> <!-- 配置DispatcherServlet --> <servlet> <servlet-name>seckill-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置springMVC须要加载的配置文件 spring-dao.xml,spring-service.xml,spring-web.xml Mybatis - > spring -> springmvc --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-*.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>seckill-dispatcher</servlet-name> <!-- 默认匹配全部的请求 --> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> 

第五步:Java后台逻辑代码。

相关文章
相关标签/搜索