论坛首页 Java企业应用论坛

SSH框架注解版整合搭建图文教程

浏览 1358 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2019-06-03  

文章转载自:https://www.jiweichengzhu.com/article/68df4c127c2a491bb6f7056e970318d5

如果还有问题,加群交流:686430774

案例代码下载,请移步原文链接!

SSH框架用起来还是可以的,但配置也蛮多,struts一堆配置,hibernate一堆配置,spring更不用说也是一堆配置,还好各个框架的设计团队都意识到了这个问题,都在朝着这方面而努力,在后续的版本中,都推出了注解配置,方便了很多。

之前的笔记中也有关于ssh框架的注解版,整理出来分享给大家,由于前面讲过了ssh配置版,描述的比较详细了,这一次就不再重复讲解了,只将我认为一些关键的地方贴出来着重说明一下。

除了spring的版本保持不变,另外两个框架都稍微提升了几个小版本:

Struts版本:2.3.24

Spring版本:4.1.5.RELEASE

Hibernate版本:4.3.10.Final

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>

    <!-- 配置为开发模式 -->
    <constant name="struts.devMode" value="true"/>
    <!-- 将对象交给spring管理 -->
    <!-- 此时可以不用在applicationContext.xml中生命bean了,直接从action就可以注入进去 -->
    <constant name="struts.objectFactory" value="spring"/>
    <!-- 确定搜索包的路径(坑死:一定记得加上这句啊,默认只扫描以action命名的包) -->
    <constant name="struts.convention.package.locators" value="controller"/>

</struts> 

后两个配置需要重点关注,由于使用注解了,那我们就不再需要手动声明bean来注入对象了,直接交给spring来管理就行,而没了配置文件,struts的@Namespace也需要使用注解来声明,在这里要指定@Namespace注解所在的包名,默认是action,如果你跟我一样习惯性写controller,千万记得在这里指定,我当时被坑了好久。

applicationContext.xml

 

<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 	http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
 	http://www.springframework.org/schema/tx 
 	http://www.springframework.org/schema/tx/spring-tx-4.1.xsd 
 	http://www.springframework.org/schema/context
 	http://www.springframework.org/schema/context/spring-context-4.1.xsd">

    <!-- 开启注解并扫描   -->
    <!-- <context:annotation-config /> -->
    <!-- 开启注解并扫描,并指定扫描目录(有下面这一句,上面那句就可以省略) -->
    <context:component-scan base-package="com.ssh"/>

    <!-- 数据源 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true"/>
        <property name="username" value="test"/>
        <property name="password" value="111111"/>
    </bean>

    <!-- hibernate使用注解的方式 -->
    <!-- 可以使用@Column、@OneToOne、@DateTimeFormat、@JsonSerialize等注解 -->
    <!-- @JoinColumn(name = "关联字段", unique = true) -->
    <!-- @OneToOne(targetEntity = 关联实体bean.class) -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 注解方式,下面这句一定要加上,不然扫描不到实体bean -->
        <property name="packagesToScan" value="com.ssh.entity"/>
        <!-- 在这里配置了xml映射文件的位置,就不需要在hibernate.cfg.xml中配置了 -->
        <!-- <property name="mappingLocations" value="classpath:com/ssh/entity/*.hbm.xml"/> -->
        <!-- 配置sql格式化、dialect等属性 -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="hibernate.autoReconnect">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <!-- hibernate使用配置文件的方式 -->
    <!--
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
                <prop key="hibernate.autoReconnect">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
        直接将配置文件写在spring配置中
        <property name="mappingResources">
            <list>
                <value>com/ssh/entity/Book.hbm.xml</value>
                <value>com/ssh/entity/School.hbm.xml</value>
                <value>com/ssh/entity/Student.hbm.xml</value>
            </list>
        </property>
        引用外部配置文件

        <property name="configLocations">
           <list>
               <value>classpath:hibernate.cfg.xml</value>
           </list>
       </property>

    </bean>
    -->

    <!-- 将hibernateTemplate交由Spring管理,以便使用注解的方式进行调用 -->
    <!-- 否则,需要在dao层继承hibernateDaoSupport,使用的时候需要调用getHibernateTemplate()方法 -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 事务管理 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 开启@Transactional注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

 

spring的这个配置文件中,关于hibernate的配置,与之前相比有了两个变化:不用引入映射文件需要扫描实体bean,因为使用了注解模式,可以不需要那些映射文件了,直接在bean使用注解来取代xml。

