07_企业框架

Model(javabean技术)-View(jsp技术)-Control(servlet技术)

entity-dao(Hibernate/MyBatis)-service(Spring)-web(Struts2/SpringMVC)

SSH(Hibernate+Spring+Struts2)-SSM(MyBatis+Spring+SpringMVC)

Hibernate

EJB:EJB3.0

实体bean:Entity Bean;实现O/R映射

会话bean:Session Bean;实现业务逻辑

消息驱动bean:MessageDriven Bean;只能接收客户端发送的JMS消息然后处理

点对点: 中间件(用户a->服务器->用户b)

pub/sub:发布/订阅模型

扫描二维码关注公众号,回复: 2439865 查看本文章

ORM(对象-关系映射):Object Relational Mapping,

对象三种状态:自由状态/瞬时状态 持久状态 脱管状态/游离状态

持久化:将程序中数据在瞬时状态和持久状态键转换的机制

持久化层:DAO层(数据访问层)

  1. jdbc连接数据库的参数
  2. 方言
  3. 类---表
  4. 属性---字段

Hibernate框架:持久层(Dao层)框架

Hibernat配置流程

  1. 添加jar包(hibernate3.jar、/required/、ojdbc6.jar、slf4j.jar、log4j.jar、slf4j-log4j.jar)

hibernate3.jar   +   required 目录中所有  + jpa  + 数据库驱动包

antlr-2.7.6.jar

commons-collections-3.1.jar

dom4j-1.6.1.jar

hibernate-jpa-2.0-api-1.0.0.Final.jar

hibernate3.jar

javassist-3.12.0.GA.jar

jta-1.1.jar

mysql-connector-java-5.1.12-bin.jar

slf4j-api-1.6.1.jar

  1. 添加Hibernate配置文件(hibernate.cfg.xml)

<hibernate-configuration>

<session-factory>

    <!-- 数据库连接 -->

    <property name="myeclipse.connection.profile">t38_oracle</property>

    <property name="connection.url">

        jdbc:oracle:thin:@localhost:1521:orcl

    </property>

    <property name="connection.username">t38</property>

    <property name="connection.password">123456</property>

    <property name="connection.driver_class">

        oracle.jdbc.OracleDriver

    </property>

    <!-- 辅助参数 -->

        <!-- 方言 -->

    <property name="dialect">

        org.hibernate.dialect.Oracle9Dialect

    </property>

    <!-- 显示sql语句 -->

    <property name="show_sql">true</property>

    <property name="format_sql">true</property>

    <!-- 引入映射文件 -->

    <mapping resource="com/hfxt/entity/User.hbm.xml" />

</session-factory>

</hibernate-configuration>

  1. 添加实体类和实体类的映射文件(User--User.hbm.xml)

//实体类User(javaBean):持久化类

public class User implements Serializable {

    //自动生成的串号

    private static final long serialVersionUID = 7373379251590476940L;

    private Integer id;

    private String username;

    private String password;

    private Integer status;

    private Date createtime;

    private Integer roleId;

}

//实体类映射文件User.hbm.xml

<hibernate-mapping package="com.hfxt.entity">

    <class name="User" table="TB_USER">

        <!-- 唯一标识:属性-主键 -->

<id name="id" column="ID" type="java.lang.Integer">

            <!-- 主键生成策略 -->

<generator class="sequence">

                <param name="sequence">SEQ_USER</param>

            </generator>

        </id>

        <property name="username" column="USERNAME" type="java.lang.String" ></property>

        <property name="password" column="PASSWORD" type="java.lang.String" ></property>

        <property name="status" column="STATUS" type="java.lang.Integer"></property>

        <!-- 设置修改时不更新 -->

        <property name="createtime" column="CREATETIME" type="java.util.Date" update="false"></property>

        <property name="roleId" column="ROLE_ID" type="java.lang.Integer"></property>

    </class>

</hibernate-mapping>

Test类:

public class Test {

    public static void main(String[] args) {

        User item = new User();//创建增加对象

        item.setUsername("bn");

        item.setPassword("456");

        item.setStatus(1);

        item.setCreatetime(new Date());

        item.setRoleId(1);

        //1.加载配置文件

        Configuration cfg = new Configuration().configure();

        //2.得到SessionFactory 重量级的 线程安全的

        SessionFactory sf = cfg.buildSessionFactory();

        //3.得到Session 轻量级的 非线程安全的

        Session session = sf.openSession();

        /* ThreadLocal:本地线程的私有空间

* 配置HibernateSessionFactory

Session session = HibernateSessionFactory.getSession();*/

        Transaction tx = null;

        try {

            //4.开启事务(增、删、改)

            tx = session.beginTransaction();

            //5.持久化操作

            //增加

            session.save(item);

            //item.setUsername("xxx");//持久化写入

            /*//先得到,再修改

            User item = (User) session.get(User.class, 23);//先得到

            item.setUsername("**");

            item.setPassword("789");

            session.update(item);

            //先得到,再删除

            User item = (User) session.get(User.class, 23);//先得到

            session.delete(item);*/

            //6.提交事务

            tx.commit();

        } catch (Exception e) {

            e.printStackTrace();

            if(tx != null) tx.rollback();

        } finally{

            //7.关闭session

            session.close();

        }

    }

}

为工程添加Hibernate支持:MyEclipse>Add Hibernate Capabilities

>com.hfxt.dao.impl>HibernateSessionFactory类

static {

    try {

        configuration.configure();

        sessionFactory = configuration.buildSessionFactory();

    } catch (Exception e) {

        System.err.println("%%%% Error Creating SessionFactory %%%%");

        e.printStackTrace();

    }

}

public static Session getSession() throws HibernateException {

Session session = (Session) threadLocal.get();//threadLocal:本地线程的私有空间 线程安全

    if (session == null || !session.isOpen()) {

        if (sessionFactory == null) {

            rebuildSessionFactory();

        }

        session = (sessionFactory!=null) ? sessionFactory.openSession(): null;

            threadLocal.set(session);

        }

    return session;

    }

Hiberante API:

|-- Session 一个与数据库连接的会话信息

Sesison里面维护了一个连接对象,且对常用操作进行封装!

更新:

session.save(obj);    保存一个对象

session.update(obj)   更新一个对象, 注意修改对象的主键一定要在数据库存在!

session.saveOrUpdate(obj)  保存或更新

如果有设置主键且主键存在执行更新!

没有设置主键执行保存!

session.delete(obj)     删除一个对象; 注意修改对象的主键一定要在数据库存在!

主键查询:

Session.get(clazz,id);    根据主键查询

Session.load(clazz,id);    根据主键查询

HQL查询(Hibernate Query language):面向对象的查询语言,查询对象、对象的属性

<!-- 关键字不区分大小写,类名和属性名区分大小写 -->

[select ...] from Entity [where ...] [group by ] [having ] [order by ]

update Entity set...[where ]

delete from Entity [where ]

HQL与SQL区别:

Hql 查询的是对象、对象的属性,区分大小写!

Hql查询的对象一定要有映射!

SQL 查询的是表、字段,不区分大小写!

HQL的使用:

//1 创建Session

    Session session = HibernateSessionFactory.getSession();

    //2 编写hql语句

    String hql = "from User";

    //String hql = "from User where username=? and password=?";

    //String hql = "from User where username=:uname and

password=:upass";//命名参数查询

    //3 创建Query对象

    Query query = session.createQuery(hql);

    //query.setString(0,"张三");

    //query.setString(1, "123");

    //query.setString("uname","张三");

    //query.setString("upass", "123");

    // 分页

    int currentPage = 1;

    int pageSize = 3;

    query.setFirstResult((currentPage-1)*pageSize);

    query.setMaxResults(pageSize);

    //4 执行查询,得到结果

    List<User> list = query.list();//根据结果集变换类型

    for(User user : list){

        System.out.println(user.getUsername());

    }

Hibernate执行流程

hibernate.cfg.xml配置详解:

hibernate-distribution-3.6.0.Final\project\etc\hibernate.properties

#hibernate.dialect org.hibernate.dialect.MySQLDialect

#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect

#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect

#hibernate.connection.driver_class com.mysql.jdbc.Driver

#hibernate.connection.url jdbc:mysql:///test

#hibernate.connection.username gavin

#hibernate.connection.password

自动建表:

#hibernate.hbm2ddl.auto create-drop  每次在创建sessionFactory的时候创建表;执行sf.close()删除表

#hibernate.hbm2ddl.auto create     每次都先删除表,再创建新的表

#hibernate.hbm2ddl.auto update      如果表不存在则创建,存在就不创建!

#hibernate.hbm2ddl.auto validate    检查映射配置与数据库结构是否一致,不一致就报错

映射配置:映射文件(*.hbm.xml),描述“对象”与“表”的映射关系

<!--

通过XML映射,把对象映射到数据库的表中

package 表示包名; 可选,如果没有写,后面的类必须指定类的全名!

auto-import="true" 默认为true,即在写hql的时候,会自动引入包名;

如为falsehql中对象要写上包名称

Query q = session.createQuery("from Users");

-->

<hibernate-mapping package="cn.itcast.b_api" auto-import="true">

<!--

class 表示映射的一个javabean对象(可以有多个class节点,但一般一个映射文件对应一个class)

name  表示映射的类的名称;

table (可选)类的名称,对应的表名, 如果不写默认与类名称一样

-->

<class name="Users" table="t_users">

<!--

id  表示映射的是主键

注意: hibernate的映射文件中,必须要有主键映射!

generator  表示的是主键生成策略  (Api : Various additional generators)

class

identity  主键自增长, mysql/sqlservlet等数据库使用的自增长的方式

sequence  以序列的方式实现自增长;

native   表示主键自增长: 根据底层数据库的能力选择 identitysequence等其中一个。

assigned  手动指定主键的值

uuid      uuid的值作为主键,确保一定唯一

-->

<id name="userId" column="id">

<generator class="native"></generator>

</id>

<!--

property 表示普通字段的映射

name 属性的名称

column 可选,如果没有指定,与属性名称一致

length 表示字符长度,只对字符类型有效

type 数据库中字段的类型  (如果没有指定,会匹配属性的类型)

hibernate中指定的类型小写开头

java中类型写类的全名

unique  设置为true,表示给当前列添加唯一约束

(主键约束 = 唯一约束 + 非空)

-->

<property name="userName" type="java.lang.String" column="username" length="50" unique="true"></property>

<property name="age" column="age" type="int"></property>

<!-- 注意:如果列名称对应的是数据库的关键字,需要处理 -->

<property name="desc" column="`desc`" length="200"></property>

</class>

</hibernate-mapping>

hibernate对象状态:临时状态(new)-持久化状态(session)-游离状态(session关闭)

session.save(对象);

  • 临时状态

1 . 直接new出来的对象

2. 不处于session的管理(即没有与任何一个session关联)

3. 对象在数据库中没有对应的记录!

    Employee  e  = new Employee();

    e.setId(2);  只要主键在数据库中存在,就说这个对象在数据库中有对应记录!

     在数据库中叫主键!

 OID, object identified 对象的唯一标识 (对应数据库中的主键)

(二) 持久化状态

1. 处于session的管理范围

    当执行session的方法如:save/update/saveOrUpdate/get/load

    对象就会自动转变为持久化状态!

2. 在数据库中有对应的记录

3. 处于持久化状态的对象,当对对象属性进行更改的时候,提交事务更改会反映到数据库中!

(三) 游离状态

1. 对象不处于session的管理范围;通常指session关闭后对象的状态

2. 对象在数据库中有对应的记录

UML:Unified Modeling Language,统一建模语言

工具:powerdesigner、visio、national rose

类图:关联、依赖、泛化、组合、聚合

关联关系:A关联B

public class A{

      private B b;

      private List<B> list;

}

依赖关系:A依赖B

public class A{

      public void add(B b){

}

}

对象关联关系:种类(一对多关联/一对一关联/多对多关联)-方向(单向/双向关联)

主键表-外键表 主表-子表 主键-外键

配置多对一关联:student--grade

  1. 外键改为对象:Student类中(private Grade grade;)
  2. 实体类映射文件配置many-to-one:Student.hbm.xml(

<!-- 多对一:grade-student外键 -->

<many-to-one name="grade" column="GID" class="Grade"></many-to-one>

配置一对多关联:grade--student

  1. 添加多的容器:

Grade类(private Set<Student> students = new HashSet<Student>();)

  1. 实体类映射文件配置one-to-many: Grand.hbm.xml

<!-- set集合 -->

<set name="students">

       <key column="GID"></key>

       <one-to-many class="Student" />

</set>

配置多对多关联:student--sc--course(相当于两个一对多)

  1. 添加多的容器:

Student类:private Set<Course> courses = new HashSet<Course>();

Course类:private Set<Student> students = new HashSet<Student>();

  1. 映射文件配置:

Student.hbm.xml:

<set name="courses" table="SC">

    <key column="SID"></key>

    <many-to-many column="CID" class="Course"></many-to-many>

</set>

Course.hbm.xml:

<set name="students" table="SC">

    <key column="CID"></key>

    <many-to-many column="SID" class="Student"></many-to-many>

</set>

ManyToManyTest类:

Session session = HibernateSessionFactory.getSession();

    Student s = (Student) session.get(Student.class, 1);

    Set<Course> courses = s.getCourses();

    for(Course course : courses){

        System.out.println(course.getCname());

    }

session.close();

cascade属性:级联

all、save-update(保存更新进行级联操作)、delete、none

inverse属性:控制反转,指定关联关系中的方向

    inverse=”false”:由主动方维护关联关系

    inverse=”true”: 由对方维护关联关系

Hibernate默认:默认false,只能改set中为true;一对多关联中,将一方的inverse改为true,有助于性能的改善

<!-- 级联删除 -->

    <set name="students" inverse="true" cascade="delete/all">

       <key column="GID"></key>

       <one-to-many class="Student" />

   </set>

级联删除:先维护关系,再删除

    <set name="students" inverse="true" cascade="delete" />

    <set name="students" cascade="delete">+Student表的GID(Nullable:true)

级联增加:先增加,再维护关系

级联修改:先维护关系,再修改,再维护关系

//先增加年级,再级联增加学生(先增加主表再增加子表)

        Grade grade = new Grade();

        grade.setGid(1);

        grade.setGname("T35");

        Student s1 = new Student();

        s1.setSid(1);

        s1.setSname("张三");

        s1.setSex("");

        s1.setGrade(grade);//设置年级(手工设置关系) 自动维护关系:inverse="true"并且studentGID(Nullable:true)

        Student s2 = new Student();

        s2.setSid(2);

        s2.setSname("李四");

        s2.setSex("");

        s2.setGrade(grade);

        Student s3 = new Student();

        s3.setSid(1);

        s3.setSname("王五");

        s3.setSex("");

        s3.setGrade(grade);

        //级联操作

        grade.getStudents().add(s1);

        grade.getStudents().add(s2);

        grade.getStudents().add(s3);

        Session session = HibernateSessionFactory.getSession();

        Transaction tx = null;

        try {

            tx = session.beginTransaction();

            session.save(grade);

            tx.commit();

        } catch (Exception e) {

            e.printStackTrace();

            if(tx != null){

                tx.rollback();

            }

        } finally{

            session.close();

        }

    }

