HRSystem总结

来源:互联网 发布:单片机采样大电流电路 编辑:程序博客网 时间:2024/05/23 14:37

1.pojo类   

2.hbm映射

3.dao接口

4.dao实现类

5.daoContext

6.数据库表

7.service 接口

8.service 业务逻辑组件

9.vo 封装

10.applicationContext.xml

11.action类

12.拦截器

13.jsp页面

14.struts.xml

****************************************************


1.   hashcode()是干什么用的?
2.   如果我实现了comparable接口,重写了equals(),为什么还要重写hashCode()呢?默认的equals()是比的hashCode吗?hashCode是基于内存地址计算出来的,可是一个类的两个实例是放在堆区不同的地址空间的,为什么计算出的hash码还是一样的呢?

1.hashcode是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有
例如内存中有这样的位置
0     1     2     3     4     5     6     7    
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。
但如果用hashcode那就会使效率提高很多。
我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除8求余数直接找到存放的位置了。

2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义   equals了。
也就是说,我们先通过   hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过   equals   来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊

1.hashCode()方法使用来提高Map里面的搜索效率的,Map会根据不同的hashCode()来放在不同的桶里面,Map在搜索一个对象的时候先通过hashCode()找到相应的桶,然后再根据equals()方法找到相应的对象.要正确的实现Map里面查找元素必须满足一下两个条件:
(1)当obj1.equals(obj2)为true时obj1.hashCode()   ==   obj2.hashCode()必须为true
(2)当obj1.hashCode()   !=   obj2.hashCode()为true时obj.equals(obj2)必须为true


任何class如果覆写了equals()方法,就必须覆写hashCode()。
这样作的目的就是为了你的类就能够很好的与java的集合框架协同工作。如果我们能够确认我们定义的类不会和java集合类产生关系,那么我们完全没有必要在覆写equals()方法的时候覆写hashCode。

针对HashSet:

Set不允许重复
允许 null,重复的null只算一个
判断是否存在一个数据(是否重复),先判断其hashCode是否存在,若存在再逐个判断hashCode相同的数据是否相等
判断是否相等,除了hashCode相等外,还要判断对象引用相等(==),或者 equals
如果一个对象的hashCode变动了,会造成找不到这个对象,也就出现了内存泄漏的危险。

---------------------------------------------------------------------------------------------------------------------------------------------

我想知道Hibernate 中lazy的作用?写不写有区别么?什么时候要写?
延迟加载

比如查询一张表时,有外键对应另一张表
可以使用延迟加载
这样就不会把外键对应表的数据加载
----------------------------------------------------------------------------------------------------------------------------------------------
三 
inverse=true的含义: 由双向关联另一方维护该关联,己方不维护该关联(只能进行查询操作)。
-----------------------------------------------------------------------------------------------------------------------------------------------
最近在负责一个大项目,项目组成员包括项目经理大概10个人左右。项目技术用struts+spring+hibernate实现。项目的规模相对来说是比较大的,总共有10大模块,每个大模块又分为有十几个、甚至几十个小模块。开发工具用eclipse,由于在开发阶段,项目开发成员需要频繁重启服务器。在启动服务器的时候,每次启动时间总是会超过1分钟。记得以前在做另外一个项目时,启动时间不到5秒钟,相差了10倍,而且项目规模是差不多的。

    从初步分析来说,应该是hibernate解释hbm.xml时花费时间,或者可能是spring容器启动并解释所有的bean配置文件。诊断了一下,发现1分钟消耗的时间主要分布在hibernate解释hbm.xml花费5秒;spring容器从启动到解释bean配置文件竟然花了58秒,真是太嚣张了。当时非常怀疑spring的效率问题。企图从网上搜索相关资料,看看有什么优化措施。

    首先是找到了hibernate的启动优化 http://www.hibernate.org/194.html  里面的主要思想是通过将xml序列花到本地的文件里,每次读取的时候根据情况,从本地文件读取并反序列化,节省了hibernate xml的解析时间。按照这个方式测试了一下,发现hibernate的启动时间从5秒降低到3秒,但是这个优化对于整个启动过程是杯水车薪的,毫无用处。

    没办法,又仔细查看了spring的资料,终于发现spring的容器是提供了lazy-load的,即默认的缺省设置是bean没有lazy- load,该属性处于false状态,这样导致spring在启动过程导致在启动时候,会默认加载整个对象实例图,从初始化ACTION配置、到 service配置到dao配置、乃至到数据库连接、事务等等。这么庞大的规模,难怪spring的启动时间要花将近1分钟。尝试了一下,把beans的 default-lazy-init改为true就,再次启动,速度从原来的55秒,降到8秒钟!!Great!虽然是非常小一个改动,但是影响确实非常大。一个项目组10个人,假若每个人一天平均需要在eclipse下启动测试服务器50次。那么一天项目组需要重启500次,每次节省50秒的话,就是 25000秒,将近几个小时,差不多一个工作日,多么可观的数字!

   不过在运行期间第一次点页面的时候,由于spring做了lazy-load,现在就需要启动一部分需要的beans,所以稍微慢2-3秒钟,但是明显比等几十秒要快很多,值得一鉴。

    以上是针对开发阶段的spring容器启动优化,在部署到实际环境中,倒是没必要设置为lazy-load。毕竟部署到实际环境中不是经常的事,每次启动1分钟倒不是大问题。
-------------------------------------------------------------------------------------------------------------------------------------------

String dutyDay = new java.sql.Date(
   System.currentTimeMillis()).toString();

System.currentTimeMillis():currentTimeMillis
public static long currentTimeMillis()返回以毫秒为单位的当前时间。注意,当返回值的时间单位是毫秒时,值的粒度取决于底层操作系统,并且粒度可能更大。例如,许多操作系统以几十毫秒为单位测量时间。 返回:
当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量)。

java.sql.Date.toString:把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。
---------------------------------------------------------------------------------------------------------------------------------
4.只读
该标志可以设定为true,表明该事物不修改任何持久性状态。更多的情况下,这只是个提示,因为不是所有的事务性资源都可以利用这个设定。
在使用Hibernate的时候,它尤为有用,因为它告知Hibernate不要在只读事务中检测和刷新变化


不要搞清AOP的事务管理模式,就一定要搞清AOP的概念先。
SPRING中的事务管理一般这样实现:
1、定义事务管理器(死的)
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
2、定义advice(决策),主要是定义当调用什么方法时,用什么事务模式
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" />
<tx:method name="statistic" read-only="true" />
<tx:method name="is*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="select*" read-only="true" />
<tx:method name="get*AndUpdate*" />
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
上面的例子代码是定义在某些方法时,事务是read-only的,比如get*(以get开头的方法名),还有些事务是write的,比如 get*AndUpdate*,表示匹配get开头,中间有AndUpdate的方法都是写事务。最后的*最后起作用,因此就是上面未定义的方法名匹配都是写事务。

3、规划需要管理事务的类和方法,最好把它们放都到同一个包里面,这样定义起来方便一些。
4、定义切入点,即什么类会被切入而进入advice:
<aop:config>
<aop:pointcut id="xxxxTxPointcut"
expression="execution(* com.xxx.yyy.service.**.*(..))" />
<aop:advisor advice-ref="txAdvice"
pointcut-ref="xxxxTxPointcut" order="1" />
</aop:config>
上面的例子是定义com.xxx.yyy.service包内的及其子包的类会被切入。

这样,如果你有一个类:com.xxx.yyy.service.UserService,里面有一个方法 newUser();
按照上面的设置,当你调用UserService.newUser方法时,SPRING的事务管理器就启动一个事务,当整个方法执行完成,并且未出现异常,那么事务管理器自动提交。如果调用中出现异常,事务管理器就rollback

假设newUser你修改了2个表,比如用户ID表和用户信息表,只有当2个表的操作均未出异常,事务管理器才会提交。
-------------------------------------------------------------------------------------------------------------------------------
struts2 OGNL,struts2 表达式语言,Struts2 中OGNL表达式的用法,Struts2 #,表达式语言的好处,Struts2 $,struts2 井号,星号,百分号


表达式语言主要有以下几大好处:  
  
   1. 避免(MyType) request.getAttribute()和myBean.getMyProperty()之类的语句,使页面更简洁;  
   2. 支持运算符(如+-*/),比普通的标志具有更高的自由度和更强的功能;  
   3. 简单明了地表达代码逻辑,使用代码更可读与便于维护。


Struts2 中OGNL表达式的用法:

OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;

“#”主要有三种用途:  
  
   1. 访问OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:  
       名称   作用 例子  
      parameters    包含当前HTTP请求参数的Map    #parameters.id[0]作用相当于request.getParameter("id")  
      request   包含当前HttpServletRequest的属性(attribute)的Map    #request.userName相当于request.getAttribute("userName")  
      session   包含当前HttpSession的属性(attribute)的Map   #session.userName相当于session.getAttribute("userName")  
      application   包含当前应用的ServletContext的属性(attribute)的Map     #application.userName相当于application.getAttribute("userName")  
      attr 用于按request > session > application顺序访问其属性(attribute)    #attr.userName相当于按顺序在以上三个范围(scope)内读取userName属性,直到找到为止  
   2. 用于过滤和投影(projecting)集合,如books.{?#this.price<100};  
   3. 构造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。  


“%”的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。例如在Ognl.jsp中加入以下代码:  
<hr />  
    <h3>%的用途</h3>  
    <p><s:url value="#foobar['foo1']" /></p>  
    <p><s:url value="%{#foobar['foo1']}" /></p>  


“$”有两个主要的用途 :   
   1. 用于在国际化资源文件中,引用OGNL表达式,例子请参考《在Struts 2.0中国际化(i18n)您的应用程序》  
   2. 在Struts 2配置文件中,引用OGNL表达式,如  
      <action name="AddPhoto" class="addPhoto">  
                  <interceptor-ref name="fileUploadStack" />              
                  <result type="redirect">ListPhotos.action?albumId=${albumId}</result>  
              </action>
--------------------------------------------------------------------------------------------------------------------------------
如何自定义一个拦截器?

自定义一个拦截器需要三步:

1 自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。

2 在strutx.xml中注册上一步中定义的拦截器。

3 在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明
的情况下所有的Action都被这个拦截器拦截。

 

Interceptor接口声明了三个方法:

 

public interface Interceptor extends Serializable {

 

    void destroy();

 

    void init();

 

    String intercept(ActionInvocation invocation) throws Exception;

}

 

Init方法在拦截器类被创建之后,在对Action镜像拦截之前调用,相当于一个post-constructor方法,
使用这个方法可以给拦截器类做必要的初始话操作。

 

Destroy方法在拦截器被垃圾回收之前调用,用来回收init方法初始化的资源。

 

Intercept是拦截器的主要拦截方法,如果需要调用后续的Action或者拦截器,只需要在该方法中调用
invocation.invoke()方法即可,在该方法调用的前后可以插入Action调用前后拦截器需要做的方法。
如果不需要调用后续的方法,则返回一个String类型的对象即可,例如Action.SUCCESS。

另外AbstractInterceptor提供了一个简单的Interceptor的实现,这个实现为:

public abstract class AbstractInterceptor implements Interceptor {

 

     public void init() {

    }

   

    public void destroy() {

    }

 

 

    public abstract String intercept(ActionInvocation invocation) throws Exception;

}

在不需要编写init和destroy方法的时候,只需要从AbstractInterceptor继承而来,实现intercept方法即可。

 

我们尝试编写一个Session过滤用的拦截器,该拦截器查看用户Session中是否存在特定的属性(LOGIN属性)
如果不存在,中止后续操作定位到LOGIN,否则执行原定操作,代码为:

public class CheckLoginInterceptor extends AbstractInterceptor {

    public static final String LOGIN_KEY = "LOGIN";

    public static final String LOGIN_PAGE = "global.login";

 

    public String intercept(ActionInvocation actionInvocation) throws Exception {

 

        System.out.println("begin check login interceptor!");

        // 对LoginAction不做该项拦截

        Object action = actionInvocation.getAction();

        if (action instanceof LoginAction) {

            System.out.println("exit check login, because this is login action.");

            return actionInvocation.invoke();

        }

 

        // 确认Session中是否存在LOGIN

        Map session = actionInvocation.getInvocationContext().getSession();

        String login = (String) session.get(LOGIN_KEY);

        if (login != null && login.length() > 0) {

            // 存在的情况下进行后续操作。

            System.out.println("already login!");

            return actionInvocation.invoke();

        } else {

            // 否则终止后续操作,返回LOGIN

            System.out.println("no login, forward login page!");

            return LOGIN_PAGE;

        }

    }

}

 

注册拦截器

<interceptors>

            <interceptor

name="login" 

class="com.jpleasure.teamware.util.CheckLoginInterceptor"/>

            <interceptor-stack name="teamwareStack">

                <interceptor-ref name="login"/>

                <interceptor-ref name="defaultStack"/>

            </interceptor-stack>

</interceptors>

 

将上述拦截器设定为默认拦截器:

<default-interceptor-ref name="teamwareStack"/>

这样在后续同一个package内部的所有Action执行之前都会被login拦截。
------------------------------------------------------------------------------------------------------------
索引的用法
如果指定了status,每次的迭代数据都有IteratorStatus的实例,它有以下几个方法
int getCount()返回当前迭代了几个元素
int getIndex()返回当前元素索引
boolean isEven()当然的索引是否偶数
boolean isFirst()当前是否第一个元素
boolean isLast()
boolean isOdd()当前元素索引是否奇数

<s:iterator value="{'a','b','c'}" id='char' status='st'>
    <s:if test="#st.Even">
        现在的索引是奇数为:<s:property value='#st.index'/>
    </s:if>
    当前元素值:<s:property value='char'/>
</s:iterator>
-------------------------------------------------------------------------------------------------------------
<interceptor-ref name="basicStack"/>
拦截器栈
<interceptor-stack name="basicStack">
   <interceptor-ref name="exception"/>
  <interceptor-ref name="servlet-config"/>
   <interceptor-ref name="prepare"/>
    <interceptor-ref name="checkbox"/>
    <interceptor-ref name="params"/>
    <interceptor-ref name="conversionError"/>
</interceptor-stack>
---------------------------------------------------------------------------------------------------------------
任务调度
 <!-- 定义触发器来管理任务Bean --> 
  <bean id="cronTriggerPay"class="org.springframework.scheduling.quartz.CronTriggerBean">
//jobDetail指定  
<property name="jobDetail">
  <!-- 使用嵌套Bean的方式来定义任务Bean -->
  <bean class="org.springframework.scheduling.quartz.JobDetailBean">
  <!-- 指定任务Bean的实现类 -->
                                  //jobClass指定
  <property name="jobClass"
  value="org.qjkt.hrsystem.schedule.PayJob"/>
  <!-- 为任务Bean注入属性 -->
                                                //jobDataAsMap指定
   <property name="jobDataAsMap">
    <map>
     <entry key="empMgr" value-ref="empManager"/>
    </map>
   </property>
  </bean>
 </property>
 <!-- 指定Cron表达式:每月3日2时启动 -->
                 // //cronExpression指定
 <property name="ceonExpression" value="0 0 2 3 * ? *"/>
 </bean>
 
 <!-- 定义触发器来管理任务Bean -->
<bean id="cronTriggerPunch"
 class="org.springframework.scheduling.quartz.CronTriggerBean">
//jobDetail指定 
<property name="jobDetail">
  <!-- 使用嵌套Bean的方式来定义任务Bean -->
  <bean
  class="org.springframework.scheduling.quartz.JobDetailBean">
   <!-- 指定任务Bean的实现类 -->
                                                  //jobClass指定
   <property name="jobClass"
    value="org.qjkt.hrsystem.schedule.PunchJob"/>
   <!-- 为任务Bean注入属性 -->
                                             //jobDataAsMap指定
   <property name="jobDataAsMap">
    <map>
     <entry key="empMgr" value-ref="empManager"/>
    </map>
   </property>
  </bean>
 </property>
 <!-- 指定Cron表达式:周一到周五7点、12点执行调度 -->
                 //cronExpression指定
 <property name="cronExpression"
  value="0 0 7,12 ? * MON-FRI"/>
</bean>
<bean
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
//triggers指定
<property name="triggers">
<list>
    <ref local="cronTriggerPay"/>
    <ref local="cronTriggerPunch"/>
    </list>
    </property>
    </bean>
--------------------------------------------------------------------------------------------------------------------
Message Store Interceptor
一个拦截器存储ValidationAware Action的消息/错误和字段错误到Http Session,这样它将被重新获取在最后阶段.这允许Action的消息/错误和字段错误长期有效在特定的http请求.
在’STORE’模式中,拦截器将重新获取存储的Action 消息/错误和字段错误并且放他们到ValidationAware Action.
拦截器在’NONE’模式中什么也不做,其中一个是默认的.
操作模式可以被交换使用:
1]设置拦截器参数例子.
     <action name="submitApplication" ...>
        <interceptor-ref name="store">
           <param name="operationMode">STORE</param>
        </interceptor-ref>
        <interceptor-ref name="defaultStack" />
        ....
     </action>
