[转载] jsp/servlet/struts/hibernate/spring内部实现机制

转载自 http://blog.csdn.net/shanliangliuxing/article/details/6963702

 

正文:

一、JSP工作原理

JSP程序需要运行于特定的Web服务器中,例如Tomcat/WebLogic等。所有JSP文件,在执行的时候都会被服务器端的JSP引擎转换为Servlet程序(Java源文件),然后调用Java编译器将Servlet程序编译为class文件(字节码文件),并由Java虚拟机(JVM)解释执行。JSP的运行原理如图所示:

在一个JSP文件第一次被请求时,JSP擎把该JSP文件转换成为一个servlet。而这个引擎本身也是一个servlet,在JSWDKWEBLOGIC中,它就是JspServletJSP引擎先把该JSP文件转换成一个Java源文件,在转换时如果发现jsp文件有任何语法错误,转换过程将中断,并向服务端和客户端输出出错信息;如果转换成功,JSP引擎用javac把该Java源文件编译成相应的class文件。然后创建一个该SERVLET的实例,该SERVLETjspInit()方法被执行,jspInit()方法在servlet的生命周期中只被执行一次。然后jspService()方法被调用来处理客户端的请求。对每一个请求,JSP引擎创建一个新的线程来处理该请求。如果有多个客户端同时请求该JSP文件,则JSP引擎会创建多个线程。每个客户端请求对应一个线程。以多线程方式执行可大大降低对系统的资源需求,提高系统的并发量及响应时间.但应该注意多线程的编程限制,由于该servlet始终驻于内存,所以响应是非常快的。如果.jsp文件被修改了,服务器将根据设置决定是否对该文件重新编译,如果需要重新编译,则将编译结果取代内存中的servlet,并继续上述处理过程。虽然JSP效率很高,但在第一次调用时由于需要转换和编译而有一些轻微的延迟。此外,如果在任何时候如果由于系统资源不足的原因,JSP引擎将以某种不确定的方式将servlet从内存中移去。当这种情况发生时jspDestroy()方法首先被调用,然后servlet实例便被标记加入"垃圾收集"处理。jspInit()jspDestory()格式如下:可在jspInit()中进行一些初始化工作,如建立与数据库的连接,或建立网络连接,从配置文件中取一些参数等,在jspDestory()中释放相应的资源  

<%!
public void jspInit()
{
      System.out.println("jspinit");  
}
 
%>
 
<%!
public void jspDestory()
{
      System.out.println("jspDestory");  
}
%>

 

二、服务端的输出缓冲

缺省情况下:服务端要输出到客户端的内容,不直接写到客户端,而是先写到一个输出缓冲区中.只有在下面三中情况下,才会把该缓冲区的内容输出到客户端上
1.该JSP网页已完成信息的输出 
2.输出缓冲区已满 
 
3.JSP
中调用了out.flush()
response.flushbuffer()  
输出缓冲区的大小可以用:response.setBufferSize()设置,如下: 
设置输出缓冲区的大小为1KB。或response.setBufferSize(1);  
设置输出缓冲区的大小为0,即不缓冲。或response.setBufferSize(0);  
response.getBufferSize()out.getBufferSize()可取的输出缓冲区的大小,单位为字节.response.isCommitted()可检查看服务端是否已将数据输出到客户端.如果返回值是TRUE则已将数据输出到客户端,FALSE则还没有

 

三、服务端输出重定向

有以下3种方法可以做到输出重定向:  

RESPONSE.SETREDERECT("URL")
 该方法通过修改HTTP协议的HEADER部分,对浏览器下达重定向指令的,使浏览器显示重定向网页的内容. response.sendRedirect("http://localhost:7001/index.html");  
下面的方法也能改变HTTP HEADER属性,它的原理和1是一样的 
<%  
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);  
String newLocn="/index.html";  
response.setHeader("Location",newLocn);  
% >  
采用<JSP:FORWORD>该方法是利用服务器端先将数据输出到缓冲区的机制,在把缓冲区的内容发送到客户端之前,原来的不发送,改为发送该页面的内容,如果在<JSP:FORWORD>之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将不起作用,这一点应该特别注意.如下面的例子中(1)会输出index.html的内容,2不会输出index.html的内容,而是输出out.println("@@@@@@@@@@@@@@@@@");中的内容,并且在服务端会抛出:java.lang.IllegalStateException: Response already committed异常,但客户端没有任何错误输出。 
(1)
<%@page buffer="1kb"%>
 
<%
long i=0;
 
for(i=0;i<10;i++)
{
      out.println("@@@@@@@@@@@@@@@@@");
}
%>
 
<jsp:forward page="./index.html" />
 
 
(2)
<%@page buffer="1kb"%>
 
<%
long i=0;
 
for(i=0;i<600;i++)
{                  
      out.println("@@@@@@@@@@@@@@@@@");
}
%>
 

说明: 
1.
 方法(1),(2)可以使用变量表示重定向的地址;方法(3)不能使用变量表示重定向的地址
String add="./index.html";  
<jsp:forward page= add />  
无法重定向到index.html中去  

String add=http://localhost:7001/index.html  
response.sendRedirect(add);  
可以重定向到http://localhost:7001/index.html中去。 

2.
 采用方法(1),(2)request中的变量(通过request.setAttribute()保存到request中的值)不能在新的页面中采用,采用方法(3).综上,我们应该采用(1),(2)重定向比较好.  


四、JSP中正确应用类:  

应该把类当成JAVA BEAN来用,不要在<% %>中直接使用.如下的代码(1)经过JSP引擎转化后会变为代码(2):
从中可看出如果把一个类在JSP当成JAVA BEAN使用,JSP会根据它的作用范围把它保存到相应的内部对象中.
如作用范围为request,则把它保存到request对象中.并且只在第一次调用(对象的值为null)它时进行实例化.而如果在<% %>中直接创建该类的一个对象,则每次调用JSP,都要重新创建该对象,会影响性能.  

代码(1)
<jsp:useBean id="test" scope="request" class="demo.com.testdemo">
</jsp:useBean>
 
<%
test.print("this is use java bean");
 
testdemo td= new testdemo();
td.print("this is use new");
%>
 


代码(2)
demo.com.testdemo test = (demo.com.testdemo)request.getAttribute("test");  
if (test == null)  
{  
      try  
      {  
                test = (demo.com.testdemo) java.beans.Beans.instantiate(getClass().getClassLoader(),"demo.com.testdemo");  
      }  
      catch (Exception _beanException)  
      {
              throw new weblogic.utils.NestedRuntimeException("cannot instantiate 'demo.com.testdemo'",_beanException);  
      }  
      request.setAttribute("test", test);  
      out.print("\r\n");
}  
out.print("\r\n\r\n\r\n");
test.print("this is use java bean");  
 
testdemo td= new testdemo();
td.print("this is use new");

 

五、JSP的调试 

JSP
的调试比较麻烦,特别是当bean是在一个session中存在时,更加困难。得从好几个页面开始往里面走才行。通常是用out.println()System.out.print()来打一大堆的信息来查问题。如果是用jbuilder做开发,它能直接调试JSP.不过更重要的是知道错误产生的原因及解决方法。下面对一些JSP编程常见错误进行分析。 

(1).java.lang.NullPointerException
异常
一般是对一个为NULL值的变量进行操作引起的.如下面的操作就会抛出
java.lang.NullPointerException
String a = null;  
a.substring(0,1);  
 
为避免这种异常最好在对变量操作之前检查看它是否为NULL.:
<% String ss=Session.getAttribute("NAME")  
if isnull(ss)  {  }  else  {  }  
%>  

(2).JSP
是用JAVA写的,所以它是大小写敏感的,用过其他编程语言的人最容易犯这个错误。另外在浏览器的地址栏中输入的访问JSP的地址也是区分大小写的.http://localhost:7001/demo/t.jsphttp://localhost:7001/Demo/t.jsp是不一样的

(3).
jsp中判断字符串要使用compareTo方法,不要用==,因为在javaString变量不是一个简单的变量而是一个类实例,不同的方法会得到不同的结果,如下所示: 

  String str1="ABCD";  
  String str2="ABCD"; (String str2="AB"+"CD";  
  if (str1==str2)  
   out.print("yes");  
  else  
   out.print("no");  
  结果是"yes" 
  
  String str1,str2,str3;  
  str1="ABCD";  
  str2="AB";  
  str3=str2+"CD";  
  if (str1==str3)  
   out.print("yes");  
  else  
   out.print("no");  
  结果是"no" 

String str1=new String("ABCD");  
  String str2=new String("ABCD");  
  if (str1==str2)  
   out.print("yes");  
  else  
   out.print("no");  
  结果是"no" 

String str1=new String("ABCD");  
  String str2=new String("ABCD");  
  if (str1.compareTo(str2)==0)  
   out.print("yes");  
  else  
   out.print("no");  
  结果是"yes" 

(4)
防止JSPSERVLET中的输出被浏览器保存在缓冲区中:
浏览器在默认情况下会把浏览过的网页保存在缓冲区中,在调试时,一般不希望这样.把下面的脚本加入程序中,就可防止JSPSERVLET中的输出被浏览器保存在缓冲区中 
<%  
response.setHeader("Cache-Control","no-store"); //HTTP 1.1  
response.setHeader("Pragma","no-cache"); //HTTP 1.0  
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server  
%>  
IE中也可通过设置实现:把/工具/INTERNET选项/常规/设置/的检察所存页面的较新版本,设为每次访问该页时都检查.

六、COOKIE

HTTP COOKIE
实质是服务端与在客户端之间传送的普通HTTP,可保存也可不保存在客户的硬盘上.如果保存,每一个文件大小不超过4K的文本文件.多个COOKIE可保存到同一个文件中.如果从编程角度来看,JSPCOOKIE就是JAVA提供的一个类.常用的方法如下所表示,因为客户端可能不接受COOKIE,所以建议不用它,改用SESSION等其他方式。 


public class cookie  
{  
public String getDomain() //
返回该COOKIE的有效域 
public int getMaxAge() //
返回该COOKIE的有效期,单位为秒 
public String getName() //
返回该COOKIE的名称 
public String getPath() //
返回该COOKIE的有效路径 
public boolean getSecure() //
返回该COOKIE的安全设置 
public String getvalue() //
返回该COOKIE的值 
public void setDomain(java.lang.String pattern) //
设置该COOKIE的有效域 
public void setMaxAge(int expiry) //
设置该COOKIE的有效期,单位为秒 
public void setPath(java.lang.String uri) //
设置该COOKIE的有效路径 
public void setSecure(boolean flag) //
设置该COOKIE的安全设置 
public void setvalue(java.lang.String newvalue) //
设置该COOKIE的值 
}  
一个COOKIE包含以下五部分:  

NAME/value
,设置该COOKIE的名字及它保存的值 
COOKIE
通常和服务器相关,如果将域设为JAVA.SUN.COM,那么该COOKIE就和这个域相关,只对该网址起作用,当浏览该网址时,浏览器将把该COOKIE的内容发送给服务端,COOKIE是作为HTTP HEADER的一部分被发送的,如果没有设置域,那么COOKIE就只和创建该COOKIE的服务器相关.  
路径用于指定服务器上可以使用该COOKIE的文件所在的路径,它只对该网址下的该路径下的应用起作用."/"表示服务器上所有目录都可以使用该COOKIE.  
COOKIE
都有一个有效期,有效期默认值为-1,这表示没有保存该COOKIE,当该浏览器退出时,COOKIE立即失效.  
安全选项true/false,如果设置为true,那么在服务端与在客户端之间传送该COOKIE的内容时,采用HTTPS协议.  
如何检查一个客户端是否支持COOKIE的方法:  
用下面的方法写一个COOKIE到客户端,并确认成功 
try  
{  
Cookie c = new Cookie("mycookie","COOKIE TEST");  
response.addCookie(c);  
}  
catch(Exception e)  
{  
     System.out.println(e);  
}  


然后在一个新的JSP文件中:用下面的方法取客户端的COOKIEcookies,如果cookies.length ==0,说明该客户端的浏览器不支持COOKIE  
try  
{  
Cookie[] cookies = request.getCookies();  
if(cookies.length ==0)  
{  
     System.out.println("not support cookie");  
}  
}  
catch(Exception e)  
{  
     System.out.println(e);  
}  



七、JSPSERVLET的区别:

  SUN
首先发展出SERVLET,其功能比较强劲,体系设计也很先进,只是,它输出HTML语句还是采用了老的CGI方式,是一句一句输出,所以,编写和修改HTML非常不方便。后来SUN推出了类似于ASPJSP,把JAVA代码嵌套到HTML语句中,这样,就大大简化和方便了网页的设计和修改。ASPPHPJSP都是嵌套型的SCRIPT语言。一个分布式系统应分为三层:表示层,业务逻辑层,数据存取层,J2EE体系结构中,SERVLET用来写业务逻辑层是很强大的,但是对于写表示层就很不方便。JSP则主要是为了方便写表示层而设计的。ENTITY BEAN现数据存取层,SESSION BEAN实现业务逻辑层。如果是简单的应用系统,可采用JSP+BEANS的结构进行设计,JSP中应该仅仅存放与表示层有关的东西,也就是说,只放输出HTML网页的部份。而所有的数据计算,数据分析,数据库联结处理,统统是属于业务逻辑层,应该放在JAVA BEANS中。通过JSP调用JAVA BEANS,实现两层的整合。实际上,微软的DNA技术,简单说,就是ASP+COM/DCOM技术。与JSP+BEANS完全类似,所有的表示层由ASP完成,所有的业务逻辑由COM/DCOM完成。为什么要采用这些组件技术呢?因为单纯的ASP/JSP语言是非常低效率执行的,如果出现大量用户点击,纯SCRIPT语言很快就到达了他的功能上限,而组件技术就能大幅度提高功能上限,加快执行速度。另外一方面,纯SCRIPT语言将表示层和业务逻辑层混在一起,造成修改不方便,并且代码不能重复利用,采用组件技术就只改组件就可以了。对于复杂的应用,应该采用ENTITY BEAN实现数据存取层,SESSION BEAN实现业务逻辑层,用JSP来调用SESSION BEAN,由SESSION BEAN调用ENTITY BEAN。即采用JSP+EJB来构建一个复杂的分布式系统。它比JSP+BEAN具有更高的吞吐量,可靠性,安全性。综上所述,对简单应用,可采用JSP+BAEN,对复杂的应用系统,应采用JSP+EJBSERVLET变的无足轻重。用JSP完全可替代它。当然不要忘记structs阿:)

 

servlet原理

 struts原理

struts1运行流程图:

上图是Struts1执行流程

Struts1是针对Servlet编程,Struts2是针对Filter编程

struts2并不是一个陌生的web框架,它是以Webwork的设计思想为核心,吸收struts1的优点,可以说

struts2是struts1和Webwork结合的产物。

 

struts2 的工作原理图:

一个请求在Struts2框架中的处理分为以下几个步骤:

1.客户端发出一个指向servlet容器的请求(tomcat);

2.这个请求会经过图中的几个过滤器,最后会到达FilterDispatcher过滤器。

3.过滤器FilterDispatcher是struts2框架的心脏,在处理用户请求时,它和请求一起相互配合访问struts2

  的底层框架结构。在web容器启动时,struts2框架会自动加载配置文件里相关参数,并转换成相应的类。

  如:ConfigurationManager、ActionMapper和ObjectFactory。ConfigurationManager 存有配置文件的一

  些基本信息,ActionMapper存有action的配置信息。在请求过程中所有的对象(Action,Results,

  Interceptors,等)都是通过ObjectFactory来创建的。过滤器会通过询问ActionMapper类来查找请求中

  需要用到的Action。

4.如果找到需要调用的Action,过滤器会把请求的处理交给ActionProxy。ActionProxy为Action的代理对象

  。ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类。

5.ActionProxy创建一个ActionInvocation的实例。ActionInvocation在ActionProxy层之下,它表示了

  Action的执行状态,或者说它控制的Action的执行步骤。它持有Action实例和所有的Interceptor。 

6.ActionInvocation实例使用命名模式来调用,1. ActionInvocation初始化时,根据配置,加载Action相

  关的所有Interceptor。2. 通过ActionInvocation.invoke方法调用Action实现时,执行Interceptor。在

  调用Action的过程前后,涉及到相关拦截器(intercepetor)的调用。

7. 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果

  通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表

  示的过程中可以使用Struts2 框架中继承的标签。

 

struts2拦截器

拦截器:动态拦截Action调用的对象。它提供了一种机制可以使开发者在一个Action执行前执行一段代码或

        一个Action执行后执行一段代码,也可以在一个action执行前阻止其执行,同时也是提供了一种可

        以提取action中可重用的部分的方式。

 

拦截器链:拦截器链就是将拦截器按照一定的顺序连结成一条链。当一些方法或字段被拦截时,拦截器链中

          的拦截器就会按其之前定义的顺序被调用。

 

 

    拦截器几乎完成了Struts2框架70%的工作,包括解析请求参数、将请求参数赋值给Action属性、执行数据校验、文件上传……,Struts2设计的灵巧性,更大程度地得益于拦截器设计,当需要扩展Struts2功能时,只需要提供对应拦截器,并将它配置在Struts2容器中即可;如果不需要该功能时,也只需要取消该拦截器的配置即可。这种可插拔式的设计,正是软件设计领域一直孜孜以求的目标。从某个角度来看,我们可以把Struts2框架理解成一个空壳,而这些拦截器像一个一个抽屉,随时可以插进去,也可以拔出来——这是软件产品一直追求的目标。

 

    Struts2内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default. xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定义的package继承了Struts2的默认struts-default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。

 

struts2的内建默认拦截器:

自定义拦截器:

    其实拦截器就是java类,一般拦截器的定义有两种方式:

    1.实现Interceptor接口 ;

 

         public interface Interceptor {   

              public void init();   

               public void destroy();   

               public String intercept(ActionInvocation invocation)();   

          } 

       实现上述接口;

         public class MyInterceptor implementsInterceptor {   

              public void init();   

               public void destroy();   

               public String intercept(ActionInvocation invocation)(){

                    自定义方法;

               }   

          } 

    2.继承AbstractInterceptor类,重写intercept()方法即可,此方法更可行,其实

      AbstractInterceptor类也就是实现了Interceptor接口;   

 

使用拦截器:在struts.xml中配置

主要:使用了自定义拦截器的action要配置默认拦截器的引用,因为默认拦截器包含了参数的读取、session

     的管理等功。

 

 

Struts1配置文件web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- Standard Action Servlet Configuration (with debugging) -->
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>
      <param-value>2</param-value>
    </init-param>
    <init-param>
      <param-name>detail</param-name>
      <param-value>2</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>


  <!-- Standard Action Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>  
</web-app>

 

其中<load-on-startup>2</load-on-startup>表示服务器启动的时候就初始化servlet实例,而不是等到第一次用到servlet的时候才初始化,值越小表示越优先启动


Struts2配置文件web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <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>
</web-app>

 

Struts工作机制?为什么要使用Struts?  
工作机制:  
Struts的工作流程:  
在web应用启动时就会加载初始化ActionServlet,ActionServlet从  
struts-config.xml文件中读取配置信息,把它们存放到各种配置对象  
当ActionServlet接收到一个客户请求时,将执行如下流程.  
  -(1)检索和用户请求匹配的ActionMapping实例,如果不存在,就返回请求路径无效信息;  
  -(2)如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中;  
  -(3)根据配置信息决定是否需要表单验证.如果需要验证,就调用ActionForm的validate()方法;  
  -(4)如果ActionForm的validate()方法返回null或返回一个不包含ActionMessage的ActuibErrors对象, 就表示表单验证成功; 
  -(5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给哪个Action,如果相应的 Action实例不存在,就先创建这个实例,然后调用Action的execute()方法; 
  -(6)Action的execute()方法返回一个ActionForward对象,ActionServlet在把客户请求转发给 ActionForward对象指向的JSP组件; 
  -(7)ActionForward对象指向JSP组件生成动态网页,返回给客户; 

为什么要用:  
JSP、Servlet、JavaBean技术的出现给我们构建强大的企业应用系统提供了可能。但用这些技术构建的系统非常的繁乱,所以在此之上,我们需要一个规则、一个把这些技术组织起来的规则,这就是框架,Struts便应运而生。 

基于Struts开发的应用由3类组件构成:控制器组件、模型组件、视图组件 

web应用程序启动时就会加载并初始化ActionServler。用户提交表单时,一个配置好的ActionForm对象被创建,并被填入表单相应的数据,ActionServler根据Struts-config.xml文件配置好的设置决定是否需要表单验证,如果需要就调用ActionForm的Validate()验证后选择将请求发送到哪个Action,如果Action不存在,ActionServlet会先创建这个对象,然后调用Action的execute()方法。Execute()从ActionForm对象中获取数据,完成业务逻辑,返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指定的jsp组件,ActionForward对象指定的jsp生成动态的网页,返回给客户。

 

 

struts1与struts2的区别?
什么是Struts2  

虽然Struts2号称是一个全新的框架,但这仅仅是相对Struts 1而言。Struts 2 与Struts 1相比,确实有很多革命性的改进,但它并不是新发布的新框架,而是在另一个赫赫有名的框架:WebWork基础上发展起来的。从某种程度上来讲,Struts2没有继承Struts 1的血统,而是继承WebWork的血统。或者说,WebWork衍生出了Struts2,而不是Struts 1衍生了Struts2。因为Struts2是WebWork的升级,而不是一个全新的框架,因此稳定性、性能等各方面都有很好的保证:而且吸收了Struts 1和WebWork两者的优势,因此,是一个非常值得期待的框架。

  Apache Struts2是一个优雅的,可扩展的JAVA EE web框架。框架设计的目标贯穿整个开发周期,从开发到发布,包括维护的整个过程。

  Apache Struts 2即是之前大家所熟知的WebWork 2。在经历了几年的各自发展后,WebWork和Struts社区决定合二为一,也即是Struts 2


Action类 
Struts1要求Action类要扩展自一个抽象基类。Struts1的一个共有的问题是面向抽象类编程而不是面向接口编程。 
Struts2的Action类实现了一个Action接口,连同其他接口一起实现可选择和自定义的服务。Struts2提供一个名叫ActionSupport的基类实现一般使用的接口。虽然,Action接口不是必须的。任何使用execute方法的POJO对象可以被当作Struts2的Action对象使用。

线程模型 
Struts 1 Action类是单例类,因只有一个示例控制所有的请求。单例类策略造成了一定的限制且给开发带来了额外的烦恼。Action资源必须是程安全或者同步的。
Struts 2 Action对象每一个请求都实例化对象,所以没有程安全的问题。(实践中,servlet容器生许多丢的对象对于每一个请求,多于一个的对象并不影响垃圾收集)

Servlet 依赖 
Struts 1的Action类依赖于servlet API以HttpServletRequest和HttpServletResponse作参数传给execute方法当Action被调用时。
Struts 2的Action不和容器有关。Servlet上下文被表现简单的Maps,允许Action被独立的测试。Struts 2的Action可以访问最初的请求和相应,如果需要的话。然而,其他的架构元素少或者排除直接访问HttpServletRequest或者HttpServletResponse的需要。

易测性 
测试Struts 1的主要障碍是execute方法暴露了Servlet API。第三方的扩展,Struts测试用例,提供Struts 1的集合对象。 
Struts 2的Action可以通过实例化Action测试,设置属性,然后调用方法。依赖注入的支持也是测试变得更简单。

接受输入 
Struts 1使用ActionForm对象捕获输入。象Action一样,所有的ActionForm必须扩展基类。因其他的JavaBean不能作ActionForm使用,开发者经常创建多余的类捕获输入。DynaBeans可以被用来作替代ActionForm的类创建。但是开发者可以重新描述已经存在的JavaBean。
Struts 2 Action属性作输入属性,排除第二个输入对象的需要。输入属性可能有丰富的对象类型这些类型有他们自己的属性。Action的属性可以通过标签库访问。Struts 2也支持ActionForm形式。丰富的对象类型,包含业务或者域对象,可以被当作输入或者输出对象使用。馍型驱动特性简化标签对POJO输入对象的引用。

表达式语言 
Struts 1整和JSTL,所以它使用JSTL的表达式语言。表达式语言有基本的图形对象移动,但是相对很弱的集合和被索引的属性支持。 
Struts 2使用JSTL,但是框架也支持更大和更灵活的表达式,叫做“对象图形符号语言”(OGNL)。

将值绑定要视图上 
Struts 1使用标准JSP机制来绑定对象到页面上下文。 
Struts 2使用“ValueStack”技术了标签库可以不用链接你的视图到对象的表现类型访问值。ValueStack策略允许重用视图。

类型转换 
Struts 1的ActionForm属性经常都是String的。Struts 1使用Commons-Beanutils类型转换。转换每一个类,不是每一个实例配置。
Struts 2使用OGNL类型转换。框架包含转换器基本的和共同的对象类型和原始类型。

验证 
Struts 1支持手动验证凭借ActionForm的validate方法,或者通过扩展的公用验证器。类可以有不同的验证上下文未相同的类,但是不能不能包括验证子对象。
Struts 2支持手动验证凭借validate方法和XWork验证框架。Xwork验证框架支持一连串的验证子属性使用的验证了属性类的类型和严正上下文而定义。

Action执行的控制 
Struts 1支持独立的请求处理器对于每一个模型,但是所有在模型中的Action必须共享同一个生命周期。 
Struts 2支持在每一个Action基础上凭借拦截栈创建不同的生命周期。自定义栈可以被创建且使用不同的所需 的Action。 

 

Hibernate原理

Hibernate是采用ORM模式实现数据持久层的java组件。它提供了高效的、强大的将java对象进行数据持久化操作的服务。利用hibernate,开发人员可以按照java对象的结果进行持久层的开发,并可以完成java对象和关系型数据库之间的转换和操作。

Hibernate工作原理及为什么要用?
原理:  
1.读取并解析配置文件  
2.读取并解析映射信息,创建SessionFactory  
3.打开Sesssion  
4.创建事务Transation  
5.持久化操作  
6.提交事务  
7.关闭Session  
8.关闭SesstionFactory 

为什么要用:  
1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 

2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 

3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。 

4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。 

2. Hibernate是如何延迟加载?  
1. Hibernate2延迟加载实现:a)实体对象 b)集合(Collection) 

2. Hibernate3 提供了属性的延迟加载功能 

当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。 

3.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系) 

类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、 

4. 说下Hibernate的缓存机制 

1. 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存 

2. 二级缓存:  
a) 应用及缓存  
b) 分布式缓存  
条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非 关键数据  
c) 第三方缓存的实现 

5. Hibernate的查询方式  
Sql、Criteria,object comptosition  
Hql:  
1、 属性查询  
2、 参数查询、命名参数查询  
3、 关联查询  
4、 分页查询  
5、 统计函数 

6. 如何优化Hibernate?  
1.使用双向一对多关联,不使用单向一对多  
2.灵活使用单向一对多关联  
3.不用一对一,用多对一取代  
4.配置对象缓存,不使用集合缓存  
5.一对多集合使用Bag,多对多集合使用Set  
6. 继承类使用显式多态  
7. 表字段要少,表关联不要怕多,有二级缓存撑腰 

 

hibernate的缓存:为了提高系统性能,hibernate也使用了缓存机制。在hibernate框架中,主要包含两个

                 方面的缓存,一级缓存和二级缓存。hibernate缓存的作用主要表现在以下两个方面:

                 1 通过主键(ID)加载数据的时候 2 延迟加载中。

一级缓存:hibernate的一级缓存是由session提供的,因此它只存在session的生命周期中。也就是说

          session关闭的时候该session所管理的一级缓存也随之被清除。hibernate的一级缓存是

          session所内置的,不能被卸载,也不能进行任何配置。一级缓存采用的是Key-Value的MAP方式

          来实现的。在缓存实体对象时,对象的主关键字ID是MAP的Key,实体对象就是对象的值。所以说

          一级缓存是以实体对象为单位进行存储的。访问的时候使用的是主键关键字ID。一级缓存使用的

          是自动维护的功能。但可以通过session提供的手动方法对一级缓存的管理进行手动干预。

          evict()方法用于将某个对象从session的一级缓存中清除。clear()方法用于将session缓存中的

          方法全部清除。

    

二级缓存:SessionFactory提供的缓存机制可以将缓存分为内置缓存和外置缓存。内置缓存存放了映

          射文件中数据的副本和预定义SQL语句。SessionFactory的外置缓存就是我们的二级缓存

          。它是一个可配置的插件,默认情况下SessionFactory不会启用这个插件,外置缓存的数据是数

          据库数据的副本。外置缓存的介质可以是内存或者硬盘。二级缓存的实现原理与一级缓存是一样

          的。也是通过Key-Value的Map来实现对对象的缓存。二级缓存是作用在SessionFactory范围内的

          。因此它比一级缓存的范围更广。它可被所有的Session对象所共享。需要注意的是放入缓存中

          的数据不能有第三方的应用对数据进行修改。

 

Hibernate实体对象的生命周期

     实体对象的生命周期主要存在三种不同状态:瞬态、持久态和游离态。

     瞬态:表示该实体对象在内存中是自由自在的。与数据库中的数据没有任何关系。与session没有任何

           关系,也就是没有通过session的实例对其任何持久化的操作。

     持久态:该实体对象处于hibernate框架所管理的状态。也就是说这个对象是与session的实体对象相

             关的。处于持久态的实体对象的特征就是其所作的任何的变更操作都将被Hibernate持久化到

             数据库中。我们可以说持久态的周期与其对应的session的周期息息相关的。hibernate会依

             据处于持久态的实体对象的属性变化而改变数据库中的对应记录。

     游离态:处于持久态的实体对象,当不再与其对应的session对象相关联时,就处于游离态。

 

 

 

spring原理

spring IOC(控制反转)浅析

简单的来说,spring是一个轻量级的开源的控制反转(IOC)和面向切面(AOP)的容器框架。主要是为了解决企业应用程序开发中的复杂性而创建的。它的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架(struts、hibernate等)。Spring由 7 个定义良好的模块组成,Spring 模块构建在核心容器之上(就是我们所说的IOC容器),核心容器定义了创建、配置和管理 bean 的方式。组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。spring的目标是实现一个全方位的整合框架,在spring框架下实现多个子框架的组合,这些子框架之间可以相互独立,也可以使用其他框架方案加以替代。

 

IOC:控制反转,它是不是什么技术,它是一种设计模式。所谓控制反转就是由容器控制程序间的关系,而

     不是传统实现中,由编程代码直接操控。说白了就是由容器控制对象间的依赖关系。

DI:Dependency Injection 依赖注入 ,即组件(对象)之间的依赖关系由容器在运行期间决定。其实依赖注

    入和控制反转是对同一概念的不同描述。

 

    Spring通过这种控制反转(IoC)的设计模式促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。我们可以把IoC模式看做是工厂模式的升华,可以把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java的“反射”编程,根据XML中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。


    (自己理解的白话)其实控制反转就是不需要我们手动new一个对象了,它把我们所要实例化的对象都写在了配置文件xml中了,一般这个类都是我们应用的业务类。框架内部已经将xml中配置的类自动实例化成对象,当我们调用某个类A,并且这个类中存在另一个类B时,我们就说A依赖于B,容器就会将B对象注入到A类中,大多数情况下都是通过A类中的setB()方法注入进来的。以前是由类中的代码查找类并new对象,现在是xml文件控制的对象的生成,控制权由程序代码转移到了xml文件中。这样做还是有好处的,假如在A中需要5个对象,那么A类中就会new5个对象,不管以后A中用不用到这5个类,只要用到A类,就会把这5个类全部new出来。如果我们在xml文件中定义类的话,当类需要用到其中的三个类时,就会用对应的set类()方法将对象注入进来,不用的就不注入进来,由此看来,第一个方法时将类A和5个类紧紧联系起来,不管用不用到5个类都new一下,真浪费,而第二个方法是第一个类你需要我得时候我就注入进来被你用,你不需要就和我没关系。这样类A和其中的5个类是分别独立的互不干预,当有关系的时候,容器自动注入关系。没关系的时候,你是老大,我也是大哥!

Spring AOP

为什么用AOP?

  1.为了方便,看一个国外很有名的大师说,编程的人都是“懒人”,因为他把自己做的事情都让程序做

    了。用了aop能让你少写很多代码,这点就够充分了吧 。
  2.就是为了更清晰的逻辑,可以让你的业务逻辑去关注自己本身的业务,而不去想一些其他的事情,这些

    其他的事情包括:安全,事物,日志等。

 

AOP原理:

    spring用代理类包裹切面,把他们织入到Spring管理的bean中。也就是说代理类伪装成目标类,它会截取对目标类中方法的调用,让调用者对目标类的调用都先变成调用伪装类,伪装类中就先执行了切面,再把调用转发给真正的目标bean。
    现在可以自己想一想,怎么搞出来这个伪装类,才不会被调用者发现(过JVM的检查,JAVA是强类型检查,哪里都要检查类型)。
    1.实现和目标类相同的接口,我也实现和你一样的接口,反正上层都是接口级别的调用,这样我就伪装

      成了和目标类一样的类(实现了同一接口,咱是兄弟了),也就逃过了类型检查,到java运行期的时

      候,利用多态的后期绑定(所以spring采用运行时),伪装类(代理类)就变成了接口的真正实现,

      而他里面包裹了真实的那个目标类,最后实现具体功能的还是目标类,只不过伪装类在之前干了点事


      这就好比,一个人让你办件事,每次这个时候,你弟弟就会先出来,当然他分不出来了,以为是你,

      你这个弟弟虽然办不了这事,但是他知道你能办,所以就答应下来了,并且收了点礼物(写日志),

      收完礼物了,给把事给人家办了啊,所以你弟弟又找你这个哥哥来了,最后把这是办了的还是你自

      己。但是你自己并不知道你弟弟已经收礼物了,你只是专心把这件事情做好。

     
      顺着这个思路想,要是本身这个类就没实现一个接口呢,你怎么伪装我,我就压根没有机会让你搞出

      这个双胞胎的弟弟,那么就用第2种代理方式,创建一个目标类的子类,生个儿子,让儿子伪装我。

 

   2.生成子类调用,这次用子类来做为伪装类,当然这样也能逃过JVM的强类型检查,我继承的吗,当然  

     查不出来了,子类重写了目标类的所有方法,当然在这些重写的方法中,不仅实现了目标类的功能,

     还在这些功能之前,实现了一些其他的(写日志,安全检查,事物等)。


     这次的对比就是,儿子先从爸爸那把本事都学会了,所有人都找儿子办事情,但是儿子每次办和爸爸

     同样的事之前,都要收点小礼物(写日志),然后才去办真正的事。当然爸爸是不知道儿子这么干的

     了。 这里就有件事情要说,某些本事是爸爸独有的(final的),儿子学不了,学不了就办不了这件

     事,办不了这个事情,自然就不能收人家礼了。 

     前一种兄弟模式,spring会使用JDK的java.lang.reflect.Proxy类,它允许Spring动态生成一个新类

     来实现必要的接口,织入通知,并且把对这些接口的任何调用都转发到目标类。 

     后一种父子模式,spring使用CGLIB库生成目标类的一个子类,在创建这个子类的时候,spring织入通

     知,并且把对这个子类的调用委托到目标类。

   
    相比之下,还是兄弟模式好些,他能更好的实现松耦合,尤其在今天都高喊着面向接口编程的情况下,

    父子模式只是在没有实现接口的时候,也能织入通知,应当做一种例外。

 

 

 强调在回答的时候不要光回答概念,要思维扩散性的讲些相关的东西 

spring 的优点? 
1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 
2.可以使用容易提供的众多服务,如事务管理,消息服务等 
3.容器提供单例模式支持 
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 
5.容器提供了众多的辅助类,能加快应用的开发 
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等 
7.spring属于低侵入式设计,代码的污染极低 
8.独立于各种应用服务器 
9.spring的DI机制降低了业务对象替换的复杂性 
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部 

什么是DI机制? 
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色 
需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中 
创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者 
因此也称为依赖注入。 
spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。 
设置注入的优点:直观,自然 
构造注入的优点:可以在构造器中决定依赖关系的顺序。 

什么是AOP? 
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面 
1.面向切面编程提供声明式事务管理 
2.spring支持用户自定义的切面 

面向切面编程(aop)是对面向对象编程(oop)的补充, 
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。 
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象, 
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。 

aop框架具有的两个特征: 
1.各个步骤之间的良好隔离性 
2.源代码无关性

 

 

Spring的IoC,又叫DI,是怎样实现的呢?
java1.3之后一个重要特征是反射reflection,它允许程序在运行的时候运态的生成对象、执行对象的方法、改变对象的属性,Spring就是通过反射来实现注入的。

反射有两个缺点。第一个是性能问题。用于字段和方法接入时反射要远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。即使测试中最坏情况下的计时图显示的反射操作只耗用几微秒。仅反射在性能关键的应用的核心逻辑中使用时性能问题才变得至关重要。

许多应用中更严重的一个缺点是使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。反射代码比相应的直接代码更复杂,正如性能比较的代码实例中看到的一样。解决这些问题的最佳方案是保守地使用反射——仅在它可以真正增加灵活性的地方——记录其在目标类中的使用。

 

 

 

 

在Struts + Spring + Hibernate的组合框架模式中,三者各自的特点都是什么?

Struts 的MVC设计模式可以使我们的逻辑变得很清晰。 
Spring 的IOC和AOP可以使我们的产品在最大限度上解藕。 
hibernate的当然就是实体对象的持久化了

典型的J2EE三层结构,分为表现层、中间层(业务逻辑层)和数据服务层。三层体系将业务规则、数据访问及合法性校验等工作放在中间层处理。客户端不直接与数据库交互,而是通过组件与中间层建立连接,再由中间层与数据库交互。

表现层是传统的JSP技术,自1999年问世以来,经过多年的发展,其广泛的应用和稳定的表现,为其作为表现层技术打下了坚实的基础。

中间层采用的是流行的Spring+Hibernate,为了将控制层与业务逻辑层分离,又细分为以下几种。

Web层,就是MVC模式里面的“C”(controller),负责控制业务逻辑层与表现层的交互,调用业务逻辑层,并将业务数据返回给表现层作组织表现,该系统的MVC框架采用Struts。

Service层(就是业务逻辑层),负责实现业务逻辑。业务逻辑层以DAO层为基础,通过对DAO组件的正面模式包装,完成系统所要求的业务逻辑。

DAO层,负责与持久化对象交互。该层封装了数据的增、删、查、改的操作。

PO,持久化对象。通过实体关系映射工具将关系型数据库的数据映射成对象,很方便地实现以面向对象方式操作数据库,该系统采用Hibernate作为ORM框架。

Spring的作用贯穿了整个中间层,将Web层、Service层、DAO层及PO无缝整合,其数据服务层用来存放数据。

一个良好的框架可以让开发人员减轻重新建立解决复杂问题方案的负担和精力;它可以被扩展以进行内部的定制化;并且有强大的用户社区来支持它。框架通常能很好的解决一个问题。然而,你的应用是分层的,可能每一个层都需要各自的框架。仅仅解决UI问题并不意味着你能够很好的将业务逻辑和持久性逻辑和UI 组件很好的耦合。

 

 

在SSH架构中出现异常时
1、要进行捕获且展现友好的信息给用户
2、要记录出现的异常供维护人员回溯问题

想到的几个点
1、利用web应用的error-page可以处理
2、利用struts的global-exception好像也可以处理
3、hibernate是不是对异常进行了封装或者也有自己的处理机制
3、spring中aop的afterThrowing可以捕获并记录异常
4、捕获到的异常是不是最原始的异常信息,还是经过封装的?
5、aop处理异常对性能影响如何?如果架构中使用了缓存机制,是否会有影响?
6、是不是需要处理异常,抛出自定义的异常?
7、ajax方式,后台异常如何处理?


1.对一个需要提供稳定、高质量的WEB系统而言,
 对整个WEB程序的入口、出口的异常处理都需要做封装。
2.Logic、DAO可以根据需要,向上层抛出相应的Exception,
 而这些Exception都必须在Action截住,也就是封装起来,向View返回一个合适的信息。
3.发生异常之后,返回到View的信息,可以是给人看得HTML也可以是给JavaScript看的JSON,
 所以,普通页面的异常,可以显示错误页面;Ajax发生的异常,可以返回一个包容错误信息的JSON,让Ajax显示出来。
4.很多异常处理是在设计阶段就可以预见的,不要用Spring的AOP拦截,这样会对系统性能操成恶性的影响。
 可以做一个BaseAction,把共通的处理写在里面。
5.具体的,抛出、捕获什么样的异常信息,根据系统实际处理内容确定。
 根据不同的异常,可以让接收方程序作相应的处理——不局限于错误处理。

 

能捕获的可控制的异常,就不要让用户知道太多细节。可以改成一些客户能理解的信息。

比如网络连接中断,而不是IOException, 比如服务器忙,而不是SocketTimeOutExceotion等

总之,大部分异常我们都可以预先捕获的。那些我们程序的bug,由于各种原因没有捕获,比如空指针,必须用errorPage进行最后的处理。

不能让用户认为我们系统出了什么大问题了。


1、利用web应用的error-page可以处理 
个人感觉这个方式不好,很显然不好统一定制。
2、利用struts的global-exception好像也可以处理 
还可以,简单的应用可以试试
3、hibernate是不是对异常进行了封装或者也有自己的处理机制 
对你来说没影响,可以不管他,有封装,但是好像没处理机制
3、spring中aop的afterThrowing可以捕获并记录异常 
推荐记录,记录后利用异常链继续向上抛runtime非必捕获异常
4、捕获到的异常是不是最原始的异常信息,还是经过封装的?  
跟异常链有关,一般java新手写的程序95%断链,开源框架的异常可以追溯到原始的信息
5、aop处理异常对性能影响如何?如果架构中使用了缓存机制,是否会有影响?  
异常的捕获确实有性能影响的,个人感觉影响不大,比较异常是偶然发生的。
你指的缓存不明白如何影响异常的捕获
6、是不是需要处理异常,抛出自定义的异常? 
当一段代码抛异常的时候,你要看你能不能在catch块内修复程序,让程序继续走不会出问题,否则不建议catch
业务系统比较大的话可以自己模仿开源框架那样定义业务异常,和逻辑异常。方便逻辑判断例如使用instanceof
7、ajax方式,后台异常如何处理? 
向上抛,或者在jsp中发现异常,然后throw出来,直到jsb报红叉为止,否则ajax判断的状态码永远是对的。

在有一个地方可以捕获异常,过滤器。

 

 

 java异常处理的原则和技巧:
1.避免过大的try块,不要把不会出现异常的代码放到try块里面,尽量保持一个try块对应一个或多个异常
2.细化异常的类型,不要不管什么类型的异常都写成Exception
3.catch块尽量保持一个块捕获一类异常,不要忽略捕获的异常,捕获到后要么处理,要么转译,要么重新抛出新类型的异常。
4.不要把自己能处理的异常抛给别人。
5.不要用try...catch参与控制程序流程,异常控制的根本目的是处理程序的非正常情况。

 

SSH知识总结

1 什么是MVC思想?

    答:即Model-View-Controller,即把一个应用的流程按照Model、View、Controller的方式                    进行分离。MVC开发模式的思想是将业务逻辑和页面显示分离开来,实现程序的低耦合。一般在java中,充当视图层的是html和jsp页面,即用户看到并与之交互的界面。模型层一般是javabean,用来处理一些业务逻辑和数据传递,如连接数据库和实体类,控制器的话是用servlet来表示的,用来做流程控制和页面转向。

 

2 说说你知道的框架?

    答:有struts,spring,hibernate

Struts
Struts是一个基于Sun J2EE平台的MVC框架,主要是采用Servlet和JSP技术来实现的。
Struts框架可分为以下四个主要部分,其中三个就和MVC模式紧密相关:
 1、模型(Model),本质上来说在Struts中Model是一个Action类(这个会在后面详细讨论),开发者通过其实现商业逻辑,同时用户请求通过控制器(Controller)向Action的转发过程是基于由struts-config.xml文件描述的配置信息的。
 2、视图(View),View是由与控制器Servlet配合工作的一整套JSP定制标签库构成,利用她们我们可以快速建立应用系统的界面。
 3、控制器(Controller),本质上是一个Servlet,将客户端请求转发到相应的Action类
 4、一堆用来做XML文件解析的工具包,Struts是用XML来描述如何自动产生一些JavaBean的属性的,此外Struts还利用XML来描述在国际化应用中的用户提示信息的(这样一来就实现了应用系统的多语言支持)。

 

Spring
Spring是轻量级的J2EE应用程序框架。
Spring的核心是个轻量级容器(container),实现了IoC(Inversion of Control)模式的容器,Spring的目标是实现一个全方位的整合框架,在Spring框架下实现多个子框架的组合。

 

Hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了轻量级的对象封装,使得Java程序员可以使用对象编程思维来操纵数据库。Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化。它还可以应用在任何使用JDBC的场合,既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用。


AJAX
全称“Asynchronous JavaScript and XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。

3 什么是Struts2,Struts2有哪些作用?(struts2,spring和hibernate在ssh框架中各起到什么作用?)

    答:struts2本身是一个MVC框架。

在整合的ssh框架中,struts2 起控制作用的,hibernate 操作数据库的,spring用来解耦的
详细的说:
struts2在 SSH 框架中起控制的作用 , 其核心是 Controller, 即 ActionServlet, 而 ActionServlet 的核心就是 Struts-config.xml. 主要控制逻辑关系的处理 .

hibernate 是数据持久化层 , 是一种新的对象、关系的映射工具 , 提供了从 Java 类到数据表的映射,也提供了数据查询和恢复等机制 , 大大减少数据访问的复杂度。把对数据库的直接操作 , 转换为对持久对象的操作 .
spring是一个轻量级的控制反转 (IoC) 和面向切面 (AOP) 的容器框架 , 面向接口的编程 , 由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓 “ 控制反转 ” 的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。依赖注入,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中
起到的主要作用是解耦。


Struts 、spring、 Hibernate 在各层的作用


1 ) struts 负责 web 层 .
ActionFormBean 接收网页中表单提交的数据,然后通过 Action 进行处理,再 Forward 到对应的网页
在 struts-config.xml 中定义 <action-mapping>, ActionServlet 会加载。


2 ) spring 负责业务层管理,即 Service (或 Manager).
1 . service 为 action 提供统计的调用接口,封装持久层的 DAO.
2 .可以写一些自己的业务方法。
3 .统一的 javabean 管理方法
4 .声明式事务管理
5.  集成 Hiberante

3 ) Hiberante ,负责持久化层,完成数据库的 crud(增删改查) 操作
hibernate 为持久层,提供 OR/Mapping 。
它有一组 .hbm.xml 文件和 POJO, 是跟数据库中的表相对应的。然后定义 DAO ,这些是跟数据库打交道的类,它们会使用 PO 。


在 struts+spring+hibernate 的系统中,
对象的调用流程是: jsp-> Action -> Service ->DAO ->Hibernate 。
数据的流向是 ActionFormBean 接受用户的数据, Action 将数据从 ActionFromBean 中取出,封装成 VO 或 PO,
再调用业务层的 Bean 类,完成各种业务处理后再 forward 。而业务层 Bean 收到这个 PO 对象之后,会调用 DAO 接口方法,进行持久化操作。

 

4 Struts2与Struts1相比有什么优点或者说区别?(说说最主要2到3点的就行了)

答:1 类

• Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。

• Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2   提供一个ActionSupport基类去实现常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。

  2 线程模式:
 

• Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。(单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。)

• Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)

3 Servlet 依赖:

• Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。

• Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。

4 可测性:

• 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。

• Struts 2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。

5 捕获输入:

• Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存在的

6 JavaBean(仍然会导致有冗余的javabean)。

• Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。

表达式语言:

• Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引7 属性的支持很弱。

• Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).

8 绑定值到页面(view):

• Struts 1使用标准JSP机制把对象绑定到页面中来访问。

• Struts 2 使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。

9 类型转换:

• Struts 1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。

• Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。

10 校验:

• Struts 1支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。

• Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性

11 Action执行的控制:

• Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。

• Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。

——————————————————————————————————

个人觉得Struts1是基于servlet开发,Struts2是基于Filter开发,相对于现在的企业来说Struts1的技术成熟,便于维护,而且现在的许多程序员使用SSH框架时,还是多选用struts1来开发~~

当然Struts2安全性比Struts1要高~~

 

4.1  struts1.2和struts2.0的区别?

     struts1.2和struts2.0的对比

   a、Action类:

      struts1.2要求Action类继承一个基类。struts2.0 Action要求继承ActionSupport基类

   b、线程模式

      struts1.2 Action是单例模式的并且必须是线程安全的,因为仅有一个Action的实例来处理所有的请求。

      单例策略限制了Struts1.2 Action能做的事情,并且开发时特别小心。Action资源必须是线程安全的或同步的。

      struts2.0 Action为每一个请求产生一个实例,因此没有线程安全问题。

   c、Servlet依赖

      struts1.2 Action依赖于Servlet API,因为当一个Action被调用时HttpServletRequest和HttpServletResponse被传递给execut方法。

      struts2.0 Action不依赖于容器,允许Action脱离容器单独测试。如果需要,Struts2 Action仍然可以访问初始的Request和Response。

      但是,其他的元素减少或者消除了直接访问HttpServletRequest和HttpServletResponse的必要性。

   d、可测性

      测试struts1.2 Action的一个主要问题是execute方法暴露了Servlet API(这使得测试要依赖于容器)。一个第三方扩展:struts TestCase

      提供了一套struts1.2的模拟对象来进行测试。

      Struts2.0 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”也使得测试更容易。
4.2  struts2.0的MVC模式,与struts1.0的区别

 struts2的mvc模式:当用户在页面提交用户请求时,该请求需要提交给struts2的控制器处理。struts2的控制器根据处理结果,决定将哪个页面呈现给客户端。

    与struts1最大的不同是:struts2的控制器。struts2的控制器不再像struts1的控制器,需要继承一个Action父类,甚至可以无需实现

    任何接口,struts2的Action就是一个普通的POJO。实际上,Struts2 的Action就是一个包含execute方法的普通Java类

    该类里包含的多个属性用于封装用户的请求参数。

 

5 Struts2的用法,好处?你用到了struts2的哪些东西?

1         Struts2基于MVC架构,框架结构清晰,开发流程一目了然,开发人员可以很好的掌控开发的过程。我在项目开发过程中,一个具体的功能的开发流程是:拿到一个具体的功能需求文档和设计好的前台界面(在开发中我不负责设计页面),分析需要从前台传递哪些参数,确定参数的变量名称,在Action中设置相应的变量,这些参数在前台如何显示,并将页面上的一些控件适当使用Struts2提供的服务器端控件来代替,编写Action对应的方法来完成业务逻辑,最后,做一些与配置文件相关的设置。当然实际的开发比这个过程要复杂,涉及到数据库,验证,异常等处理。但是使用Struts2进行开发,你的关注点绝大部分是在如何实现业务逻辑上,开发过程十分清晰明了。

2         使用OGNL进行参数传递。OGNL(Object-Graph Navigation Language是一种EL表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。)提供了在Struts2里访问各种作用域中的数据的简单方式,你可以方便的获取Request,Attribute,Application,Session,Parameters中的数据。大大简化了开发人员在获取这些数据时的代码量。

3         强大的拦截器Struts2 的拦截器是一个Action级别的AOP,Struts2中的许多特性都是通过拦截器来实现的,例如异常处理,文件上传,验证等。拦截器是可配置与重用的,可以将一些通用的功能如:登录验证,权限验证等置于拦截器中以完成一些Java Web项目中比较通用的功能。在我实现的的一Web项目中,就是使用Struts2的拦截器来完成了系统中的权限验证功能。

4         易于测试Struts2的Action都是简单的POJO,这样可以方便的对Struts2的Action编写测试用例,大大方便了Java Web项目的测试。

5         易于扩展的插件机制在Struts2添加扩展是一件愉快而轻松的事情,只需要将所需要的Jar包放到WEB-INF/lib文件夹中,在struts.xml中作一些简单的设置就可以实现扩展。

6         模块化Struts2已经把模块化作为了体系架构中的基本思想,可以通过三种方法来将应用程序模块化:将配置信息拆分成多个文件,把自包含的应用模块创建为插件创建新的框架特性,即将与特定应用无关的新功能组织成插件,以添加到多个应用中去。

7         全局结果与声明式异常为应用程序添加全局的Result,和在配置文件中对异常进行处理,这样当处理过程中出现指定异常时,可以跳转到特定页面,这一功能十分实用。

 

6 Struts的工作原理(内部运行机制,体系结构,控制流程)?(结合流程来说)

答:总共八步:

1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求;

2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin);

3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action;

4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;

5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类;

6、ActionProxy创建一个ActionInvocation的实例。

7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。

8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper。

 

7 Struts2一个请求的生命周期(工作流程)?

答:七步:

1.    用户发送请求 : 用户为访问资源向服务器发送请求.

2.   FilterDispatcher决定适当的action : FilterDispatcher接受请求然后决定调用适当的action

3.    调用拦截器 : 配置拦截器来应用常用的功能如工作流,验证,文件上传等,都是自动应用于请求的.

4.    action的执行 : 然后action将被执行来调用诸如存储数据、检索数据之类的数据库相关操作.

5.   呈递输出 : 结果呈递到输出

6.    返回请求 : 请求通过拦截器按照相反的顺序返回,返回的请求可以允许我们执行一些清理或额外的处理

7.    向用户展示结果 : 控制权最终回归到输出结果至用户浏览器的Servlet容器

 

8 Struts.xml都配置了什么?、

 答:1 全局属性,

     2 <include>引入其他配置文件

     3 <package>来管理Action和拦截器等

     4 全局的<result>

Struts2允许我们定义异常处理器和拦截器

l 异常处理器

异常处理器允许我们定义基于局部和全局的异常处理程序.Struts2捕获到异常后会将恰当的信息和异常的详情显示在我们指定的页面上.

l 拦截器

拦截器详细说明了一个action的请求流程的生存周期.配置的拦截器对请求实现了一些常用的功能如工作流,验证等.

 

9 什么是过滤器,什么是监听器?什么是拦截器,三者的区别?

答:过滤器就是过滤掉不要东西,取所要的。如可以用过滤器解决中文乱码问题。

    监听器,是一个事物处理过程,常用来做初始化内容的添加等动作

    拦截器就是对不要的东西进行拦截,struts2中经常用到

1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。

2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器。

3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。

4、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。

5、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。

 

10 拦截器的工作原理?如何自定义一个拦截器?

 答: 如何理解struts2的拦截器

 1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并 且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.

2. 拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

   原理:Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器

自定义拦截器的步骤:

 1. 定义自己的拦截器。即一个实现了Intercept接口的类。该类覆盖了intercept()方法;在intercept方法里面写代码实现过滤。

 2 在struts.xml中申明该拦截器

 3 把它引入到相应的Action中

 

11 Hibernate的作用,工作原理。

答:作用:

hibernate,通过对jdbc进行封装,对 java类和 关系数据库进行mapping,实现了对关系数据库的面向对象方式的操作,改变了传统的jdbc + sql操作数据的方式,从而使开发人员可以花更多精力进行对象方面的开发
好处呢,并不只是简化了数据库操作,更有价值的是对不同的数据库提供了统一操作的接口,使应用程序的跨数据库开发成为可能

工作原理:

1.读取并解析配置文件。
2.读取并解析映射信息,创建SessionFactory
3.打开Session
4.创建事物Transaction
5.持久化操作
6.提交事务
7.关闭Session
8.关闭SessionFactory
核心接口:

Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。

 

12 什么是hibernate的并发机制?怎样去处理并发问题。

 Hibernate并发机制:

   a、Hibernate的Session对象是非线程安全的,对于单个请求,单个会话,单个的工作单元(即单个事务,单个线程),它通常只使用一次,

      然后就丢弃。

      如果一个Session 实例允许共享的话,那些支持并发运行的,例如Http request,session beans将会导致出现资源争用。

      如果在Http Session中有hibernate的Session的话,就可能会出现同步访问Http Session。只要用户足够快的点击浏览器的“刷新”,

      就会导致两个并发运行的线程使用同一个Session。

   b、多个事务并发访问同一块资源,可能会引发第一类丢失更新,脏读,幻读,不可重复读,第二类丢失更新一系列的问题。

 

   解决方案:设置事务隔离级别。

              Serializable:串行化。隔离级别最高

             Repeatable Read:可重复读

             Read Committed:已提交数据读

             Read Uncommitted:未提交数据读。隔离级别最差        

             设置锁:乐观锁和悲观锁。

             乐观锁:使用版本号或时间戳来检测更新丢失,在<class>的映射中设置 optimistic-lock="all"可以在没有版本或者时间戳属性映射的情况下实现 版本检查,此时Hibernate将比较一行记录的每个字段的状态 行级悲观锁:Hibernate总是使用数据库的锁定机制,从不在内存中锁定对象!只要为JDBC连接指定一下隔 离级别,然后让数据库去搞定一切就够了。类LockMode 定义了Hibernate所需的不同的锁定级别:LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ;

 

13 hibernate与jdbc的联系。

 答:hibernate是jdbc的轻量级封装,包括jdbc的与数据库的连接(用hibernate.property的配置文件实现     当然本质是封装了jdbc的forname),和查询,删除等代码,都用面向对象的思想用代码联系起来,hibernate通过hbm 配置文件把entity类或者说叫dto类的字段和数据库的字段关联起来比如数据库的id,

    在po类中就是pravite Long id; public Long getId() ;public setId(Long id);

    然后hql语句也是面向对象的,它的查询语句不是查询数据库而是查询类的,这些实现的魔法就是xml文件,其实hibernate=封装的jdbc+xml文件

 

14 hibernate与Spring的联系。

答:hibernate中的一些对象可以给Spring来管理,让Spring容器来创建hibernate中一些对象实例化。例如:SessionFactory,HibernateTemplate等。

    Hibernate本来是对数据库的一些操作,放在DAO层,而Spring给业务层的方法定义了事务,业务层调用DAO层的方法,很好的将Hibernate的操作也加入到事务中来了。

 

15  Hibernate自带的分页机制是什么?如果不使用Hibernate自带的分页,则采用什么方式分页?

答:1、hibernate自带的分页机制:获得Session对象后,从Session中获得Query对象。用Query.setFirstResult():设置要显示的第一行数据,

       Query.setMaxResults():设置要显示的最后一行数据。

    2、不使用hibernate自带的分页,可采用sql语句分页,

       如:5:为每页显示的记录,2为当前页: select * top 5 from table where tabId not in (select tabId top (2-1)*5 from table);

 

16  Hibernate的三种状态,三种状态之间是如何装换的?

答:当对象由瞬时状态(Transient)一save()时,就变成了持久化状态。

    当我们在Session里存储对象的时候,实际是在Session的Map里存了一份,

    也就是它的缓存里放了一份,然后,又到数据库里存了一份,在缓存里这一份叫持久对象(Persistent)。

    Session 一 Close()了,它的缓存也都关闭了,整个Session也就失效了,

    这个时候,这个对象变成了游离状态(Detached),但数据库中还是存在的。

    当游离状态(Detached)update()时,又变为了持久状态(Persistent)。

    当持久状态(Persistent)delete()时,又变为了瞬时状态(Transient),

    此时,数据库中没有与之对应的记录。

 

17  Hibernate的核心接口?

答:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

  Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。这5个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。下面对这五个核心接口分别加以介绍。

  ·Session接口:Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句。)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSesion对象称为用户session。

  ·SessionFactory接口:SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。

  ·Configuration接口:Configuration接口负责配置并启动Hibernate,创建SessionFactory对象。在Hibernate的启动的过程中,Configuration类的实例首先定位映射文档位置、读取配置,然后创建SessionFactory对象。

  ·Transaction接口:Transaction接口负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。

  ·Query和Criteria接口:Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式。

 

18  Hibernate的主键生成策略?

答:有8种:

   Assigned

  Assigned方式由程序生成主键值,并且要在save()之前指定否则会抛出异常

  特点:主键的生成值完全由用户决定,与底层数据库无关。用户需要维护主键值,在调用session.save()之前要指定主键值。

  Hilo

  Hilo使用高低位算法生成主键,高低位算法使用一个高位值和一个低位值,然后把算法得到的两个值拼接起来作为数据库中的唯一主键。Hilo方式需要额外的数据库表和字段提供高位值来源。默认请况下使用的表是

  hibernate_unique_key,默认字段叫作next_hi。next_hi必须有一条记录否则会出现错误。

  特点:需要额外的数据库表的支持,能保证同一个数据库中主键的唯一性,但不能保证多个数据库之间主键的唯一性。Hilo主键生成方式由Hibernate 维护,所以Hilo方式与底层数据库无关,但不应该手动修改hi/lo算法使用的表的值,否则会引起主键重复的异常。

  Increment

  Increment方式对主键值采取自动增长的方式生成新的主键值,但要求底层数据库的支持Sequence。如Oracle,DB2等。需要在映射文件xxx.hbm.xml中加入Increment标志符的设置。

  特点:由Hibernate本身维护,适用于所有的数据库,不适合多进程并发更新数据库,适合单一进程访问数据库。不能用于群集环境。

  Identity

  Identity当时根据底层数据库,来支持自动增长,不同的数据库用不同的主键增长方式。

  特点:与底层数据库有关,要求数据库支持Identity,如MySQl中是auto_increment, SQL Server 中是Identity,支持的数据库有MySql、SQL Server、DB2、Sybase和HypersonicSQL。 Identity无需Hibernate和用户的干涉,使用较为方便,但不便于在不同的数据库之间移植程序。

  Sequence

  Sequence需要底层数据库支持Sequence方式,例如Oracle数据库等

  特点:需要底层数据库的支持序列,支持序列的数据库有DB2、PostgreSql、Qracle、SAPDb等在不同数据库之间移植程序,特别从支持序列的数据库移植到不支持序列的数据库需要修改配置文件

  Native

  Native主键生成方式会根据不同的底层数据库自动选择Identity、Sequence、Hilo主键生成方式

  特点:根据不同的底层数据库采用不同的主键生成方式。由于Hibernate会根据底层数据库采用不同的映射方式,因此便于程序移植,项目中如果用到多个数据库时,可以使用这种方式。

  UUID

  UUID使用128位UUID算法生成主键,能够保证网络环境下的主键唯一性,也就能够保证在不同数据库及不同服务器下主键的唯一性。

  特点;能够保证数据库中的主键唯一性,生成的主键占用比较多的存贮空间

  Foreign GUID

  Foreign用于一对一关系中。GUID主键生成方式使用了一种特殊算法,保证生成主键的唯一性,支持SQL Server和MySQL

18  简述Hibernate的缓存管理机制?

答:

Hibernate的缓存机制概念:

java对象的属性(通常是一些集合类型的属性 )占用的内存空间。如果对象的占用的内存很大就称为重量级的对象。如果对象的内存小就称为轻量级的对象。

Session 的缓存被称为hibernate的第一级缓存。

SessionFactory的外置缓存称为hibernate 的二级缓存。

这两个缓存都位于持久层,它们存放的都是数据库数据的拷贝。SessionFactory的内置缓存存放元数据和预定义SQL,  SessionFactory的内置缓存是只读缓存。

Session 缓存的三大作用:

1,减少数据库的访问频率,提高访问性能。

2,保证缓存中的对象与数据库同步,位于缓存中的对象称为持久化对象。

3,当持久化对象之间存在关联时,Session 保证不出现对象图的死锁。

 Session 如何判断持久化对象的状态的改变呢?

  Session 加载对象后会为对象值类型的属性复制一份快照。当Session 清理缓存时,比较当前对象和它的快照就可以知道那些属性发生了变化。

Session 什么时候清理缓存?

1,commit() 方法被调用时

2,查询时会清理缓存,保证查询结果能反映对象的最新状态。

3,显示的调用session 的 flush方法。

session 清理缓存的特例:

当对象使用 native 生成器 时 会立刻清理缓存向数据库中插入记录。

 

 

19 spring有哪些作用?核心是什么?

答:
在SSH框假中spring充当了管理容器的角色。我们都知道Hibernate用来做持久层,因为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不用书写大量的SQL语句。Struts是用来做应用层的,他它负责调用业务逻辑serivce层。所以SSH框架的流程大致是:Jsp页面----Struts------Service(业务逻辑处理类)---Hibernate(左到右)
  struts负责控制Service(业务逻辑处理类),从而控制了Service的生命周期,这样层与层之间的依赖和强,属于耦合。这时,使用spring框架就起到了控制Action对象(Strus中的)和Service类的作用,两者之间的关系就松散了,Spring的Ioc机制(控制反转和依赖注入)正是用在此处。
  Spring的Ioc(控制反转和依赖注入)
  控制反转:就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控 
  依赖注入:组件之间的依赖关系由容器在运行期决定 ,由容器动态的将某种依赖关系注入到组件之中。
  从上面我们不难看出:从头到尾Action仅仅是充当了Service的控制工具,这些具体的业务方法是怎样实现的,他根本就不会管,也不会问,他只要知道这些业务实现类所提供的方法接口就可以了。而在以往单独使用Struts框架的时候,所有的业务方法类的生命周期,甚至是一些业务流程都是由Action来控制的。层与层之间耦合性太紧密了,既降低了数据访问的效率又使业务逻辑看起来很复杂,代码量也很多。,Spring容器控制所有Action对象和业务逻辑类的生命周期,由与上层不再控制下层的生命周期,层与层之间实现了完全脱耦,使程序运行起来效率更高,维护起来也方便。
  使用Spring的第二个好处(AOP应用):
  事务的处理:
  在以往的JDBCTemplate中事务提交成功,异常处理都是通过Try/Catch 来完成,而在Spring中。Spring容器集成了TransactionTemplate,她封装了所有对事务处理的功能,包括异常时事务回滚,操作成功时数据提交等复杂业务功能。这都是由Spring容器来管理,大大减少了程序员的代码量,也对事务有了很好的管理控制。Hibernate中也有对事务的管理,hibernate中事务管理是通过SessionFactory创建和维护Session来完成。而Spring对SessionFactory配置也进行了整合,不需要在通过hibernate.cfg.xml来对SessionaFactory进行设定。这样的话就可以很好的利用Sping对事务管理强大功能。避免了每次对数据操作都要现获得Session实例来启动事务/提交/回滚事务还有繁琐的Try/Catch操作。这些也就是Spring中的AOP(面向切面编程)机制很好的应用。一方面使开发业务逻辑更清晰、专业分工更加容易进行。另一方面就是应用Spirng AOP隔离降低了程序的耦合性使我们可以在不同的应用中将各个切面结合起来使用大大提高了代码重用度

Spring工作原理
        Spring 已经用过一段时间了,感觉Spring是个很不错的框架。内部最核心的就是IOC了,
动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射
反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml  Spring的配置
文件来动态的创建对象,和调用对象里的方法的 。
     Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就
在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通
配置类达到的。
   Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说
管理的(Spring根据这些配置 内部通过反射去动态的组装对象)
   要记住:Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。
Spring里用的最经典的一个设计模式就是:模板方法模式。

 

20 你一般用spring做什么?

答:IOC和AOP

 

21 根据你的理解谈谈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中的各种模块提供了基础支持。

 

22 Spring的依赖注入方式有哪几种?

23 项目中如何体现Spring的切面编程的?

答:面向切面编程:主要是横切一个关注点,将一个关注点模块化成一个切面。在切面上声明一个通知(Advice)和切入点(Pointcut); 通知: 是指在切面的某个特定的连接点(代表一个方法的执行。通过声明一个org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。)上执行的动作。通知中定义了要插入的方法。切入点:切入点的内容是一个表达式,以描述需要在哪些对象的哪些方法上插入通知中定义的方法。

   项目中用到的Spring中的切面编程最多的地方:声明式事务管理。

   a、定义一个事务管理器

   b、配置事务特性(相当于声明通知。一般在业务层的类的一些方法上定义事务)

   c、配置哪些类的哪些方法需要配置事务(相当于切入点。一般是业务类的方法上)

 

14 说说spring的事物处理机制?(Transaction(事务处理)有哪几种实现?)

15 什么是AJAX,说一说AJAX的工作原理?

答:Ajax(Asynchronous JavaScript and XML,异步JavaScript和XML)。

16  什么是Jquery?

答:Javascrīpt框架

 

posted on 2013-08-07 17:18  wings27  阅读(646)  评论(0编辑  收藏  举报

导航