Hibernate加载方式:延迟加载(默认)、立即加载

//默认延迟加载:

Session session = HibernateSessionFactory.getSession();

    Student s = (Student) session.get(Student.class, 1);

    System.out.println("--------------");

    System.out.println(s.getGrade().getGname()+":"+s.getSname());

    session.close();

//立即加载:fetch=”select/join”

<!-- 立即加载 fetch:sql查询语句内联 -->

<many-to-one name="grade" column="GID" class="Grade" fetch="join" />

Hibernate缓存

缓存分类:事务级别缓存、应用程序级别缓存、分布式缓存

缓存作用范围:事务范围 进程范围 集群范围

一级缓存:Session缓存,依赖于Session生命周期

清理缓存的方法:evict(Obeject obj)//清空对象、clear()//全部清空

二级缓存:SessionFactory外置缓存,依赖于SessionFactory的生命周期

Hibernate默认提供的是HashtableCache的二级缓存实现,它仅仅用于开发测试

通常配置一个第三方的缓存插件(EHCache、OsCache、SwarmCache、JBossCache)

二级缓存默认开启,配置文件中添加cache.user_second_level_cache,值为false可以关闭

配置二级缓存

  1. 添加ehcache.jar (依赖包commons-logging-1.1.1.jar)
  2. 在src下,添加ehcache.xml文件,文件模板在Hibernate源代码文件的etc文件夹下

<!-- 默认缓存策略 -->

    <defaultCache

        maxElementsInMemory="10000"--最大内存容量

        eternal="false"--永不过期false

        timeToIdleSeconds="120"--最大空闲时间

        timeToLiveSeconds="120"--最大存活时间

        overflowToDisk="true"--内存溢出存磁盘true

        />

    <!-- 自定义缓存策略 -->

    <cache name="com.hfxt.entity.User"

        maxElementsInMemory="10000"

        eternal="false"

        timeToIdleSeconds="300"

        timeToLiveSeconds="600"

        overflowToDisk="true"

        />

  1. 在配置文件添加cache.provider_class,值为:org.hibernate.cache.EhCacheProvider

默认cache.use_second_level_cache:true

  1. 在要使用缓存的类的映射文件中,在class节点下配置:<cache usage=”read-write” />

Hibernate查询:

get/load方法

get方法:

  1 在使用get方法查询的时候,它就会发送SQL语句,查询数据库,而不是在调用它的某个属性的时候

  2 在查询数据库,找不到的情况下,返回null;

load方法:

  1 在调用它的某个属性的时候才会去发送SQL语句,查询数据库

  2 找不到的情况下,就报异常

Session session = HibernateSessionFactory.getSession();

    User item1 = (User) session.get(User.class, 21);//get立即发送sql

    System.out.println("-----------------------------");

    System.out.println(item1.getUsername());

    System.out.println("++++++++++++++++++++++++++++++");

    session.close();//关闭一级缓存

    session = HibernateSessionFactory.getSession();

    //session.clear();//清空session缓存

    //session.evict(item1);//清空一个对象缓存

    User item2 = (User) session.load(User.class,21);//load需要时发送sql 创建虚拟对象item2

    System.out.println("------------------------------");

    System.out.println(item2.getUsername());

    session.close();

查询缓存:查询结果缓存,查询对象集合依赖于一级二级缓存;主要用于通过hql或qbc查询的缓存,主要对list起作用;

默认关闭的,通过在配置文件中配置cache.use_query_cache,值为true来开启,然后必须在代码中设置query.setCacheable(true)才能使用

list()/iterate()方法

iterate:查询对象的时候,先查询所有id,在使用的时候,根据id去一级缓存,二级缓存中去查询实体对象,如果查不到,根据id,逐个发送sql语句去数据库中查(N+1次问题)

list:查询缓存中会保存sql,结果集,不依赖于二级缓存,只存不取

第一次使用查询缓存和list查询的时候,得到 :

1.查询结果

2.如果是对象,它把结果放入一级缓存和二级缓存

3.如果是对象数组,把sql语句、id、类型放入查询缓存中

再一次使用list查询同样的hql的时候,会取得查询缓存里面的id去一二级缓存中查询,如果查不到,根据id查询数据库(N次问题)

Session session = HibernateSessionFactory.getSession();

    String hql = "from User";

    Query query1 = session.createQuery(hql);

    List<User> list = query1.list();//list()立即加载

    for(User u : list){

        System.out.println(u.getUsername());

    }

    System.out.println("++++++++++++++++++++++++++");

    session.close();

    session = HibernateSessionFactory.getSession();

    Query query2 = session.createQuery(hql);

    Iterator<User> it = query2.iterate();//iterate()延迟加载

    while(it.hasNext()){

        User u = it.next();

        System.out.println(u.getUsername());

    }

    session.close();

Hibernate注解

配置实体类注解:

@Entity:声明实体bean(持久化POJO类)

@Id:实体bean标识属性(数据表的主键)

@Generated:标识符的生成策略

@Table:实体bean映射指定表

@UniqueConstraint:表的唯一约束

@Column:属性映射到列

配置对象关联关系注解:@OneToMany @ManyToOne @ManyToMany

配置命名查询注解:@NamedQuery

Struts2

Struts2:基于MVC的Web应用框架,对servlet技术的封装

Struts2=WebWork技术+Struts1的知名度和市场

Action(业务控制器):用户(*.action)>ActionServlet(总控制器)>SubAction(execute方法)

Struts2使用步骤:

  1. 导入struts2支持的jar包

commons-beautils   [beanutils工具包]

commons-filupload.ajr、commons-io.jar [文件上传]

commons-lang       [struts2对java.lang.*类的支持]

freemarker.jar     [视图显示技术]

javassit            [struts2对字节码运算的支持]

ognl.jar            [struts2对ognl表达式的支持]

struts2-core.jar   [ struts2的核心包]

xwork-core.jar    [webwork框架的支持,struts2的前身就是webwork(对webwork的封装)]

  1. web.xml中配置启动的全局过滤器Filter(类似ActionServlet)

<!-- 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>

  1. 创建业务Action类,编写业务方法,默认execute方法:继承ActionSupport(实现Action接口)

//HelloAction

public class HelloAction extends ActionSupport{

private String message;//属性方式传参

    //处理请求的方法: 默认execute方法

public String execute() throws Exception{

        message = "Hello,struts2 ";

        return SUCCESS;//字符串常量:SUCCESS="success"

    }

    public String getMessage() {

        return message;

    }

    public void setMessage(String message) {

        this.message = message;

    }

}

  1. src/struts.xml,配置Action对象:

<struts>

<!-- 动态方法调用 /hello!reg 禁用>default properties-->

<constant name="struts.enable.DynamicMethodInvocation"

value="false" />

<package name="default" extends="struts-default" namespace="">

    <!-- 配置Action: 浏览器访问localhost:8080/struts2demo/hello -->

<!-- hello(action别名)>处理请求的类>处理请求的方法(默认execute) -->

    <action name="hello" class="com.hfxt.web.action.HelloAction" method="execute">

        <!-- 结果视图:type默认是dispatcher(转发),redirect(重定向) -->

        <result name="success" type="dispatcher">/index.jsp</result>

<result name="error" type=" redirect">/error.jsp</result>

    </action>

</package>

</struts>

  1. 浏览器访问业务方法:localhost:8080/struts2demo/hello,转发到index.jsp:

<body>

    ${message }

</body>

Struts2执行过程

项目启动:

1)创建核心过滤器StrutsPrepareAndExecuteFilter对象

2)执行核心过滤器的init方法,读取了依次以下的配置:

struts-default.xml   [struts2框架的默认配置文件(不需要自定修改)]

struts-plugin.xml    [struts2的插件配置文件]

struts.xml            [业务配置文件(包含配置的Action)]

访问资源:

3)在内存中查询对应的Action配置,得到class内容,创建Action对象

4)读取Action配置的method内容,执行Action对象对应的方法

struts-default.xml(对象bean>默认包(跳转类型|拦截器))-struts.xml(包package>Action>result)

struts-default.xml文件详解:

1)声明struts2框架运行过程中使用到的一些对象

<bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork"/>

2)默认包,包名叫struts-default(我们写的package必须继承默认包,才可使用该默认包下的功能)

<package name="struts-default" abstract="true">

<package name="default" extends="struts-default" namespace="">

2.1)常用跳转类型:

redirect: 重定向到页面

dispatcher: 转发到页面

redirectAction: 重定向到Action

chain:  转发到Action

<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>

2.2)声明拦截器(Interceptor):struts2默认的拦截器(32个),完成strutrs2的核心功能(请求封装,文件上传,国际化,后台数据校验..)

过滤器Filter:可以过滤任何类型的请求(html、servlet、jsp)和响应。加入通用的代码逻辑

拦截器Intercptor:sturts2特有功能,只能过滤Action。在执行Action的时候加入通用的代码

2.3)声明拦截器栈 (<interceptor-stack name="basicStack">)

默认拦截器:<interceptor-stack name="defaultStack">    (18个拦截器)

2.4)默认包当前使用的拦截器:

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

2.5)当前默认包下的默认Action

<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

struts.xml文件详解:开发者自行配置的业务配置文件

1)包package:用于管理Action,一般可以按模块划分包

package: 代表一个包。管理action配置。在用一个包下面不能有同名的action

name:包名,在一个项目中不能出现同名的包。

extends: 继承。如果一个包继承另一个包,就会把父包的功能继承下来

namespace: 名称空间。区分不同的包的访问路径。默认值“/”

  用户访问Action的路径搜索规则:http://localhsot:8080/project/namespace/action的name

abstract: 表示当前包是否抽象。如果当前包是抽象包,那么不能含有action。

抽象包中一般用来定义拦截器,公共视图,不做具体的业务。

2) Action和result的配置

action配置:

name: action的名称。用于访问该Action的路径

class: Action业务对象的类名。一定是全名(包名+类名),struts2是用反射构造Action对象

method: 执行的业务方法。不写默认值execute

result配置:

name: 视图的标记。在一个Action中名称不要重复

type: 跳转的类型。

redirect:重定向

dispatcher: 转发(默认值)

redirectAction: 重定向到Action

chain: 转发到Action。可以在不同Action中通过request共享数据

stream: 用在下载文件的时候。

文本内容: 跳转到的页面或者Action

3) 可以通过划分不同的xml文件来管理package

<!-- 包含读取其他xml文件,声明的顺序就是读取的顺序 -->

<include file="config/struts-action.xml"></include>

<include file="config/struts-path.xml"></include>

struts2的配置相关:Action三种使用方式-路径通配符-常量配置-全局视图配置和默认配置-Action的属性注入

1) struts2使用Action方法:不实现继承/实现Action接口/继承ActionSupport(常用)

/**

* 第一种方式:不需要实现或继承任何接口或类

*/

public class UserAction1 {

public String login()throws Exception{

System.out.println("UserAction1.login()");

return "success";

}

}

/**

* 第二种方式:实现Action接口

*  1) 定义了默认的execute方法的标准

*  2) 提供了项目中常用的视图标记

*/

public class UserAction2 implements Action {

public String login() throws Exception {

System.out.println("UserAction2.login()");

return SUCCESS;

}

public String execute() throws Exception {

return null;

}

}

/**

* 第三种方式:继承ActionSupport(推荐使用)

* 1)提供了常用的视图标记

* 2)提供了数据校验功能

*/

public class UserAction3 extends ActionSupport{

public String login() throws Exception{

System.out.println("UserAction3.login()");

return SUCCESS;

}

}

2) 路径通配符

<!-- 一个模块(Action对象)使用一个action配置:减少action的配置 -->

<!-- * (星号):表示路径的通配符

获取通配符的内容:{1}(表示获取第一个通配符的实际内容)-->

<!--

<action name="user_*" class="com.hfxt.b_path.UserAction" method="{1}">

<result name="{1}">/{1}.jsp</result>

</action>   -->

<!-- 多个模块使用一个action配置:第一个*代表模块,第二个代表方法

User_login   -->

<action name="*_*" class="com.hfxt.b_path.{1}Action" method="{2}">

<result name="{2}">/{1}/{2}.jsp</result>

</action>

2) struts2常量配置:struts-core.jar、default.properties常量文件

struts.xml文件中修改常量值 <constant name="" value=""/> 

<!-- 指定默认编码集,作用于HttpServletRequestsetCharacterEncoding方法 -->

<constant name="struts.i18n.encoding" value="UTF-8"/>

<!--自定义后缀修改常量-->

<constant name="struts.action.extension" value="do"/>

<!--设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭-->

<constant name="struts.serve.static.browserCache" value="false"/>

<!--struts配置文件修改后,系统是否自动重新加载该文件,默认为false(开发环境下使用)-->

<constant name="struts.configuration.xml.reload" value="true"/>

<!--开发模式下使用,这样可以打印出更详细的错误信息-->

<constant name="struts.devMode" value="true" />

<!--默认的视图主题-->

<constant name="struts.ui.theme" value="simple" />

<!--spring集成时,指定由spring负责action对象的创建-->

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

<!--该属性设置Struts2是否支持动态方法调用,该属性的默认值是true-->

<constant name="struts.enable.DynamicMethodInvocation" value="false"/>

<!--上传文件的大小限制-->

<constant name="struts.multipart.maxSize" value=“10701096"/>

3) 全局视图和action默认配置:

<!-- 全局结果: 当前包下的所有action共享视图

action中也有相同名称的视图,那么action的局部视图会覆盖全局视图  -->

<global-results>

  <result name="error">/error.jsp</result>

</global-results>

<!-- 异常映射: 程序出现异常是跳转到的结果视图 -->

<global-exception-mapping>

  <exception-mapping result="error" exception="java.lang.RuntimeException">

  </exception-mapping>

</global-exception-mapping>

<!--action默认配置:name(必填)class(可选,默认ActionSupport)method(可选)

result:name(可选,默认success)type(可选,默认dispatcher)  -->

<!-- 全部使用默认配置的action的作用:专门用于转发到WEB-INF下的页面 -->

<action name="user">

<result name="success">/WEB-INF/jsp/login.jsp</result>

</action>

4) Action属性注入: Action对象把经常改变的参数提取到配置文件中,就可以使用属性注入的方法

1)在Action类中声明一个成员变量,用于接收xml配置文件传入内容

2)在Action类提供一个该变量的setter方法,该方法接收了xml配置的内容

    //1)在action中提供一个属性

    private String iocStr;

    //2)提供属性的setter方法,用于外部的action的参数进行注入

    public void setIocStr(String iocStr) {

        this.iocStr = iocStr;

    }

3)在对应的struts.xml文件中,找到对应的action对象的配置,然后在action中使用<param name=""></param> 这个标签来向Action对象的属性注入内容

<action name="ioc" class="com.hfxt.d_ioc.IocAction" method="IocMethod">

<!--3)配置往Action对象的属性注入内容(只要有setter都可以使用param进行注入)

param:

name: setter方法名  setIocStr -> iocStr

-->

<param name="iocStr">”注入的字符串值”</param>

<result>/login.jsp</result>

</action>

struts2核心业务功能数据共享(三种方式)-请求数据封装-类型转换(自定义)-文件上传和下载、国际化-数据验证-模型驱动

1) (域对象)数据共享三种方式: ServletActionContext/ActionContext/Action

1. ServletActionContex得到servlet的api(依赖servlet)

HttpServletRequest getRequest():获取request对象

HttpSession getRequest().getSession():获取session对象

ServletContext getServletContext():获取ServletContext对象

2. ActionContext得到操作域对象数据的Map集合(不依赖servlet,方法局部)

      ActionContext ac =  ActionContext.getContext();

      Map<String,Object> requestMap = ac.getContextMap();

Map<String,Object> seesionMap = ac.getSession();

      Map<String,Object> contextMap = ac.getApplication();

requestMap/seesionMap/contextMap.put(“key”,value);

3. Action类实现RequestAware,SessionAware,ApplicationAware接口(action全局)

//实现提供的方法:获取操作域对象数据的Map集合

public UserAction extends ActionSpport implements RequestAware,SessionAware,ApplicationAware{

private Map<String,Object> requestMap/SessionMap/contextMap;

public void setRequest/setSession/setApplication(Map<String,Object> request/session/application){

  this.requestMap/SessionMap/contextMap = request/session/application;

}

requestMap/SessionMap/contextMap.put(“key”,value);

}

2) 请求参数封装:属性注入(setter)-JavaBean-ModelDriven

    表单参数(传值)>Action属性/JavaBean对象(赋值)>JSP页面(取值)

1. 基本数据类型接收参数(action中提供setter方法)

//参数赋值(注入方式)

    private String name;

    private String password;

    //参数通过这个set方法注入到Action

    public void setName(String name) {

        this.name = name;

    }

    public void setPassword(String password) {

        this.password = password;

    }

2. javabean类型接收参数(action提供getter和setter)

public class UserAction extends ActionSupport{

  //使用一个javabean对象接收

  private User user;

  public User getUser() {

      return user;

  }

  public void setUser(User user) {

      this.user = user;

}

用户名: <input type="text" name="user.name"/><br/>

  密码: <input type="password" name="user.password"/><br/>

Action接受参数的三种方式

 

属性方式

JavaBean方式

ModelDriven方式

form中上传参数

form中元素name取值属性名

form中元素name取值对象名.属性名

form中元素name取值属性名

Action中接收参数

为Action添加实体属性以及setter方法

对象表单参数的属性及对应JavaBean对象的setter、getter方法

Action实现ModelDriven接口,重写getModel()

页面中取值

${username}

<s:property value=”属性名”/>

name=”item.username”

${item.username}

<s:property value=”对象名.属性名”/>

<s:property value=”属性名”/>

3) 类型转换(自定义类型转换器,继承StrutsTypeConverter类)

默认情况下:基本数据类型可以直接从String转换,日期只能转yyyy-MM-dd类型

/**

     * 从页面的数据到服务器的类型转换

     * 参数一 context 值栈上下文对象

     * 参数二 values: 从页面传递过来的参数值

     * 参数三 toClass: 转换到的类型。String->java.util.Date

     */

public Object convertFromString(Map context,String[] values,Class toClass)

/**

     * 从服务器到页面的类型转换

     */

    public String convertToString(Map context, Object o) {

        return null;

    }

绑定自定义转换器的方式:

局部绑定(只能绑定一个Action):在action同一个包下建立ActionName-conversion.properties

user.birth=com.hfxt.g_convert.MyDateConverter

全局绑定(绑定整个项目多个Action):在src下建立xwork-conversion.properties

java.util.Date=com.hfxt.g_convert.MyDateConverter

4) 上传与下载

文件上传:

1.三个条件:表单有file、post提交、enctype="multipart/form-data"

    <s:form action="Upload" method="post" enctype="multipart/form-data">

        <input type="file" name="attach" />

        <input type="submit" value="上传" />

</s:form>

2.在Action中接收文件内容:

public class UploadAction extends ActionSupport {

单文件:

File attach;  (attach是file表单的name属性)

String attachContentType;  文件类型

String attachFileName;   文件名称

多文件:

File[] attach;

String[] attachContentType;

String[] attachFileName;

//属性设置setter方法:上传文件内容赋值

//文件保存

String savePath = ServletActionContext.getServletContext()

.getRealPath("/");  //获取路径

FileUtils.copyFile(attach,new File(savePath+attachFileName));

}

3.配置struts.xml,拦截器会自动接收上传的文件

<!-- 限制上传文件的大小和类型 -->

<constant name="struts.multipart.maxSize" value="100000"></constant>

<action name="upload" class="com.hfxt.web.action.UploadAction"

method="upload">

    <interceptor-ref name="fileUpload">

        <!-- 限制文件类型 -->

        <param name="allowedTypes">image/jpg,image/png</param>

        <!-- 限制文件后缀 -->

<param name="allowedExtensions">jpg,png</param>

    </interceptor-ref>

    <interceptor-ref name="defaultStack"></interceptor-ref>

<result>/upload_view.jsp</result>

<result name="upload">/upload.jsp</result>

</action>

文件下载:

<action name="down_*" class=" com.hfxt.upload_down.DownAction ">

<!-- 文件下载视图类型是stream -->

<result  type="stream">

<!-- 返回给浏览器的文件类型,返回通用的二进制 -->

<param name="contentType">xxx</param>

<!-- 返回给浏览器的输入流 -->

<param name="inputName">Action中定义获取输入流的方法(方法名)</param>

<!-- 浏览器下载资源的方式 -->

<param name="contentDispostion">xxx</param>

<!-- 缓存大小 -->

<param name="bufferedSize">1024</param>

</result>

</action>

//Action对象中提供一个对应的获取输入流的方法

public InputStream getInputStream(){

FileInputStream fis = new FileInputStream(new File(serverPath+name));

return fis;

}

拦截器interceptor(拦截Action资源)-值栈value stack(显示数据)

拦截器:只能拦截Action资源;拦截完Action,添加逻辑代码

1)自定义拦截器: 实现Interceptor接口

init(): 在创建拦截器对象的时候,拦截器对象在加载web应用时创建。

interceptor(): 每次访问action的业务方法的时候调用

destory(): 拦截器对象销毁的时候调用。web应用重新部署或web服务器停止

<!-- Struts.xml定义使用拦截器: 调用默认拦截器(defaultStack) -->

<package name="inter" extends="struts-default" namespace="/inter">

        <!-- 定义拦截器 -->

        <interceptors>

             <interceptor name="inter1" class=" com.hfxt.interceptor.MyInterceptor1"></interceptor>

        </interceptors>

        <!-- 全局作用的使用拦截器 -->

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

        <action name="user_*" class="com.hfxt.interceptor.UserAction" method="{1}">

             <!-- 局部作用的使用拦截器 -->

             <interceptor-ref name="inter1"></interceptor-ref>

             <result>/index.jsp</result>

        </action>

    <!-- 引入自定义拦截器 -->

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

</package>

2)拦截器栈:当前action同时被多个拦截器拦截,就使用拦截器栈

<!-- 拦截器栈 myStack -->

    <interceptor-stack name="myStack">

        <interceptor-ref name="Interceptor1"></interceptor-ref>

        <interceptor-ref name="Interceptor2"></interceptor-ref>

        <!-- 默认拦截器 defaultStack -->

        <interceptor-ref name="defaultStack"></interceptor-ref>

    </interceptor-stack>

<!-- 默认拦截器栈 defaultStack -->

    <interceptor-ref name="defaultStack"></interceptor-ref>

    <!-- struts-default.xml:默认拦截器 -->

<interceptor-stack name="defaultStack">

<interceptor-ref name="exception"/>

    <interceptor-ref name="alias"/>

    <interceptor-ref name="servletConfig"/>

    <interceptor-ref name="i18n"/>

<interceptor-ref name="prepare"/>

  <interceptor-ref name="chain"/>

<interceptor-ref name="scopedModelDriven"/>

      <interceptor-ref name="modelDriven"/>

      <interceptor-ref name="fileUpload"/>

  <interceptor-ref name="checkbox"/>

  <interceptor-ref name="multiselect"/>

<interceptor-ref name="staticParams"/>

<interceptor-ref name="actionMappingParams"/>

<interceptor-ref name="params">

          <param name="excludeParams">

dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*

</param>

  </interceptor-ref>

</interceptor-stack>

值栈:是struts2的数据存取的核心;Struts2使用OGNL作为默认的表达式

OGNL表达式(Object Graph Navigation Langage,对象图导航语言)>OGNLContext对象(存取数据)>OgnlValueStack值栈对象(存取数据List/Map)>Struts2标签

EL表达式:获取域对象的数据。不能存放数据,不能调用方法

Ognl表达式:获取域对象的数据。可以存放数据,可以调用方法

1、支持对象方法调用,如xxx.doSomeSpecial();

2、支持类静态的方法调用和值访问,表达式的格式:

@[类全名(包括包路径)]@[方法名 |  值名],例如:

@java.lang.String@format('foo %s', 'bar')

或@tutorial.MyConstant@APP_NAME;

3、支持赋值操作和表达式串联,如price=100, discount=0.8,

calculatePrice(),这个表达式会返回80;

4、访问OGNL上下文(OGNL context)和ActionContext;

5、操作集合对象

Struts2标签:逻辑标签(数据标签|控制标签)-UI标签-Ajax标签

<%@ taglib uri="/struts-tags" prefix="s"%>

逻辑标签:

迭代: <s:iterator value="ognl表达式" var="" status="">

赋值: <s:set var="" value="ognl表达式"/>

获取:  <s:property value="ognl表达式"/>

判断: <s:if/>  <s:elseif/>  <s:else/>

UI标签:数据回显功能

<s:form/>       -> <form>

<s:textfield/>  -> <input type="text"/>

<s:password/>   -> <input type="password"/>

<s:checkbox/>   -> <input type="checkbox"/>

<s:checkboxlist  list="多个值"/>  ->  多个<input type="checkbox"/>

<s:radio list="多个值"/>   ->  多个<input type="radio"/>

<s:select list="多个值"/>  -> <select>多个<option/></select/>

Ajax标签:dateimepicker

1) ognl表达式:存取数据(Ognl存取数据的核心:OgnlContext对象)

OgnlContext对象数据结构:

根对象 Object root: 直接访问属性

非根对象 Map values: 带#,根据key获取value

//struts2项目中导入ognl.jar包来实现支持ognl表达式

//1)创建一个OgnlContext对象

OgnlContext context = new OgnlContext();

//2a)user对象存入OgnlContext对象

context.put("user", user);//OgnlContext的非根对象存数据

//3a)使用Ognl表达式从OgnlContext对象取出数据

Object ognlObj = Ognl.parseExpression("#user.name");//表达式对象

Object result = Ognl.getValue(ognlObj, context, context.getRoot()); //获取数据方法

//2b)user对象存入OgnlContext对象

context.setRoot(user);////OgnlContext的根对象存数据

//3b)使用Ognl表达式从OgnlContext对象取出数据

Object ognlObj = Ognl.parseExpression("name");//表达式对象

Object result = Ognl.getValue(ognlObj, context, context.getRoot()); //获取数据方法

System.out.println(result);

<%@ taglib uri="/struts-tags" prefix="s"%>

<!-- EL表达式 -->

<%-- ${username } --%>

<%-- ${item.username } --%>

<!-- Struts2标签 -->

<!-- 访问根对象:对象.属性名 -->

<s:property value="item.username" />

<!-- 访问非根对象:#对象.属性名 -->

<s:property value="#session.loginUser.username" />

2) struts2值栈对象:ValueStack(Struts2存取数据的核心:实现类OgnlValueStack,本质OgnlContext)

ValueStack数据存储结构:List(根栈)-Map(非根栈)

OgnlValueStack对象数据结构:

List<Objet> root:  根对象(List栈)

OgnlContext对象:

Object root: 根对象              不用带#,直接访问属性

Map values: 非根对象(Map栈)     带#,根据key获取value

OgnlValueStack对象分为两部分存储数据:List-Map

List对象栈:Action对象,Provider对象,ValueStack.push(obj)

Ognl表达式访问List栈(不要#,直接写属性名):依次搜索

第一个对象:找user,找到返回,找不到往下一个对象找

第二个对象:找user,找到返回,找不到往下一个对象找

所有对象找完,都没有,就返回空

Map栈:request域的Map,session域的Map,application域的Map,attrMap,paramter参数的Map

Ognl表达式访问Map栈(必须要#,根据key找value):

request域的Map     : #request.user

session域的Map     :   #session.user

application域的Map :   #application.user

attr的Map,         :    #attr.uesr

paramter参数的Map   :  #parameter.user

用户访问Action对象业务方法:ActionContext对象>OgnlValueStack对象(List/Map)>Action对象

//1)获取ActionContext对象

ActionContext ac = ActionContext.getContext();

List<User> list = new ArrayList<User>();

list.add(new User("jacky",30));

list.add(new User("rose",40));

list.add(new User("lucy",50));

ac.getContextMap().put("userList", list);

Map<String,User> map = new HashMap<String,User>();

map.put("100", new User("mark",20));

map.put("101", new User("maxwell",30));

map.put("102", new User("lily",40));

ac.getContextMap().put("userMap", map);

//往域对象存放数据

ac.getContextMap().put("request_data", "request_data");

ac.getSession().put("session_data", "session_data");

ac.getApplication().put("application_data", "application_data");

//2)从ActionContext对象获取OnglValueStack对象

ValueStack vs = ac.getValueStack();

//3)查看OnglValueStack对象的结构

//往OgnlValueStack的根对象(List栈)存放数据

vs.push(user);//往List栈 的栈顶

vs.pop(); //从List栈中 取出元素(栈顶元素)

<%-- 1) 取出List栈的数据 --%>

<s:property value="user.name"/> - <s:property value="user.age"/> <br/>

<%--查看值栈的所有数据 --%>

<%--2) 取出Map栈的数据 --%>

<s:property value="#request.request_data"/><br/>

<%--值栈对象是通过request域专递到页面,可以直接忽略#request去取request域的数据 --%>

<s:property value="#request_data"/><br/>

<s:property value="#session.session_data"/><br/>

<s:property value="#application.application_data"/><br/>

<%-- #attr:三个域中从小到大搜索数据: #request->#session->#application --%>

<s:property value="#attr.session_data"/><br/>

<s:property value="#parameters.name"/><br/>

<hr/>

${session_data }

<hr/>

<%-- 遍历集合 :List--%>

<s:iterator value="#request.userList" var="user">

姓名: <s:property value="#user.name"/> - <s:property value="#user.age"/><br/>

</s:iterator>

<hr/>

<%-- 遍历集合:Map --%>

<s:iterator value="#request.userMap" var="entry">

编号: <s:property value="#entry.key"/> - 姓名: <s:property value="#entry.value.name"/> - <s:property value="#entry.value.age"/><br/>

</s:iterator>

<s:debug></s:debug>

struts2核心功能:国际化-数据验证-模型驱动

struts2中简化国际化步骤:

1)准备不同国家的资源包

中国: message_zh_CN.properties

user=用户名

美国: message_en_US.properties

英国:  message_en_GB.properties

2)在struts.xml文件中(修改)指定资源包加载路径的常量

struts.custom.i18n.resources=message

3)在页面上使用资源包的内容

<s:text name="user"/>

struts2数据验证:提供给开发者进行表单数据的后台数据验证的功能

1)Action类继承ActionSupport(为了实现Valiateable接口)

2)Action类覆盖validate方法(验证所有方法)

public void validate() {

//在这里写表单数据验证的逻辑

//System.out.println("调用了validate方法");

if(user.getName()==null || user.getName().equals("")){

//用户名为空

//把错误信息放入错误信息Map集合

super.addFieldError("user.error.requried", "用户名不能为空!");

}

if(user.getPassword()==null || user.getPassword().equals("")){

//密码为空

//把错误信息放入错误信息Map集合

super.addFieldError("password.error.requried", "密码不能为空!");

}

}

3)在struts.xml文件中对应的action配置加上input视图,然后struts2就会自动把错误信息转发到input视图的页面上去

4)在input视图页面上,打印出错误信息

<s:fielderror></s:fielderror>

模型驱动:

请求数据封装:

方式一: 表单:name -> 基本数据类型: String name

方式二: 表单:user.name -> javabean数据类型:User user  (User:String name)

方式三(模型驱动方式):表单:name -> javabean数据类型:User user (User:String name)

public class UserAction extends ActionSupport implements ModelDriven<User>{

      //注意:使用模型驱动的方式,存放数据的模型引用不能为空

      private User user = new User();

      //该方法struts2可以把值栈中的请求参数封装到User对象

      public User getModel() {

         return user;

      }

}

Spring

Spring框架:轻量级的企业级开源框架,面向Bean的编程

Spring体系结构

功能模块:Core Container>AOP>Data>Access/Integration>Web

Ioc:Inversion of Control,控制反转 / 依赖注入(DI:Dependency Injection)

实现业务层与数据访问层解耦合,将组件对象C的控制权从代码本身转移到外部容器:

A --工厂BFactory--  B (IB接口 B1 B2 B3)

public class A {

  IB b = BFactory.getInstance();

}

Spring配置步骤

  1. 添加核心jar包:spring-beans|spring-context|spring-core|spring-expression

commons-logging.jar            【单独下载】

spring-beans.RELEASE.jar      【spring源码, bean节点管理】

spring-context.RELEASE.jar     【spring上下文类】

spring-core.RELEASE.jar        【IOC容器】

spring-expression.RELEASE.jar  【spring表达式】

  1. 添加配置文件applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:context="http://www.springframework.org/schema/context"

        xmlns:tx="http://www.springframework.org/schema/tx"

        xmlns:p="http://www.springframework.org/schema/p"

        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd

                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <!-- 创建对象 -->

    <!-- userDaoImpl userDao = new UserDaoImpl() -->

    <bean id="userDao" class="com.hfxt.dao.impl.UserDaoImpl"></bean>

    <!-- userService对象注入userDao对象 -->

    <!-- 设值注入  scope默认singleton(单例) -->

    <bean name="userService" class="com.hfxt.service.impl.UserServiceImpl" scope="prototype">

        <!-- ref注入对象  value注入值 -->

        <property name="UserDao" ref="userDao"></property>

        <property name="name" value="ftmy"></property>

        <!-- 注入List集合 -->

        <property name="testList">

            <list>

                <value>aaa</value>

                <value>bbb</value>

            </list>

        </property>

    </bean>

    <!-- 构造注入 -->

    <bean name="userService" class="com.hfxt.service.impl.UserServiceImpl">

        <constructor-arg ref="userDao"></constructor-arg>

    </bean>

    <!-- p标签注入方式 -->

    <bean name="userService" class="com.hfxt.service.impl

.UserServiceImpl" p:name="ftmy" p:userDao-ref="userDao" ></bean>

</beans>

  1. 在要注入的类添加注入接口:set方法注入/构造注入

UserDao userDao;

/**

* 注入接口:设值注入

* @param userDao

 */

public void setUserDao(UserDao userDao) {

    this.userDao = userDao;

}

/**

* 构造注入

*/

public UserServiceImpl(UserDao userDao) {

    this.userDao = userDao;

}

Test.java:

public static void main(String[] args) {

/*

* 获取注入对象

*/

    //加载spring配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext(

"applicationContext.xml");

    //getBean()方法获取对应idnameBean对象

    UserService userService = (UserService) ctx.getBean("userService");

    userService.addUser();

/*

UserService userService1 = (UserService) ctx.getBean(

"userService");

UserService userService2 = (UserService) ctx.getBean(

"userService");

System.out.println(userService1 == userService2);//同一对象

*/

}

Spring IOC容器

配置文件详解:创建bean细节

<!-- 把对象加入IOC容器 -->

<!--

细节1

id    name

id 不能以数字开头,不能含有特殊符号, 不能有空格、逗号等;  id 不能重复!

name 可以以数字开头,可以有特殊符合,如果name值重复,编译没有问题但运行报错!

<bean id="user" name="user2,user3 user4" class="cn.itcast.a_config.User"></bean>

<bean name="user5" class="cn.itcast.a_config.User"></bean>

<bean id="user6" class="cn.itcast.a_config.User"></bean>

<bean id="user6" class="cn.itcast.a_config.User"></bean>

-->

<!-- 细节2 (单例/多例)  -->

<!--

scope="singleton"   默认表示单例!

prototype    多例

init-method=""      在创建完对象之后执行初始化方法

destroy-method=""   在调用容器类的destroy()方法时候,对单例的对象有效!

lazy-init="true"    延迟初始化 / 这个属性的设置只对单例有影响,对多例没有任何影响!

单例的对象默认是在创建容器的时候就创建所有单例的对象,如果希望在第一次访问的时候创建单例的对象,就设置延迟初始化

Bean生命周期:

beanxml中配置,

singleton  单例

1) 创建对象

如果有配置延迟初始化,

lazy-init=true  如果单例的对象有配置延迟初始化, 在创建容器之后,在第一次从容器获取对象的时候

创建单例的对象!

如果没有配置或延迟初始化为默认值, 单例的对象会在创建容器的时候创建对象

2) 执行初始化方法 , init-method配置的方法会执行

3) 调用容器destroy() 方法时候,容器在销毁单例对象的实例的时候,会调用destroy-method对应的方法

此时bean对象会被销毁!

prototype  多例

1) 每次在从容器获取对象的时候,都会创建新的对象

2) 每次创建完对象后,就执行初始化方法

3) java回回收不用资源(jvm gc)

-->

<bean id="user"

class="cn.itcast.a_config.User"

init-method="init"

destroy-method="destroy_"

lazy-init="false"

scope="prototype"></bean>

</beans>

自动装配:默认no|byName|byType|constructor

全局装配:default-autowire="byName"

<bean name="userService" class="com.hfxt.service.impl.UserServiceImpl" autowire="byName" >

</bean>

IoC两大关键技术一个设计模式:JDOM(DOM解析)|反射机制|工厂模式(单例模式)

Bean作用域:singleton(默认)、prototype、request、session

处理对象的依赖关系:

给对象属性赋值(DI, 依赖注入),几种方式:

 1) 构造函数赋值

 2) set 方法注入值

    * 普通字段赋值

    * 集合属性 (list/map/property)

注解总结:

@Component  表示一个组件(类),把当前组件加入ioc容器

加入容器的组件的名称默认是类名第一个字母小写

@Component(“”)   指定加入ioc容器的组件类的类名

@Repository    标识是一个持久层的组件

@Service       标识是一个业务逻辑层的组件

@Controller     标识是一个控制层的组件

@Scope("prototype") 指定对象单例/多例

@Resource     1. 默认根据修饰的字段名称会取ioc容器找对象自动注入找到后注入

2. 如果名称没有找到,再根据类型查找  找到后就立刻注入

如果改类型在ioc容器中有多个对象,报错!

3. 根据类型也没有找到对象,报错!

@Resource(name =””) 会根据指定的名称去容器找对象自动注入

创建对象的几种方式:

1) 调用无参数构造器

2) 调用有参数构造器

3) 工厂

* 静态方法

<bean id=”’  class=””  factory-method=””/>

* 非静态方法

<bean id=”factory”  class=”..”>

<bean id=””  factory-bean=” factory”   factory-method=”实例方法” />

4)  反射

AOP(Aspect Oriented Programming):面向切面编程(面向方面编程), 关注点代码(重复执行的代码,关注点代码形成的类叫做切面)与业务代码分离

使用Aop开发步骤:

1. 引入aop 相关 jar文件

(aspectj在spring之前,面向切面开发的公用组件)

aopalliance.jar               [spring-framework-2.5.6\lib\aopalliance]

aspectjrt.jar             [spring-framework-2.5.6\lib\aspectj]

aspectjweaver.jar             [spring-framework-2.5.6\lib\aspectj]

spring-aop-3.2.5.RELEASE.jar      [Spring3.2源码]

2. 引入aop名称空间

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:aop="http://www.springframework.org/schema/aop"

    xsi:schemaLocation="

        http://www.springframework.org/schema/aop

        http://www.springframework.org/schema/aop/spring-aop.xsd">

  <!-- 开启注解扫描 -->

  <context:component-scan base-package="cn.itcast.e_aop_anno"></context:component-scan>

  <!-- 开启aop注解 -->

  <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

4. 使用Aop相关注解

@Aspect     指定一个类为切面类

(切面类也需要实例化)(切面类中的方法,也叫做通知)

@Before           前置通知    【在执行目标对象方法之前执行】

@After           后置通知    【在执行目标对象方法之后执行】

@AfterReturning    返回后通知  【在执行目标对象方法结束后执行, 出现异常不执行】

@AfterThrowing    异常通知     【在执行目标对象方法出现异常时候执行】

@Around            环绕通知     【环绕目标方法执行】

@Pointcut 定义一个切入点表达式变量(后面使用这个切入点表达式的时候,直接引用方法名即可)

Spring生成代理对象的过程:

1. 创建容器对象的时候, 根据“切入点表达式”拦截的类,生成代理对象;

2. 如果目标对象有实现接口,使用jdk代理!

3. 如果目标对象没有实现接口,使用cglib代理!

4. 从容器获取代理后的对象

5. 执行代理对象的方法,在运行时期,动态植入“切面”类中的“通知”!

aop编程

1. 引入aop 相关jar文件

2. bean.xml  引入aop名称空间

3. Aop配置:XML配置方式

<beans

    <!-- dao实例加入容器 -->

    <bean id="userDao" class="cn.itcast.f_aop_xml.UserDao"></bean>

    <!-- 实例化切面类 -->

    <bean id="aop" class="cn.itcast.f_aop_xml.TransactionAop"></bean>

    <!-- Aop相关配置 -->

    <aop:config>

        <!-- 切入点表达式定义 -->

        <aop:pointcut expression="execution(* cn.itcast.f_aop_xml.UserDao.*(..))" id="pt"/>

        <!-- 切面配置 -->

        <aop:aspect ref="aop">

            <!-- 【环绕通知】 -->

            <aop:around method="arroud" pointcut-ref="pt"/>

            <!-- 【前置通知】 在目标方法之前执行 -->

            <aop:before method="beginTransaction" pointcut-ref="pt" />

            <!-- 【后置通知】 -->

            <aop:after method="commit" pointcut-ref="pt"/>

            <!-- 【返回后通知】 -->

            <aop:after-returning method="afterReturing" pointcut-ref="pt"/>

            <!-- 异常通知 -->

            <aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>

        </aop:aspect>

    </aop:config>

</beans>

4.AOP编程:主要是分离业务代码与关注点代码;关注点代码,写一次,在执行业务代码时候动态植入关注点代码

public void add(User user) {

Session session = null;

Transaction trans = null;

try {

session = HibernateSessionFactoryUtils.getSession();   【关注点代码】

trans = session.beginTransaction();                      【关注点代码】

session.save(user);     // 业务

trans.commit();                                            【关注点代码】

} catch (Exception e) {

e.printStackTrace();

if(trans != null){

trans.rollback();

}

} finally{

HibernateSessionFactoryUtils.closeSession(session);

}

}

切入点表达式:拦截指定的类,生成代理对象

execution(

modifiers-pattern?           拦截的方法的访问修饰符

ret-type-pattern               方法返回类型,必须指定

declaring-type-pattern?        拦截的方法所在的类

name-pattern(param-pattern)    拦截的方法(以及方法的参数列表)

throws-pattern?)                方法声明的异常

代理模式Proxy:静态代理-动态代理(Jdk代理/Cglib子类代理)

类的单一职责原则(一个类只做一件事件),在不改变一个类的情况下,给这个类添加新的功能(被代理类-代理类)

静态代理:一个被代理类都必须有一个代理类

动态代理:可以根据被代理的对象来生成代理类的对象

Cglib代理:子类代理,当目标对象没有实现接口,就不能使用jdk提供的代理,可以以子类的方式实现,在运行时期动态在内存中构建一个子类对象的方法,从而对目标对象扩展,这种就是cglib代理!

Spring也支持cglib代理,核心包中已经包含此功能!

   JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口的类,就可以使用CGLIB实现。

   CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。

   CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

public class SecurityHandler implements InvocationHandler {

    private Object delegate;//被代理类的对象

    /**

     * 根据被代理类的对象生成代理类的对象

     * @param delegate

     * @return

     */

    public Object newProxy(Object delegate){

        this.delegate = delegate;

        return Proxy.newProxyInstance(delegate.getClass()

.getClassLoader(), delegate.getClass().getInterfaces(), this);//参数:被代理类类加载器,被代理类接口,当前handler

    }

    @Override

    public Object invoke(Object proxy, Method method, Object[] args)

            throws Throwable {

        //System.out.println(method.getName());//打印方法名

        Object o = method.invoke(delegate, args);

        //Object o = addNewUser();//新的add方法(在不改变原先类的情况下,实现替换或增加新功能)

        Security security = new Security();

        security.checkSecurity();

        return o;

    }

    public int addNewUser(){

        System.out.println("--------addNewUser---------");

        return 1;

    }

}

public static void main(String[] args) {

    SecurityHandler sh = new SecurityHandler();

    //根据被代理类的对象来生成代理类的对象

    UserDao userDao = (UserDao) sh.newProxy(new UserDaoImpl());

    //所有调用转为对invoke()方法的调用

    userDao.addUser();

}

AOP横切技术:核心关注点、横切关注点

增强(Advice)、切入点(Pointcut)、连接点(Joinpoint)

切面(Aspect)、代理(Proxy)、目标对象(Target)、织入(Weaving)

Advisor配置

//实现前置增强处理接口MethodBeforeAdvice

public class ServiceBeforeAdvisor implements MethodBeforeAdvice {

    @Override

    public void before(Method arg0, Object[] arg1, Object arg2)

            throws Throwable {

        //启动事务的代码

    }

}

<bean id="serviceBeforeAdvisor" class="com.hfxt.aop"></bean>

<aop:config>

<aop:pointcut id="servicePointcut" expression="execution

(public * com.hfxt.service.*.*(..))" />

<!-- 在切入点织入增强处理 -->

<aop:advisor advice-ref="serviceBeforeAdvisor"

pointcut-ref="servicePointcut"/>

</aop:config>

实现AOP方式3种方式:配置、注解、实现接口

SSH

SSH整合:Struts2--Spring(粘合剂|对象注入)--Hibernate

Spring与Struts整合→Action创建交给Spring完成

Spring与Hibernate整合→SessionFactory创建,交给spring完成(管理事务)

添加struts2

1、在lib下添加jar包(struts-2.3.16.3\apps\struts2-blank\WEB-INF\lib)

2、在src下添加struts.xml配置文件(apps\struts2-blank\WEB-INF\classes)

3、在web.xml中添加struts2核心控制器(过滤器组成)(apps\struts2-blank\WEB-INF\web.xml)

4、登陆界面

<!-- 修改默认布局 -->

<constant name="struts.ui.theme" value="simple"></constant>

<!-- 表单提交至/user命名空间的login方法 -->

<s:form action="login" namespace="/user">

    用户名:<s:textfield name="item.username"></s:textfield> <br />

    密码:<s:password name="item.password"></s:password> <br />

    <s:submit value="登陆"></s:submit>

</s:form>

ActionContext.getContext().getSession().put("username", username);

欢迎您!<s:property value="#session.username"></s: property >

添加spring

1、在lib下添加jar包(spring-framework-3.2.8.RELEASE\libs\)

2、在src下添加spring的配置文件applicationContext.xml

3、在web.xml中配置spring配置文件位置及配置一个监听器来加载spring的配置文件

<!-- Spring -->

    <!-- spring配置文件位置 -->

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>

            classpath:applicationContext.xml

        </param-value>

    </context-param>

    <!-- 监听器 -->

    <listener>

        <listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

    </listener>

整合struts2spring

1、添加一个整合的jar包(struts-2.3.4.1\lib\struts2-spring-plugin-2.3.4.1.jar)

2、在struts.xml中添加一个常量

<!-- 对象的创建工作交给spring -->

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

3、在spring的配置文件创建action类的bean,切记scope="prototype"

<!-- scope="prototype" -->

<bean name="userAction" class="com.hfxt.web.action.UserAction" scope="prototype">

</bean>

4、在struts.xml中把action的class改为spring中bean的id

<action name="login" class="userAction" method="login">

</action>

添加hibernate

1、在lib下添加jar包

2、添加hibernate配置文件并配置(t38_mysql hibernate.show_sql)

3、添加实体类和实体类的映射文件

<id name="id" column="id" type="java.lang.Integer">

    <generator class="native"></generator>

</id>

整合springhibernate

1、添加一些必须包(spring-jdbc|orm|tx)

2、创建dao层,在spring配置文件中加载hibernate配置文件,得到sessionFactory.把sessionFactory注入到userDao

3、创建service层并注入dao

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

    @Override

    public User getUserByUsername(String username) {

        String hql = "from User where username=?";

        List<User> list = super.getHibernateTemplate().find(hql, username);

        return list != null && list.size() > 0 ? list.get(0) : null;

    }

}

<!-- 加载hibernate配置文件 -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate3

.LocalSessionFactoryBean">

    <property name="configLocations">

        <value>classPath:hibernate.cfg.xml</value>

    </property>

</bean>

<!-- dao -->

<!-- sessionFactory注入到userDao -->

<bean id="userDao" class="com.hfxt.dao.impl.UserDaoImpl">

    <property name="sessionFactory" ref="sessionFactory"></property>

</bean>

<!-- service -->

<bean id="userService" class="com.hfxt.service.impl.UserServiceImpl">

    <property name="userDao" ref="userDao"></property>

</bean>

<!-- Action(注入userService) -->

<!-- scope="prototype" -->

<bean id="userAction" class="com.hfxt.web.action.UserAction" scope="prototype">

    <property name="userService" ref="userService"></property>

</bean>

4、修改aciton等

ssh整合改:BaseDao--Dao--Service--Action

源文件夹newSourceFolder:src/code src/config

开闭原则:Dao层|IBaseDao接口-BaseDao实体类--BaseService(存放注入接口或扩展功能)--BaseAction

异常处理

Exception>ServiceException>DaoException>HibernateDaoSupportException

拆分配置文件

Spring配置文件拆分:

applicationContext.xml

<!-- connection-->

<!-- 加载属性文件:jdbc.properties(键值对) -->

<context:property-placeholder location="classpath:jdbc.properties"/>

<!-- dataSource 数据库连接池 -->

    <bean id="dataSource" class="com.mchange.v2.c3p0

.ComboPooledDataSource" destroy-method="close">

        <property name="driverClass" value="${jdbc.driverClassName}" />

        <property name="jdbcUrl" value="${jdbc.url}" />

        <property name="user" value="${jdbc.username}" />

        <property name="password" value="${jdbc.password}" />

        <!-- 指定连接数据库连接池的最大连接数 -->

        <property name="maxPoolSize" value="${jdbc.maxPoolSize}" />

        <!-- 指定连接数据库连接池的最小连接数 -->

        <property name="minPoolSize" value="${jdbc.minPoolSize}"/>

        <!-- 指定连接数据库连接池的初始化连接数 -->

        <property name="initialPoolSize"

value="${jdbc.initialPoolSize}">

</property>

        <!-- 指定连接数据库连接池的连接的最大空闲时间 -->

        <property name="maxIdleTime" value="${jdbc.maxIdleTime}" />

    </bean>

    <!-- sessionFactory -->

    <bean id="sessionFactory" lass="org.springframework.orm

.hibernate3.LocalSessionFactoryBean">

        <property name="dataSource">

            <ref bean="dataSource" />

        </property>

        <property name="hibernateProperties">

            <props>

                <prop key="hibernate.dialect">

                    ${jdbc.dialect}

                </prop>

                <prop key="hibernate.show_sql">

${hibernate.show_sql}

</prop>

            </props>

        </property>

        <property name="mappingResources">

            <list>

                <value>com/hfxt/entity/User.hbm.xml</value>

            </list>

        </property>

    </bean>

<!-- 配置声明式事务 -->

    <!-- 创建事务管理器 -->

    <bean id="myTransactionManager" class="org.springframework.orm

.hibernate3.HibernateTransactionManager">

        <property name="sessionFactory" ref="sessionFactory"></property>

    </bean>

    <!-- 创建一个事务advice -->

    <tx:advice id="txAdvice" transaction-manager="myTransactionManager">

        <tx:attributes>

            <tx:method name="add*" propagation="REQUIRED"></tx:method>

            <tx:method name="del*" propagation="REQUIRED"></tx:method>

            <tx:method name="update*" propagation="REQUIRED"></tx:method>

            <tx:method name="do*" propagation="REQUIRED"></tx:method>

            <tx:method name="*" propagation="SUPPORTS" read-only="true">

</tx:method>

        </tx:attributes>

    </tx:advice>

    <!-- aop -->

    <aop:config proxy-target-class="true">

        <aop:pointcut id="bizMethods" expression=

"execution(* com.hfxt.service.*.*(..))" />

        <aop:advisor advice-ref="txAdvice" pointcut-ref=

"bizMethods"></aop:advisor>

    </aop:config>

daoContext.xml

<!-- 导入公共配置文件 -->

<import resource="applicationContext.xml"/>

<!-- dao -->

<bean id="baseDao" class="com.hfxt.dao.impl.BaseDao" abstract="true">

    <property name="sessionFactory" ref="sessionFactory"></property>

</bean>

<bean id="userDao" class="com.hfxt.dao.impl.UserDaoImpl" parent=

"baseDao">

</bean>

serviceContext.xml

<!-- 导入dao层配置文件 -->

<import resource="daoContext.xml"/>

<!-- service -->

<bean id="baseService" class="com.hfxt.service.impl.BaseService" abstract="true">

<property name="userDao" ref="userDao"></property>

</bean>

<bean id="userService" class="com.hfxt.service.impl.UserServiceImpl" parent="baseService">

</bean>

actionContext.xml

<!-- 导入service层配置文件 -->

<import resource="serviceContext.xml"/>

<bean id="baseAction" class="com.hfxt.web.action.BaseAction" abstract="true">

<property name="userService" ref="userService"></property>

</bean>

<!-- scope="prototype" -->

<bean id="userAction" class="com.hfxt.web.action.UserAction" scope="prototype" parent="baseAction">

</bean>

Struts配置文件拆分:struts.xml(公共部分)--struts-admin.xml

日志:debug--info--warn--error

web.xml:

<!--如果不定义webAppRootKey参数,那么webAppRootKey是缺省的"webapp.root"-->

<context-param>

    <param-name>webAppRootKey</param-name>

<!-- 这里的t38http://localhost:8080/t38/ -->

<!-- root是系统开发目录中t38.root-->

    <param-value>t38.root</param-value>

</context-param>

<!--Sprng载入的Log4j配置文件位置-->

<context-param>

    <param-name>log4jConfigLocation</param-name>

    <param-value>classpath:log4j.properties</param-value>

</context-param>

<!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond-->

<context-param>

    <param-name>log4jRefreshInterval</param-name>

    <param-value>60000</param-value>

</context-param>

<!-- Web 项目 Spring 加载 Log4j 的监听 -->

<listener>

    <listener-class>

org.springframework.web.util.Log4jConfigListener

</listener-class>

</listener>

log4j.properties:

<!-- 取消显示多余信息 debug->info -->

log4j.logger.xxx=INFO

<!-- 添加log-->

public Logger log = LoggerFactory.getLogger(this.getClass());

log.info("{} login success!!!"+item.getUsername());

登陆jQuery>ajax>json>Map集合(type="json")

导入jquery和验证框架:${jquery_js} ${validate_js } ${validate_css }

taglibs.jspBasejsp

<%-- system values --%>

<c:set var="ctx" value="${pageContext.request.contextPath}" />

<c:set var="siteName" value="******系统" />

<%-- css file define--%>

<c:set var="index_css" value="<link href='${ctx}/css/index.css' rel='stylesheet' type='text/css' />"/>

<c:set var="validate_css" value="<link href='${ctx}/css/validate.css' rel='stylesheet' type='text/css' />"/>

<%-- js file define --%>

<c:set var="jquery_js" value="<script type='text/javascript' src='${ctx}/js/jquery-1.7.js'></script>"  />

<c:set var="validate_js" value="<script type='text/javascript' src='${ctx}/js/jquery.validate.js'></script>"  />

//表单验证

$(function() {

    //定义规则

    $("#login_form").validate({

        rules : {

            "item.username" : "required",//name属性:

            "item.password" : {

                "required" : true,

                "minlength" : 3

            }

        },

        messages : {

            "item.username" : "用户名不能为空",

            "item.password" : {

                "required" : "密码不能为空",

                "minlength" : "密码长度不能小于3"

            }

        }

    });

    $("#btnLogin").click(function() {

        /* //非框架验证

         if ($.trim($("#username").val()) == "") {

            alert("用户名不能为空");

            return;

        }

        if ($.trim($("#password").val()) == "") {

            alert("密码不能为空");

            return;

        } */

        //validate框架验证

        $(this).attr('disabled',"true");//禁用登陆按钮-防止多次提交请求

        if ($("#login_form").valid()) {

            var url = "${ctx}/user/ajaxLogin.action";

            $.post(

                url,

                { "item.username" : $("#username").val(),

"item.password" : $("#password").val() },

                function(data) {

                    $("#btnLogin").removeAttr("disabled");//启用按钮

                    if (data.retcode == "0") {

                     window.location.href="${ctx}/user/findUsers.action";

                    } else {

                        alert(data.retmsg);

                    }

                }

            );

        }

    });

});

<body>

    <s:form id="login_form" action="login" namespace="/user">

        用户名:<s:textfield name="item.username" id="username"/><br />

        密码:<s:password name="item.password" id="password"/><br />

        <input type="button" value="登陆" id="btnLogin" />

    </s:form>

</body>

public String ajaxLogin(){

    try {

item = userService.checkLogin(item.getUsername(),

item.getPassword());

        if(item != null){

            putToSession("loginUser",item);

            log.info("{} login success!!!"+item.getUsername());

            resultMap.put("retcode", RetCode.SUCCESS);

        } else{

            resultMap.put("retcode", RetCode.FAIL);

            resultMap.put("retmsg", "用户名或密码错误!");

        }

    } catch (Exception e) {

        log.error("method login bug:"+e);

        resultMap.put("retcode", RetCode.UNKOWN_WRONG);

        resultMap.put("retmsg", "未知错误!请重试或联系管理员!");

    }

    return SUCCESS;

}

<package name="default" extends="json-default" namespace="/user">

<action name="ajaxLogin" class="userAction" method="ajaxLogin">

        <result type="json">

            <param name="root">resultMap</param>

        </result>

</action>

增删改查CRUD

// 删除:

public String deleteUser(){

    try {

        //验证item.id

        boolean result = userService.deleteUser(item.getId());

        if(result){

            log.info("delete user success,id:{}!!!",item.getId());

            resultMap.put("retcode", RetCode.SUCCESS);

        } else{

            resultMap.put("retcode", RetCode.FAIL);

            resultMap.put("retmsg", "删除失败!");

        }

    } catch (Exception e) {

        log.error("method deleteUser bug:"+e);

        resultMap.put("retcode", RetCode.UNKOWN_WRONG);

        resultMap.put("retmsg", "未知错误!请重试或联系管理员!");

    }

    return SUCCESS;

}

<action name="deleteUser" class="userAction" method="deleteUser">

    <result type="json">

        <param name="root">resultMap</param>

    </result>

</action>

// 增加/修改:

udpateUser.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@ include file="/common/taglibs.jsp" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>编辑/增加用户-${siteName }</title>

${jquery_js } ${jquery_form_js }

</head>

  <body>

    <s:form id="edit_form" action="doUpdateUser" namespace="/user">

        <!-- add:id空值|update:id=item.id -->

<s:hidden id="id" name="item.id"></s:hidden>

        <!-- struts2标签自动取得当前action的值(对象item的值) -->

        用户名:<s:textfield name="item.username"></s:textfield><br/>

        密码:<s:textfield name="item.password"></s:textfield><br/>

        状态:<s:select name="item.status" list="#{1:'正常',2:'禁用' }">

</s:select><br />

        <input type="button" value="保存" id="btnSave" />

    </s:form>

  </body>

</html>

<!-- 先加载body静态页面,再加载js,提升用户体验-->

<script type="text/javascript">

    $(function(){

        $("#btnSave").click(function(){

            var id = $("#id").val();

            var url;

            if(id == ""){

                url = "${ctx}/user/doAddUser.action";

            }else{

                url = "${ctx}/user/doUpdateUser.action";

            }

            //异步提交表单

            var options = {

                url : url,

                success : callback,

                type : 'post',

                dataType : 'json'

            };

            $("#edit_form").ajaxSubmit(options);

        });

    });

    function callback(data){

        alert(data.retmsg);

        if (data.retcode == "0") {

            window.location.href="${ctx}/user/findUsers.action";

        }

    }

</script>

public String toAddUser(){

    return SUCCESS;

}

public String toUpdateUser(){

    try {

        //item.id做验证(设置拦截器,非登陆用户不能操作)

        item = userService.getUserById(item.getId());

        return SUCCESS;

    } catch (Exception e) {

        log.error("method toUpdateUser bug :{}",e);

        return ERROR;

    }

}

public String doAddUser(){

    try {

        // 验证item

        item.setCreatetime(new Date());

        userService.addUser(item);

        log.info("add user success,id:{}!!!", item.getId());

        resultMap.put("retcode", RetCode.SUCCESS);

        resultMap.put("retmsg", "增加成功!");

    } catch (Exception e) {

        log.error("method doAddUser bug:" + e);

        resultMap.put("retcode", RetCode.UNKOWN_WRONG);

        resultMap.put("retmsg", "未知错误!请重试或联系管理员!");

    }

        return SUCCESS;

    }

public String doUpdateUser(){

    try {

        //验证item

        boolean result = userService.updateUser(item);

        if(result){

            log.info("udpate user success,id:{}!!!",item.getId());

            resultMap.put("retcode", RetCode.SUCCESS);

            resultMap.put("retmsg", "修改成功!");

        } else{

            resultMap.put("retcode", RetCode.FAIL);

            resultMap.put("retmsg", "修改失败!");

        }

    } catch (Exception e) {

        log.error("method doUpdateUser bug:"+e);

        resultMap.put("retcode", RetCode.UNKOWN_WRONG);

        resultMap.put("retmsg", "未知错误!请重试或联系管理员!");

    }

    return SUCCESS;

}

<action name="toAddUser" class="userAction" method="toAddUser">

    <!-- /WEB-INF目录下只有转发才能访问|安全性 -->

    <result>/WEB-INF/pages/updateUser.jsp</result>

</action>

<action name="toUpdateUser" class="userAction" method="toUpdateUser">

        <result>/WEB-INF/pages/updateUser.jsp</result>

</action>

<action name="doAddUser" class="userAction" method="doAddUser">

    <result type="json">

        <param name="root">resultMap</param>

    </result>

</action>

<action name="doUpdateUser" class="userAction" method="doUpdateUser">

    <result type="json">

        <param name="root">resultMap</param>

    </result>

</action>

public int updateUser(User item) throws DAOException {

    String hql = "update User set username=:username,password=:password

,status=:status where id=:id";

    Map<String, Object> params = new HashMap<String, Object>();

    params.put("username", item.getUsername());

    params.put("password", item.getPassword());

    params.put("status", item.getStatus());

    params.put("id", item.getId());

    return executeUpdate(hql, params);

}

分页和模糊查询

<script type="text/javascript">

    function jump(p,s){

//window.location.href="${ctx}/user/findUsers.action?pager

.currentPage="+p;

    //var oForm = document.searchForm || document.forms[0];

        with(document.searchForm){

            elements["pager.currentPage"].value = p;

            elements["pager.pageSize"].value = s;

            submit();

        }

    }

</script>

<s:form name="searchForm" action="findUsers" namespace="/user">

    <s:hidden name="pager.currentPage"></s:hidden>

    <s:hidden name="pager.pageSize"></s:hidden>

    <table style="width:70%;margin:0 auto;">

        <tr>

<td>用户名:<s:textfield name="item.username"></s:textfield> </td>

<td>密码:<s:textfield name="item.password"></s:textfield> </td>

<td>状态:<s:select name="item.status" headerKey="0"

headerValue="请选择" list="#{1:'正常',2:'禁用' }">

</s:select> </td>

            <td><s:submit value="查询"></s:submit> </td>

        </tr>

    </table>

<hr />

    <table border="1" class="main_table">

    <tr class="head_tr">

         <td>序号</td>

         <td>用户名</td>

         <td>密码</td>

         <td>状态</td>

         <td>角色</td>

         <td>创建时间</td>

            <!-- 取消href默认行为-->

         <td>操作/<a href="javascript:void(0);" class="add">增加</a>

</td>

     </tr>

        <!-- 当前遍历对象临时放入栈顶|根对象 -->

    <s:iterator value="pager.pageRecords" status="s">

    <tr>

         <td><s:property value="(pager.currentPage-1)*pager.pageSize

+#s.index+1" /></td>

         <td><s:property value="username" /></td>

         <td><s:property value="password" /></td>

         <td>

             <s:if test="status == 1">

                 正常

             </s:if>

             <s:else>

                 <span style="color:red">禁用</span>

             </s:else>

         </td>

         <td>

             <s:property value="tbRole.rolename" />

         </td>

         <td>

             <s:date name="createtime" format="yyyy-MM-dd HH:mm:ss" />

         </td>

         <td>

             <a href="javascript:void(0);"class="update" rel=

"<s:property value="id"/>" >修改</a>

             <a href="javascript:void(0);" class="delete" rel=

"<s:property value="id"/>" >删除</a>

         </td>

    </tr>

    </s:iterator>

    </table>

<hr />

</s:form>

<table style="width:98%;margin:0 auto;">

    <tr>

        <td style="text-align: left">

            <span style="color:red"><s:property value=

"pager.currentPage"/></span>/<s:property value="pager.pageCount" />

            <s:property value="pager.total" />

        </td>

        <td style="text-align: right">

            <s:if test="pager.currentPage == 1">

                首页

                上一页                  

            </s:if>

            <s:else>

                <a href="javascript:jump(1,<s:property value=

"pager.pageSize"/>)">首页</a>

                <a href="javascript:jump(<s:property value="pager.currentPage-1"/>,<s:property value="pager.pageSize"/>)">上一页</a>

            </s:else>

            <s:if test="pager.currentPage == pager.pageCount">

                下一页

                末页

            </s:if>

            <s:else>

                <a href="javascript:jump(<s:property value="pager.currentPage+1"/>,<s:property value="pager.pageSize"/>)">下一页</a>

                <a href="javascript:jump(<s:property value="

pager.pageCount"/>,<s:property value="pager.pageSize"/>)">末页</a>

            </s:else>

            转到<s:textfield name="pager.currentPage" id="gPage" cssStyle="width:20px;"></s:textfield>

            <input type="button" value="GO" onclick="jump(document.getElementById('gPage').value,<s:property value="pager.pageSize"/>)" />

            每页显示:<s:select list="#{3:'3',5:'5',10:'10',20:'20' }" name="pager.pageSize" onchange="jump(1,this.value)"></s:select>

        </td>

    </tr>

</table>

/**

* 分页显示数据信息

 */

public Pager<User> getUsersByPage(int currentPage, int pageSize,

    User condition) throws DAOException {

    String hql = "from User where 1=1";

    Map<String, Object> params = new HashMap<String, Object>();

    if(condition != null){

        if(condition.getUsername() != null && !"".equals(

condition.getUsername().trim())){

            hql += " and username like :username";

            params.put("username", "%"

+condition.getUsername().trim()+"%");

        }

        if(condition.getPassword() != null && !"".equals(

condition.getPassword().trim())){

            hql += " and password =:password";

            params.put("password", condition.getPassword().trim());

        }

        if(condition.getStatus() != null && condition.getStatus() != 0){

            hql += " and status =:status";

            params.put("status", condition.getStatus());

        }

    }

    return super.findPager(hql, currentPage, pageSize, params);

}

public String findUsers(){

    try {

        //userList = userService.findAllUsers();

        if(pager == null){

            pager = new Pager<User>();

        }

        pager = userService.getUsersByPage(

pager.getCurrentPage(),pager.getPageSize(), item);

        return SUCCESS;

    } catch (Exception e) {

        log.error("method findUsers bug :{}",e);

        return ERROR;

    }

}

<action name="findUsers" class="userAction" method="findUsers">

    <result>/WEB-INF/pages/userList.jsp</result>

</action>

权限:认证--授权(权限菜单的展示--权限的控制--权限的分配)

多表和基于角色的权限管理:用户--角色--权限(菜单)

tb_user--tb_role|tb_role_right(关联表)|tb_right(菜单)

实体类和映射文件反转生成:右键MyEclipse>添加Hibernate支持

DB Brower>右键表>HibernateReverse>CreateHibernateMappingFile(*.hbm.xml)

tb_user:id(pk) username password status createtime role_id(fk)

tb_role:id(pk) rolename

tb_right:right_code(pk-String|1001>100101) right_title right_url

right_parent_code(ROOT_MENU|1001)

tb_role_right:id(pk) role_id(fk) right_code(fk)

TbUser:

private TbRole tbRole;

@ManyToOne(fetch = FetchType.LAZY)

@JoinColumn(name = "role_id")

public TbRole getTbRole() {

    return this.tbRole;

}

public void setTbRole(TbRole tbRole) {

    this.tbRole = tbRole;

}

<td>角色</td>

<td>

  <-- ManyToOne关联 -->

  <s:property value="tbRole.rolename" />

</td>

web.xml

<!-- 使用Hibernate延迟加载,不会因Session被关闭,导致延迟加载数据异常,等到返回响应后才关闭session -->

    <!-- 一定要在struts2过滤器之前 -->

    <filter>

        <filter-name>hibernateFilter</filter-name>

        <filter-class>

org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

</filter-class>

        <init-param>

            <param-name>sessionFactoryBeanName</param-name>

            <param-value>sessionFactory</param-value>

        </init-param>

        <init-param>

            <param-name>singleSession</param-name>

            <param-value>true</param-value>

        </init-param>

    </filter>

    <filter-mapping>

        <filter-name>hibernateFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

RoleRightImpl:

public List<TbRight> getRightsByRoleId(int roleId) throws DAOException{

String hql = "select rr.tbRight from TbRoleRight rr where

rr.tbRole.id=:roleid";

    Map<String, Object> params = new HashMap<String, Object>();

    params.put("roleid", roleId);

    return super.queryListByHql(hql, params);

}

UserAction:

putToSession("loginUser",item);

putToSession("loginRoleId", item.getTbRole().getId());//存入session

RoleAction:

private List<TbRight> rightList;

public String findCurrentRights(){

    try {

        rightList = roleRightService.getRightsByRoleId(

(Integer)getFromSession("loginRoleId"));//获取session中数据

        resultMap.put("retcode", RetCode.SUCCESS);//存入resultMap

        resultMap.put("rightList", rightList);//避免死循环->排除

    } catch (Exception e) {

        log.error("method login bug:"+e);

        resultMap.put("retcode", RetCode.UNKOWN_WRONG);

        resultMap.put("retmsg", "未知错误!请重试或联系管理员!");

    }

    return SUCCESS;

}

<!-- 排除rightList<TbRole>中的tbRoleRights -->

<action name="findCurrentRights" class="roleAction" method=

"findCurrentRights">

    <result type="json">

        <param name="root">resultMap</param>

        <param name="excludeProperties">

rightList\[\d+\]\.tbRoleRights

</param>

    </result>

</action>

权限菜单展示:dTree目录树

tree.add(id,pid,name,url,title,target,icon,iconOpen,open);

id        :节点自身的id

pid       :节点的父节点的id

name    :节点显示在页面上的名称

url       :节点的链接地址

title     :鼠标放在节点上所出现的提示信息

target   :节点链接所打开的目标frame(如框架目标mainFrame或_blank,_self之类)

icon      :节点关闭时的显示图片的路径

iconOpen :节点打开时的显示图片的路径

open    :布尔型,节点是否打开(默认为false)

注:open项:顶级节点一般采用true,即pid是-1的节点

1:默认值的书写规则(从左至右,依次省略)

即 tree.add(id,pid,name,url);后面5个参数可以省略

2:有间隔时的默认值(如存在第6个参数,但第5个参数想用默认值)即 tree.add(id,pid,name,url,"",target);必须这样写

其它:tree.add(id,pid,name,url,"","","","",true);

dtree.js:

// Tree object

function dTree(objName) {

    this.config = {target:null, folderLinks:true, useSelection:true, useCookies:true, useLines:true, useIcons:true, useStatusText:false, closeSameLevel:false, inOrder:false};

    this.icon = {root:"dtree_/img/doc.gif", folder:"dtree_/img/doc.gif", folderOpen:"dtree_/img/doc.gif", node:"dtree_/img/doc.gif", empty:"dtree_/img/empty.gif", line:"dtree_/images/menu/win/line.gif", join:"dtree_/images/menu/win/join.gif", joinBottom:"dtree_/images/menu/win/joinbottom.gif", plus:"dtree_/images/menu/win/plus.gif", plusBottom:"dtree_/images/menu/win/plusbottom.gif", minus:"dtree_/images/menu/win/minus.gif", minusBottom:"dtree_/images/menu/win/minusbottom.gif", nlPlus:"dtree_/images/menu/win/nolines_plus.gif", nlMinus:"dtree_/images/menu/win/nolines_minus.gif"};

    this.obj = objName;

    this.aNodes = [];

    this.aIndent = [];

    this.root = new Node(-1);

    this.selectedNode = null;

    this.selectedFound = false;

    this.completed = false;

}

<link rel="stylesheet" type="text/css" href="${ctx}/dtree_/dtree.css"/>

<script type="text/javascript" src="${ctx}/dtree_/dtree.js"></script>

<script type="text/javascript">

var d = new dTree("d");//全局初始化

$(function(){

    //发送ajax请求菜单

    var url = "${ctx}/user/findCurrentRights.action";

    $.post(

        url,

        {},

        function(data){

        if(data.retcode =="0"){

            d.add("ROOT_MENU","-1","OA管理系统");

            //each方法遍历(value=rightList中每一项)

            $.each(data.rightList,function(i,value){                                      d.add(value.rightCode,value.rightParentCode

,value.rightTitle,value.rightUrl

,'','rightFrame','','','',0);

            });

            $("#menuDiv").html(d.toString());

            }

        }

    );

});

</script>

<body style="background-color:#0066CC;">

    <div id="menuDiv"></div>

</body>

tb_right表:right_url=user/findUsers.action(可以加一张表CRUD维护url)

权限框架(Shiro|Spring Security):权限控制-权限分配

Apache Shiro:认证Authentication、授权Authorization、加密、会话管理、缓存

http://dl2.iteye.com/upload/attachment/0093/9788/d59f6d02-1f45-3285-8983-4ea5f18111d5.png

ApplicationCode-->Subject(主体)->SecurityManager(安全管理器)->Realm(域)

Shiro不会去维护用户、维护权限;需要去设计/提供;通过Realm注入给Shiro即可。

全注解

DB Brower>右键表>HibernateReverse>AddHibernateMappingAnnotationsJOPO

实体类TbUser:

@Entity

@Table(name = "tb_user")

public class TbUser implements java.io.Serializable

@Id

@GeneratedValue

@Column(name = "id", unique = true, nullable = false)

public Integer getId() {

    return this.id;

}

@ManyToOne(fetch = FetchType.LAZY)

@JoinColumn(name = "role_id")

public TbRole getTbRole() {

    return this.tbRole;

}

@Column(name = "username", length = 20)

public String getUsername() {

    return this.username;

}

dao层:@Repository("userDao")

service层:@Service("userService")

BaseService/BaseService注入:

@Autowired

protected UserDao userDao;

@Autowired

protected UserService userService;

action层:

//spring注解

@Controller("userAction")

@Scope("prototype")

//struts2注解

@Namespace("/user")

@ParentPackage("struts-base")

//struts-admin注解

@Action(value = "ajaxLogin",results = {@Result(name = "success", type="json",params={"root","resultMap"}) })

public String ajaxLogin()

@Action(value = "findUsers",results = {@Result(name = "success" ,location="/WEB-INF/pages/userList.jsp") })

public String findUsers()

@Controller("roleAction")

@Scope("prototype")

@Namespace("/user")//jar包:struts-convention-plugin-2.3.4.1

@ParentPackage("struts-base")

public class RoleAction extends BaseAction

@Action(value = "findCurrentRights",results = {@Result(name = "success",type="json",params={"root","resultMap","excludeProperties","rightList\\[\\d+\\]\\.tbRoleRights"}) })

public String findCurrentRights()

aplicationContext.xml:

<!-- 自动根据名字找注解 -->

<beans xsi: default-autowire="byName">

<!-- 注解扫描 -->

<context:component-scan base-package="com.hfxt.*" />

<!-- sessionFactory -->

    <bean id="sessionFactory"

    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<property name="annotatedClasses">

        <list>

            <value>com.hfxt.entity.TbUser</value>

            <value>com.hfxt.entity.TbRole</value>

            <value>com.hfxt.entity.TbRight</value>

            <value>com.hfxt.entity.TbRoleRight</value>

        </list>

</property>

MyBatis

MyBatis(ibatis):持久化层框架;sql写到专门的配置文件

  1. lib下添加jar包:mybatis-3.1.1.jar
  2. src下添加配置文件mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    <!-- 别名alias -->

    <typeAliases>  

       <typeAlias alias="user" type="com.hfxt.entity.User"/>  

       <typeAlias alias="role" type="com.hfxt.entity.Role"/>  

    </typeAliases>

    <!-- 开发环境 -->

    <environments default="development">

       <environment id="development">

            <!-- 配置数据库连接信息 -->

           <transactionManager type="JDBC"/>

<!--事务管理类型主要有jdbcmanaged,前者依赖于数据源获得的连接,后者依赖于容器 -->

           <!-- POOLED数据库连接池 -->

           <dataSource type="POOLED">

               <property name="driver" value="com.mysql.jdbc.Driver"/>

               <property name="url" value=

"jdbc:mysql://localhost:3306/t38?characterEncoding=utf-8"/>

               <property name="username" value="root"/>

               <property name="password" value="123"/>

           </dataSource>

       </environment>

</environments>

<!-- 引入实体类mapper -->

    <mappers>

        <mapper resource="com/hfxt/mapper/UserMapper.xml" />  

        <mapper resource="com/hfxt/mapper/RoleMapper.xml" />  

    </mappers>

</configuration>

  1. 创建实体类及SQL映射文件(CRUD):sql语句--方法映射文件

com.hfxt.mapper.UserMapper.xml-RoleMapper.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- UserDao接口的完全限定名 命名空间唯一 -->

<mapper namespace="com.hfxt.dao.UserDao">

    <!-- 映射sql语句 idUserDao接口中方法名相同可省略实现类  -->

    <select id="getAllCount" resultType="int">

        select count(*) from tb_user

    </select>

    <!-- <select id="getAllUsers" resultType="user">

        select

            id as id,

            username as username,

            password password,

            status as status,

            createtime as createtime,

            role_id roleId

        from tb_user

    </select> -->

    <!-- <select id="getAllUsers" resultMap="rm_users">

        select * from tb_user

    </select> -->

    <!-- 多表:内联查询 -->

    <select id="getAllUsers" resultMap="rm_users">

        select a.*,b.rolename from tb_user a

        inner join tb_role b

        on a.role_id=b.id

    </select>

    <!-- 模糊查询

    <select id="getUsers" resultMap="rm_users" parameterType="user">

        select * from tb_user where 1=1

        <if test="username != null">

            and username like '%${username}%'

        </if>

        <if test="password != null">

            and password = #{password}

        </if>

        <if test="status != null">

        and status = #{status}

        </if>

        <if test="roleId != null">

            and role_id = #{roleId}

        </if>

    </select> -->

    <!-- 模糊查询常用写法 -->

    <select id="getUsers" resultMap="rm_users" parameterType="user">

        select * from tb_user

        <where>

            <if test="username != null">

                and username like '%${username}%'

            </if>

            <if test="password != null">

                and password = #{password}

            </if>

            <if test="status != null">

            and status = #{status}

            </if>

            <if test="roleId != null">

                and role_id = #{roleId}

            </if>

        </where>

    </select>

    <insert id="addUser" parameterType="user">

        <!--  oracle序列

        <selectKey keyProperty="id" resultType="int" order="BEFORE">

            select seq_user.nextval from dual

        </selectKey> -->

        insert into tb_user(username,password,status,createtime,role_id)

        values(#{username},#{password},#{status},now(),#{roleId})

    </insert>

    <update id="updateUser" parameterType="user">

        update tb_user

        <set>

            <if test="username != null">

                username=#{username},

            </if>

            <if test="password != null">

                password=#{password},

            </if>

            <if test="status != null">

                status=#{status},

            </if>

            <if test="roleId != null">

                role_id=#{roleId},

            </if>

        </set>

         where id=#{id}

    </update>

    <delete id="deleteUser" parameterType="int">

        delete from tb_user where id=#{id}

    </delete>

    <!-- 字段名与属性名映射-->

    <resultMap type="user" id="rm_users">

        <id column="id" property="id" />

        <result column="username" property="username" />

        <result column="password" property="password" />

        <result column="status" property="status" />

        <result column="createtime" property="createtime" />

        <result column="role_id" property="roleId" />

        <!-- 多对一(不常用)

        <collection property="role" column="role_id" select="com.hfxt.dao.RoleDao.getRoleById"></collection> -->

        <result column="rolename" property="rolename" />

    </resultMap>

</mapper>

<mapper namespace="com.hfxt.dao.RoleDao">

    <select id="getRoleById" resultMap="rm_roles" parameterType="int">

        select * from tb_role where id=#{id}

    </select>

    <resultMap type="role" id="rm_roles">

        <id column="id" property="id" />

        <result column="rolename" property="rolename" />

    </resultMap>

</mapper>

  1. 编写实体类及测试类:UserDao(User)--RoleDao(Role):

private Integer id;

private String username;

private String password;

private Integer status;

private Date createtime;

private Integer roleId;

private String rolename;//业务字段

//private Role role;//多对一

public interface UserDao {

    public int getAllCount();

    public List<User> getAllUsers();

    public List<User> getUsers(User condition);

    public int addUser(User item);

    public int updateUser(User item);

    public int deleteUser(int id);

}

private Integer id;

private String rolename;

public interface RoleDao {

    public Role getRoleById(int id);

}

  1. 测试类Test--MD5UtilMD5加密解密

public class MD5Util {

    /***

     * MD5加码 生成32md5

     */

    public static String string2MD5(String inStr) {

        MessageDigest md5 = null;

        try {

            md5 = MessageDigest.getInstance("MD5");

        } catch (Exception e) {

            System.out.println(e.toString());

            e.printStackTrace();

            return "";

        }

        char[] charArray = inStr.toCharArray();

        byte[] byteArray = new byte[charArray.length];

        for (int i = 0; i < charArray.length; i++)

            byteArray[i] = (byte) charArray[i];

        byte[] md5Bytes = md5.digest(byteArray);

        StringBuffer hexValue = new StringBuffer();

        for (int i = 0; i < md5Bytes.length; i++) {

            int val = ((int) md5Bytes[i]) & 0xff;

            if (val < 16)

                hexValue.append("0");

            hexValue.append(Integer.toHexString(val));

        }

        return hexValue.toString();

    }

    /**

     * 加密解密算法 执行一次加密,两次解密

     */

    public static String convertMD5(String inStr) {

        char[] a = inStr.toCharArray();

        for (int i = 0; i < a.length; i++) {

            a[i] = (char) (a[i] ^ 't');

        }

        String s = new String(a);

        return s;

    }

    // 测试主函数

    public static void main(String args[]) {

        String s = new String("aaa");

        System.out.println("原始:" + s);

        System.out.println("MD5后:" + string2MD5(s));

        System.out.println("加密的:" + convertMD5(s));

        System.out.println("解密的:" + convertMD5(convertMD5(s)));

    }

}

public static void main(String[] args) {

    SqlSession session = null;

    try {

        Reader reader = Resources.getResourceAsReader(

"mybatis-config.xml");

       SqlSessionFactoryBuilder builder = new

SqlSessionFactoryBuilder();

        SqlSessionFactory sessionFactory = builder.build(reader);

        session = sessionFactory.openSession();

        UserDao userDao = session.getMapper(UserDao.class);

        /*int count = userDao.getAllCount();

        System.out.println(count);*/

        /*List<User> list = userDao.getAllUsers();

        for(User user : list){

            System.out.println(user.getUsername()+user.getRoleId());           }*/

        /*增加

        User item = new User();

        item.setUsername("sb");

        item.setPassword(MD5Util.string2MD5("123"));//MD5加密

        item.setStatus(1);

        item.setRoleId(1);

        int count = userDao.addUser(item);

        session.commit();

        System.out.println(count);*/

        /*修改

        User item = new User();

        item.setId(12);

        item.setPassword(MD5Util.string2MD5("abc"));

        session.commit();

        int count = userDao.updateUser(item);

        System.out.println(count);*/

        /*删除

        int count = userDao.deleteUser(13);

        session.commit();

        System.out.println(count);*/

        /*模糊查询条件

        User condition = new User();

        condition.setUsername("a");

        condition.setPassword("123");

        List<User> list = userDao.getUsers(condition);

        for(User user : list){

            System.out.println(user.getUsername()+"||"+user.getRoleId());

        }*/

        //多表连接

        List<User> list = userDao.getAllUsers();

        for(User user : list){

        //System.out.println(user.getUsername()+"||"

+user.getRole().getRolename());

System.out.println(user.getId()+"||"+user.getUsername()

+"||"+user.getRolename() );

        }

    } catch (IOException e) {

        e.printStackTrace();

    } finally{

        session.close();

    }

}

springMVC

spring MVCSpringFrameWork后续产品+实现Web MVC设计模式的请求驱动类型的轻量级Web框架;分离了控制器、模型对象、分派器以及处理程序对象的角色

实现步骤:http://localhost:8080/ssm1/hello->核心控制器(拦截所有请求)>加载

springmvc.xml->HelloController(/Hello)>return "hello"->/WEB-

INF/page/hello.jsp

Spring MVC配置步骤:

  1. 添加jar(spring)mvcaopcore相关包
  2. web.xml中添加核心控制器

<!-- springmvc -->

<servlet>

<servlet-name>spring</servlet-name>

<servlet-class>

org.springframework.web.servlet.DispatcherServlet

</servlet-class>

<!-- 不在WEB-INF目录下或以springServlet命名,需添加的参数 -->

<init-param>

<param-name>contextConfigLocation</param-name>

        <param-value>classpath*:springmvc.xml</param-value>

</init-param>

<!-- 服务器启动就初始化 -->

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>spring</servlet-name>

<!-- 拦截所有请求 -->

<url-pattern>/</url-pattern>

</servlet-mapping>

  1. 配置文件spring-mvc.xml

<!--

    1。配置action,实现controler接口

    2。配置映射处理器,用来处理请求与action的映射,可以不用写id,

    3。配置视图解析器:完成ModelAndView的解析

-->

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:context="http://www.springframework.org/schema/context"

        xmlns:tx="http://www.springframework.org/schema/tx"

        xmlns:aop="http://www.springframework.org/schema/aop"

        xmlns:p="http://www.springframework.org/schema/p"

        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd

                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd

                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- 扫描(注解的Controller) -->

    <context:component-scan base-package="com.hfxt.web.controller" />

    <!-- 视图解析 -->

    <bean id="viewResolver"class="org.springframework.web.servlet

.view.InternalResourceViewResolver"

     p:prefix="/WEB-INF/page/" p:suffix=".jsp" />

</beans>

  1. com.hfxt.web.controller

HelloController

@Controller

public class HelloController {

    /*@RequestMapping("/hello")

    public String sayHello(ModelMap map){

        map.put("message", "这是我的第一个springmvc的项目");

        return "hello";

    }*/

    @RequestMapping("/hello")

    public ModelAndView sayHello(){

        ModelAndView mv = new ModelAndView();

        mv.addObject("message", "这是我的第一个springmvc的项目");

        mv.setViewName("hello");

        return mv;

    }

}

UserController:

@Controller

public class UserController {

    @RequestMapping(value="/login",method=RequestMethod.GET)

    public String toLogin(){

        return "login";

    }

    @RequestMapping(value="/login",method=RequestMethod.POST)

    //接收请求参数:名字一样自动填充

    //public String doLogin(@RequestParam("username") String

username,@RequestParam("password") String password){

    //public String doLogin(String username,String password){

    public String doLogin(String username,String password

,HttpSession session){

        if("admin".equals(username) && "123".equals(password)){

            //session存值

            session.setAttribute("loginUser", username);

            return "success";

        }else{

            return "login";

        }

    }

}

  1. WEB-INF/page/hello.jsp|login.jsp|success.jsp

<body>

    ${message }

</body>

<form action="login" method="post">

    用户名:<input type="text" name="username" /><br />

    密码:<input type="password" name="password" /><br />

    <input type="submit" value="登陆" />

</form>

<body>

    登陆成功!欢迎您${sessionScope.loginUser }

</body>

SSM

SSM框架整合MyBatis+Spring+SpringMVC

Spring+myBatis整合:新建项目并导入jar>配置mybatis-config.xml>创建库及表>创建实体>编写映射文件,修改mybatis-config.xml内容>进行简单测试

整合springmvc: 添加spring-mvc.xml>修改web.xml文件,加入springmvc相关信息>编写控制器类及相关jsp文件

  1. com.hfxt.mapper. UserMapper.xml>UserDao>UserSerive>UserServiceImpl

<select id="getUserByUsername" parameterType="String"

resultMap="rm_users">

    select * from tb_user where username=#{username}

</select>

public User getUserByUsername(String username);

@Service("userService")

public class UserServiceImpl implements UserService {

    @Autowired

    private UserDao userDao;

    @Override

    public User checkLogin(String username, String password) {

        User user = userDao.getUserByUsername(username);

        if(user != null && user.getPassword().equals(password)){

            return user;

        }

        return null;

    }

}

  1. applicationContext.xml(类中采用注解注入对象)

<!-- 扫描dao/service -->

<context:component-scan base-package="com.hfxt.service,com.hfxt.dao" />

<context:property-placeholder location="classpath:jdbc.properties" />

<!-- 数据源c3p0 -->

<bean id="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="driverClass" value="${jdbc.driverClassName}" />

<property name="jdbcUrl" value="${jdbc.url}" />

<property name="user" value="${jdbc.username}" />

  <property name="password" value="${jdbc.password}" />

<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />

<property name="minPoolSize" value="${jdbc.minPoolSize}" />

<property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>

</bean>

<!-- sessionFactory springmybatis整合

   <description>

        SpringMybatis相关的配置文件

        typeAliasesPackage:可以配置多个,','号分隔

        basePackage:可以配置多个,','号分隔

    </description> -->

<bean id="sqlSessionFactory" class="org.mybatis.spring.

SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<!-- 加载Mapper -->

<property name="mapperLocations">

<list>

<value>classpath*:com/hfxt/mapper/*Mapper.xml</value>

        </list>

</property>

    <!-- 实体类前缀(实体域domain,这里是entity) -->

    <property name="typeAliasesPackage" value="com.hfxt.entity" />

</bean>

<!-- Mybatisspring整合 -->

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

    <property name="basePackage" value="com.hfxt.dao" />

    <property name="sqlSessionFactoryBeanName"

value="sqlSessionFactory" />

</bean>

  1. com.hfxt.web.controller. UserController>spring_mvc.xml

@Controller

public class UserController {

    @Autowired

    private UserService userService;

    @RequestMapping(value="/login",method=RequestMethod.GET)

    public String toLogin(){

        return "login";

    }

    @RequestMapping(value="/login",method=RequestMethod.POST)

    public String login(User item,HttpSession session){

        User user = userService.checkLogin(item.getUsername()

,item.getPassword());

        if(user != null){

            session.setAttribute("loginUser", user);

            return "success";

        }else{

            return "login";

        }

    }

    //ajax请求

    @ResponseBody

//取得?id=1的值

    public Map<String, Object> doAjaxLogin(@PathVariable("id") int

id,User item,HttpSession session){

        Map<String, Object> modelMap = new HashMap<String, Object>();

        item = userService.checkLogin(item.getUsername()

,item.getPassword());

        if(item != null){

            session.setAttribute("loginUser", item);

            modelMap.put("retcode", "0");//返回json数据

        }else{

            modelMap.put("retcode", "101");

        }

        return modelMap;

    }

}

<!-- 扫描 -->

<context:component-scan base-package="com.hfxt.web.controller" />

<!-- 视图解析 -->

<bean id="viewResolver" class="org.springframework.web.servlet

.view.InternalResourceViewResolver"

p:prefix="/WEB-INF/page/" p:suffix=".jsp" />

  1. web.xml:

<!-- spring -->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:*Context.xml</param-value>

</context-param>

<listener>

    <listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

<!-- 中文过滤器  -->

<filter>

    <filter-name>encodingFilter</filter-name>

    <filter-class>

org.springframework.web.filter.CharacterEncodingFilter

</filter-class>

<init-param>

    <param-name>encoding</param-name>

    <param-value>UTF-8</param-value>

    </init-param>

<init-param>

    <param-name>forceEncoding</param-name>

    <param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

    <filter-name>encodingFilter</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

   <!-- springmvc -->

<servlet>

<servlet-name>spring</servlet-name>

    <servlet-class>

org.springframework.web.servlet.DispatcherServlet

</servlet-class>

    <init-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>classpath*:springmvc.xml</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>spring</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

  1. WEB-INF/page/login.jsp|success.jsp:

<form action="login" method="post">

    <!-- springmvc:属性与name相同自动填充 -->

    用户名:<input type="text" name="username" /><br />

    密码:<input type="password" name="password" /><br />

    <input type="submit" value="登陆" />

</form>

<body>

登陆成功!欢迎您${sessionScope.loginUser.username }

</body>

 

项目开发

项目生命周期需求分析(功能)>项目设计(数据库设计|系统架构设计)>代码(编码规范)>测试>实施部署(部署|试运行|运行)>验收(初验|中验|终验)

    数据库设计:设计库、表、表关系

    系统架构设计:开发(CRUD基本业务-公用类-公用组件-平台开发-面向解决方案开发)

项目结构(分层、应用组件及版本、工具类)

开发规范与约定:软件框架版本-开发环境-包约定-页面约定-数据库规范-分层约定

    框架(SSH/SSM)-软件技术(Junit/JQuery/EasyUI/SVN/Maven)

    开发环境:OS-JDK-IDE(MyEclipse)-数据库(MySQL)-Web容器(Tomcat)

    页面约定:JSP/CSS/JS、前端JSTL标签、权限页面放在WEB-INF下

    数据库约定:编码UTF-8、不要设置自定义/非空/外键约束、sql语句完整

    分层约定:控制层调Service,Service调Dao、层与层之间用接口、数据传输对象

web>控制层>业务层>Dao

SSH:dao/dao.impl-service/service.impl-action-model-util-interceptor-listener-filter

SSM:dao/dao.impl-service/service.impl-controller-entity-util-listener -interceptor

代码生成工具codesmithMybatis Genertor

设置:Tools->Options...->Studio->Editor->Enable unicode->显示中文

模板说明区域-属性设置区域-注册模板区域-引用声明区域-模板区域-函数区域

  1. 创建一个命令行应用solution
  2. CodeSmith的Schema Explorer>添加一个MySQL数据源(Connection String: SERVER=localhost;DATABASE=sales;UID=username;PASSWORD=password;)
  3. 当前solution添加一个Sales Data Class Library,然后在项目中添加一个CodeSmith 项目Item
  4. 分别添加三个模板,SourceDatabase 选择Schema Explorer 中添加的Sales数据库,其它属性使用缺省值>Sales.csp的Generate.code生成代码

Hbms(生成hbm.xml映射文件)、Entities(生成和数据库表对应的.Net类定义)、Queries(生成查询数据对应的类)

svn版本控制工具: git工具(开源的分布式版本控制系统)

组长--搭好框架--> svn服务器-->组员(检出checkout-更新update-提交commit)

  1. 安装MyEclipse插件:MyEclipse安装位置->拷贝svn.link

(path=D:\\Java\\myplugins\\svn)->SVN资源库->新建资源库位置(项目url)

trunk目录-->导入项目(递归子目录)--检出为->Team更新->提交(去除/classes)

  1. 客户端工具:安装TortoiseSVN->右键SVNCheckout--设置项目url/trunk和项目目录->导入MyEclipse->SVNUpdate-SVNCommit(默认不勾选/classes目录)

右键TortoiseSVN>Showlog(查看历史纪录)-Show Conflict(代码冲突)

Maven:项目构建工具和管理jar包

Maven安装配置:eclipse必须添加一个支持maven插件m2eclipse

  1. 解压缩->配置环境变量

新建系统变量MAVEN_HOME 变量值:D:\Java\apache-maven-3.3.9

编辑系统变量Path  添加变量值:;%MAVEN_HOME%\bin

测试:mvn -v

  1. maven目录下config>settings.xml(配置jar包下载路径:<localRepository>

D:\Java\apache-maven-3.3.9\repos</localRepository>)

  1. MyEclipse配置插件->preferences>Maven4MyEclipse配置settings.xml和maven目录
  2. 新建MavenProject>选择模板(*-webapp)>GroupId|项目名|version

源文件夹:main/resources main/java test/resources test/java main/webapp

配置文件pom.xml:镜像nexus(代理下载包)

<!-- maven repository(jar包仓库)下载 -->

    <dependency>

     <groupId>junit</groupId>

    <artifactId>junit</artifactId>

     <version>4.10</version>

    </dependency>

  1. 运行项目:jetty插件

MyEclipse安装位置>jetty放在dropins目录下>Run配置JettyWebApp>改Context:/t38

<build>

<finalName>t38</finalName>

<plugins>

<!-- jetty插件 -->

<plugin>

<groupId>org.mortbay.jetty</groupId>

            <artifactId>maven-jetty-plugin</artifactId>

            <version>6.1.5</version> 

            <configuration> 

              <webAppSourceDirectory>

src/main/webapp

</webAppSourceDirectory>

                <scanIntervalSeconds>3</scanIntervalSeconds> 

                <contextPath>/t38</contextPath> 

                <connectors> 

                  <connector implementation="

org.mortbay.jetty.nio.SelectChannelConnector">

                       <port>8080</port>

                    </connector>

                 </connectors>

            </configuration>

</plugin>

</plugins>

</build>

WebService

WebService:一个部署在Web服务器上的一个应用程序,它向外界暴露出一个能够通过Web进行调用的API

Soap(XML)+WSDL+HTTP

客户端(调用Web Service的应用程序)-服务器(发布web Service服务)

跨平台调用-跨语言调用-可远程调用

webservice 调用方式(3)httpget-httppost-httpsoap

CXF开发Web Service服务端:

1.新建 项目(这里用scm 环境)

2.导入cxf相关jar

asm-3.3.jar

aopalliance-1.0.jar

jett*-1.3.jar(jett开头的多个jar)

spring*.RELEASE(spring开头的多个jar)

3.修改web.xml文件

<servlet>

<servlet-name>cxf</servlet-name>

<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>cxf</servlet-name>

<url-pattern>/ws/*</url-pattern>

</servlet-mapping>

4.新建服务类:添加@WebService注解,代表发布一个WebService服务;类中所有的静态、final、非公有的方法都将不会对外公布@WebMethod(exclude=true),阻止对外公开

@WebService

@Component("accountReportWs")

public class AccountReportWs {

@Resource

private AccountRecordsService accountRecordsService;

//json数据,再自己组装成map对象

public String selectSupplier(String json){

System.out.println("json:"+json);

ObjectMapper mapper = new ObjectMapper();

try {

Map<String,String> map = mapper.readValue(json, HashMap.class);

List<Map<String, Object>> selectSupplier = accountRecordsService.selectSupplier(map);

//结果组装成json字符串

String returnJson = mapper.writeValueAsString(selectSupplier);

System.out.println("returnjson:"+returnJson);

return returnJson;

} catch (Exception e) {

e.printStackTrace();

return "exception:"+e.getMessage();

}

//return "nothing";

};

}

5. 配置applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>

<beans

    xmlns:jaxws="http://cxf.apache.org/jaxws"

xsi:schemaLocation=

    http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd

    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

<!--采用注解,不采用配置   <bean id="accountRecordsWebService" class="cn.xxx.service.impl.AccountRecordsServiceImpl" />  --> 

<!-- id:逻辑名  serviceClass=服务接口类  address:调用的路径,如下可以使用 http://localhost:8080/项目名/ws/hello?wsdl>,其中ws资源路径在web.xmlservlet中配置 -->

    <jaxws:server id="arws" serviceClass="cn.itcast.ws.AccountReportWs" address="/hello">

        <jaxws:serviceBean>

<!--采用注解的相关bean -->

            <ref bean="accountReportWs" />

        </jaxws:serviceBean>

    </jaxws:server>

6.启动服务器,发布web服务

CXF开发Web Service客户端:

1.新建项目

2.使用wsimport生成客户端代码

wsimport -s . -p cn.xxx.demo5 xxx.sss.xxx?WSDl

3.把代码存放到项目中

4.添加接口

public interface WsClient {

  public String selectSupplier(String json) ;

}

5.添加客户端调用实现类

@Component("wsClient")

public class WsClientImpl implements WsClient  {

private AccountReportWs getAccountReportWs(){

AccountReportWsService accountReportWsService  = new AccountReportWsService();

return accountReportWsService.getAccountReportWsPort();

}

public String selectSupplier(String json) {

System.out.println("clientimpl.json:"+json);

//WsClientImpl wsClientImpl = new WsClientImpl();

//String json = "{\"start\":\"2010-10-10\",\"end\":\"2016-09-09\"}";

String returnJson = getAccountReportWs().selectSupplier(json);

return returnJson;

}

}

6.修改控制类

@Controller

@RequestMapping(value="/accountRecords")

public class AccountRecordsAction extends BaseAction {

@Resource

private AccountRecordsService accountRecordsService;

@Resource

private WsClient wsClient;

@RequestMapping(value="/selectSupplier")

@ResponseBody

public Object selectSupplier(String start,String end){

System.out.println("start:"+ start+"||end:"+end);

//组装json数据

String json = "{\"start\":\""+start+"\",\"end\":\""+end+"\"}";

String returnJson= wsClient.selectSupplier(json);

return returnJson;

}

}

猜你喜欢

转载自blog.csdn.net/ftmy_c/article/details/81210387
今日推荐