2]通过请求参数(allowRequestParameterSwitch 必需为’true’,是默认的)
// the request will have the operation mode in 'STORE'
http://localhost:8080/context/submitApplication.action?operationMode=STORE
参数
. allowRequestParameterSwitch-开启请求参数可以交换拦截器的操作模式.
. requestParameterSwitch-指示拦截器中使用什么样的请求参数.
.operationMode-这个拦截器使用的操作模式(‘STORE’,’RETRIEVE’或’NONE’其中一个).’NONE’为默认.
扩展拦截器
下面的方法将被覆盖:
. getRequestOperationMode-获取拦截器的操作模式基于请求参数.
.mergeCollection-合并两个集合.
.mergeMap – 合并两个map
例子
<action name="submitApplication" ....>
      <interceptor-ref name="store">
        <param name="operationMode">STORE</param>
      </interceptor-ref>
      <interceptor-ref name="defaultStack" />
      <result name="input" type="redirect">applicationFailed.action</result>
      <result type="dispatcher">applicationSuccess.jsp</result>
</action>
<action name="applicationFailed" ....>
      <interceptor-ref name="store">
         <param name="operationMode">RETRIEVE</param>
      </interceptor-ref>
      <result>applicationFailed.jsp</result>
</action>

同上面的例子, 'submitApplication.action'有Action消息/错误/字段错误存储到Http会话中.以后需要的时候,在这种情况下,’applicationFailed.action’被激活,它将获取Action 消息/错误/字段错误存储在HTTP会话中并且放回到Action.
______________________________________________________________________________________________________________________________________________________________________________________________
与Servlet API耦合的访问方式

直接访问Servlet API将使你的Action与Servlet环境耦合在一起,我们知道对于HttpServletRequest、HttpServletResponse和ServletContext这些对象,它们都是由Servlet容器来构造的,与这些对象绑定在一起,测试时就需要有Servlet容器,不便于Action的单元测试。但有时候,我们又确实需要直接访问这些对象,那么当然是以完成任务需求为主。

要直接获取HttpServletRequest和ServletContext对象,可以使用org.apache.struts2. ServletActionContext类,该类是ActionContext的子类,在这个类中定义下面两个静态方法:


 public static HttpServletRequest getRequest()
 
得到HttpServletRequest对象。
public static ServletContext getServletContext()

得到ServletContext对象。

此外,ServletActionContext类还给出了获取HttpServletResponse对象的方法,如下:

public static HttpServletResponse getResponse()

ServletActionContext类并没有给出直接得到HttpSession对象的方法,HttpSession对象可以通过HttpServletRequest对象来得到。

除了上述的方法调用得到HttpServletRequest和ServletContext对象外,还可以调用ActionContext对象的get()方法,传递ServletActionContext.HTTP_REQUEST和ServletActionContext.SERVLET_CONTEXT键值来得到HttpServletRequest和ServletContext对象,如下所示:

ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
 
得到与ServletActionContext.HTTP_REQUEST键值绑定的HttpServletRequest对象。
ActionContext.getContext().get(ServletActionContext.SERVLET_CONTEXT);

得到与ServletActionContext.SERVLET_CONTEXT键值绑定的ServletContext对象。

同样的,也可以向ActionContext的get()方法传递ServletActionContext.HTTP_ RESPONSE键值来得到HttpServletResponse对象,如下:

 ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE);

建议读者采用第一种方式来获取HttpServletRequest和ServletContext对象,这样简单而又清晰。

我们看例3-14。

例3-14  通过ServletActionContext来获取HttpServletRequest和ServletContext对象的LoginAction3

package org.sunxin.struts2.ch03.action.way2;import javax.servlet.ServletContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import org.sunxin.struts2.ch03.model.User;


import com.opensymphony.xwork2.Action;

public class LoginAction3 implements Action
{
...


@Override
public String execute() throws Exception
{
if("zhangsan".equals(user.getUsername())
&& "1234".equals(user.getPassword()))
{
HttpServletRequest request = ServletActionContext.getRequest();      
HttpSession session = request.getSession();
ServletContext context = ServletActionContext.getServletContext();

/*ActionContext ctx = ActionContext.getContext();
HttpServletRequest request = (HttpServletRequest)ctx.get(Servlet ActionContext.HTTP_REQUEST);       
HttpSession session = request.getSession();
ServletContext context = (ServletContext)ctx.get(ServletAction Context.SERVLET_CONTEXT);*/

//在请求中放置欢迎信息。
request.setAttribute("greeting", "欢迎您来到程序员之家");

//在session中保存user对象
session.setAttribute("user", user);

//统计用户访问量,在application中保存用户访问量数据
Integer count = (Integer)context.getAttribute("counter");
if(null == count)
count=1;
else
count++;
context.setAttribute("counter", count);

return SUCCESS;
}
else
{
return ERROR;
}
}
}
 
完整的代码请参看本书配套光盘中的ch03_4目录,测试时,输入URL:
 http://localhost:8080/ch03_4/login3.jsp

除了利用ServletActionContext来获取HttpServletRequest对象和ServletContext对象这种方式外,Action类还可以实现ServletRequestAware和ServletContextAware接口,由Struts 2框架向Action实例注入HttpServletRequest和ServletContext对象。

org.apache.struts2.interceptor.ServletRequestAware接口只有一个方法,如下所示:

void setServletRequest(HttpServletRequest request)
org.apache.struts2.util.ServletContextAware接口也只有一个方法,如下所示:
void setServletContext(ServletContext context)
 

ServletRequestAware接口和ServletContextAware接口不属于同一个包,前者在org.apache.struts2.interceptor包中,后者在org.apache.struts2.util包中,这很让人迷惑。

我们看例3-15。

例3-15  通过接口注入来获取HttpServletRequest和ServletContext对象的LoginAction4

 package org.sunxin.struts2.ch03.action.way2;import javax.servlet.ServletContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.util.ServletContextAware;
import org.sunxin.struts2.ch03.model.User;


import com.opensymphony.xwork2.Action;

public class LoginAction4 implements Action, ServletRequestAware, ServletContextAware
{
private HttpServletRequest request;
private ServletContext context;


@Override
public String execute() throws Exception
{
if ("zhangsan".equals(user.getUsername())
&& "1234".equals(user.getPassword()))
{
HttpSession session = request.getSession();

//在请求中放置欢迎信息。
request.setAttribute("greeting", "欢迎您来到程序员之家");


//在session中保存user对象
session.setAttribute("user", user);


//统计用户访问量,在application中保存用户访问量数据
Integer count = (Integer) context.getAttribute("counter");
if (null == count)
count = 1;
else
count++;
context.setAttribute("counter", count);


return SUCCESS;
}
else
{
return ERROR;
}
}


@Override
public void setServletRequest(HttpServletRequest request)
{
this.request = request;
}


@Override
public void setServletContext(ServletContext context)
{
this.context = context;
}
}
 
LoginAction4类实现了ServletRequestAware和ServletContextAware接口,框架在运行时会调用这两个接口中的方法,向LoginAction4注入HttpServletRequest和ServletContext对象。在execute()方法中不再需要访问ServletActionContext,因此我们删除了与之相关的代码。
完整的代码请参看本书配套光盘中的ch03_4目录,测试时,输入URL:
http://localhost:8080/ch03_4/login4.jsp
-----------------------------------------------------------------------------------------------------------------------------------------
太奇怪了

主页面login.jsp  调用页面header.jsp

<%@ page contentType="text/html; charset=gb2312"%>
<%@ include file="header.jsp"%>

login.jsp的必须要与header.jsp看齐!!!!  header.jsp向login.jsp看齐则不行!


------------------------------------------------------------------------------

return (List<Employee>)getHibernateTemplate().find("from Employee as b where "+
    "b.manager=?",mgr);

第一种对   第二种错
return (List<Employee>)getHibernateTemplate().find("from Employee as b where"+
    "b.manager=?",mgr);