JavaBean注解:

package com.ssh.entity;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.format.annotation.DateTimeFormat;

@Entity // 表明是一个实体bean
@Table(name = "students") // 对应数据库的表名字
public class Student {

    /**
     * ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)// 数据库自增,这句加不加无所谓
    //如果使用的是oracle数据库,需要使用自增序列,可以使用下面两行注解配置
    //@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_student")
    //@SequenceGenerator(name = "seq_student", sequenceName = "ZZ_STUDENTS", allocationSize = 1)
    private int id;

    /**
     * 姓名
     */
    @Column(name = "student_name", nullable = false, length = 25)
    private String name;

    /**
     * 性别
     */
    @Column(name = "student_sex", nullable = false, length = 5)
    private String sex;

    /**
     * 年龄
     */
    @Column(name = "student_age", nullable = false, length = 5)
    private int age;

    /**
     * 生日
     */
    @Column(name = "student_birthday")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birthday;

    /**
     * 爱好
     */
    @Column(name = "student_hobby", nullable = false, length = 50)
    private String hobby;

    /**
     * 学校(schoolId关联)
     */
    // xml配置方式的一对一,就是参照这里的注解方式
    // 多方(主动方)加关联,并限定唯一从而达到一对一效果,一方(被动方)则不用加配置
    @JoinColumn(name = "school_id", unique = true)
    @ManyToOne(targetEntity = School.class, fetch = FetchType.EAGER)
    // 上面两个注解的效果,等同于下面的配置
    // <many-to-one name="school" column="school_id" unique="true" lazy="false"/>
    private School school;

    public Student() {

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    public School getSchool() {
        return school;
    }

    public void setSchool(School school) {
        this.school = school;
    }

}
 

可以看到,很多在xml中的配置,都以注解的形式表现出来了,@Id、@Column、@ManyToOne等等,语义也都清晰,一眼看过去就知道是什么意思,代码中的注释写的比较全,这里不在多说。

Controller控制器:

package com.ssh.controller;

import com.ssh.entity.School;
import com.ssh.service.SchoolService;
import java.util.List;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

@Controller// spring托管
@Scope("prototype")// 多例
@Namespace("/schoolManage")// 对应配置文件中的每个action的name
@ParentPackage("struts-default")// 对应配置文件中的:<package name="default" extends="struts-default">
public class SchoolController extends BaseController {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    // 由于bean配置了spring托管,所以这里可以直接使用注解注入
    @Autowired
    private SchoolService schoolService;

    /**
     * list列表
     */
    private List<School> list;
    /**
     * 实体bean
     */
    private School school;

    @Action(value = "school_list", results = {@Result(name = "list", location = "/school_list.jsp")})
    public String list() {
        list = schoolService.list(searchText);
        return "list";
    }

    @Action(value = "school_toAdd", results = {@Result(name = "add", location = "/school_maintain.jsp")})
    public String toAdd() {
        type = "add";
        return "add";
    }

    @Action(value = "school_add", results = {@Result(name = "refresh", type = "redirect", location = "/schoolManage/school_list.action")})
    public String add() {
        schoolService.add(school);
        return "refresh";
    }

    @Action(value = "school_toUpdate", results = {@Result(name = "update", location = "/school_maintain.jsp")})
    public String toUpdate() {
        type = "update";
        school = schoolService.getById(id);
        return "update";
    }

    @Action(value = "school_update", results = {@Result(name = "refresh", type = "redirect", location = "/schoolManage/school_list.action")})
    public String update() {
        schoolService.update(school);
        return "refresh";
    }

    @Action(value = "school_delete", results = {@Result(name = "refresh", type = "redirect", location = "/schoolManage/school_list.action")})
    public String delete() {
        schoolService.delete(id);
        return "refresh";
    }

    // 感觉这也是struts非常不爽的地方
    // 前台需要用到的变量总是需要set、get一下才行,springMVC中就不需要
    public List<School> getList() {
        return list;
    }

    public void setList(List<School> list) {
        this.list = list;
    }

    public School getSchool() {
        return school;
    }

    public void setSchool(School school) {
        this.school = school;
    }

}
 

在控制器头部加了一堆的注解,有指定spring托管的,有配置作用域的,有配置namespace的,大家直接看我上面写的注释就行。

基本上需要注意的一些点都列出来了,还是比较简单的,再给大家来一张工程目录结构图:

SSH框架注解版搭建图文教程

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics