Spring+SpringMVC+Mybatis SSM整合——简单的HelloWorld

一、导包

1)Spring

【AOP核心】

com.springsource.net.sf.cglib-2.2.0.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

spring-aspects-4.0.0.RELEASE.jar

【IOC核心包】

commons-logging-1.1.3.jar

spring-aop-4.0.0.RELEASE.jar

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-expression-4.0.0.RELEASE.jar

【jdbc核心】

spring-jdbc-4.0.0.RELEASE.jar

spring-orm-4.0.0.RELEASE.jar

spring-tx-4.0.0.RELEASE.jar

【测试包】

spring-test-4.0.0.RELEASE.jar

2)SpringMVC

【SpringMVC核心包】

spring-web-4.0.0.RELEASE.jar

spring-webmvc-4.0.0.RELEASE.jar

【文件上传下载包】

commons-fileupload-1.2.1.jar

commons-io-2.0.jar

【jstl java标准标签库】

jstl.jar

standard.jar

【数据校验包】

hibernate-validator-5.0.0.CR2.jar

hibernate-validator-annotation-processor-5.0.0.CR2.jar

classmate-0.8.0.jar

jboss-logging-3.1.1.GA.jar

validation-api-1.1.0.CR1.jar

【ajax包】

jackson-annotations-2.1.5.jar

jackson-core-2.1.5.jar

jackson-databind-2.1.5.jar

【验证码包】

kaptcha-2.3.2.jar

3)Mybatis

【Mybatis核心包】

mybatis-3.4.1.jar

【Mybatis和Spring的整合包】

mybatis-spring-1.3.0.jar

【ehcache整合】

ehcache-core-2.6.8.jar

log4j.jar

mybatis-ehcache-1.0.3.jar

slf4j-api-1.6.1.jar

slf4j-log4j12-1.6.2.jar

【mysql数据源、数据库驱动包】

mysql-connector-java-8.0.21.jar

c3p0-0.9.1.2.jar

【junit单元测试包】

hamcrest-core-1.3.jar

junit-4.12.jar

二、写配置

1)applicationContext-mvc.xml

①只扫描标了Controller注解的组件

<context:component-scan base-package="com.philshao" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

②配置视图解析器,用于拼接控制器返回的结果字符串,形成完整的文件名

<bean id="internalResourceViewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--   配置前缀和后缀  -->
    <property name="prefix" value="/pages/"/>
    <property name="suffix" value=".jsp"/>
</bean>

③扫描静态资源

<mvc:default-servlet-handler></mvc:default-servlet-handler>

扫描动态资源

<mvc:annotation-driven></mvc:annotation-driven>

④由于springmvc上下文默认没有配置文件上传解析器,所以需要自己配置,在dispatcher组件multipartResolver进行初始化时,从ioc容器中使用id=multipartResolver进行获取。

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="UTF-8"/>
    <!--配置上传文件的最大size为20M-->
    <property name="maxUploadSize" value="#{1024*1024*20}"/>
</bean>

2)applicationContext.xml

①spring只关注业务逻辑组件,所以只扫描除Controller以外的其余组件

<context:component-scan base-package="com.philshao">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>

②导入外部数据库连接配置文件dbconfig.properties

<context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>
#dbconfig.properties
jdbc.username=root
jdbc.password=12345678
jdbc.url=jdbc:mysql:///test
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.maxPoolSize=20
jdbc.minPoolSize=5

然后,配置数据源,这里使用的是开源的jdbc数据库连接池 c3p0

<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
    <property name="driverClass" value="${jdbc.driverClass}"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
    <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
</bean>

③配置使用mybatis操作数据库,这里使用到了mybatis和spring的整合包 mybatis-spring-1.3.0.jar

以配置的方式,将mybatis中的sqlSessionFactory放入ioc容器中,sqlSessionFactory可以由其工厂类org.mybatis.spring.SqlSessionFactoryBean通过getObject()方法创建。

    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
				<!--指定mybatis全局配置文件的位置,该文件为类路径下(src路径下或Resource Root下为类路径下)的mybatis-config.xml-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
				<!--指定数据源为上面配置的c3p0的ds-->
        <property name="dataSource" ref="ds"></property>
				<!--指定xml映射文件,即dao接口的实现xml文件的位置,这里包括类路径下文件名最后三位为Dao的所有xml文件-->
        <property name="mapperLocations" value="classpath:*Dao.xml"></property>
    </bean>

以配置的方式,将dao接口的实现,加入到ioc容器中

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
				<!--指定dao接口所在的基础包-->
        <property name="basePackage" value="com.philshao.dao"></property>
    </bean>

④配置事务控制,配置事务管理器控制住数据源DataSource里面connection的关闭和提交

    <bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--    控制数据源,数据源即上面配置过的    -->
        <property name="dataSource" ref="ds"></property>
    </bean>
		<!--基于xml配置,配置事务-->
    <aop:config>
				<!--配置切入点表达式,表示哪些方法需要切入事务,expression表示的方法都需要切入事务-->
      	<!-- * com.philshao.service.*.*(..) 表示任意返回值,service包下的任意类的任意方法,参数也任意 -->
        <aop:pointcut id="txPoint" expression="execution(* com.philshao.service.*.*(..))"/>
				<!--对于要切入的事务,应该配置什么样的属性-->
        <aop:advisor advice-ref="myTx" pointcut-ref="txPoint"/>
    </aop:config>
		<!--配置事务增强、事务属性、事务建议-->
    <tx:advice id="myTx" transaction-manager="tm">
				<!--配置事务属性,例如:异常回滚,get方法只读等等-->
        <tx:attributes>
						<!--所有方法,对于任何异常都回滚-->
            <tx:method name="*" rollback-for="java.lang.Exception"/>
						<!--所有get方法,都只读-->
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

3)mybatis-config.xml

由于applicationContext.xml已经配置了数据源等信息,并且也注册了dao接口的映射,所以mybatis-config.xml中就只需要配置mybatis自身的一些设置,例如开启二级缓存、懒加载等等。

    <settings>
        <!-- 开启全局缓存,即二级缓存,当session关闭时,其一级缓存会被转移到二级缓存,供其他session使用 -->
      	<!-- mybatis查询顺序为:二级缓存 > 一级缓存 > 发送sql查询数据库 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>

4)dao接口的映射文件

示例代码用了两个bean。

public class User {
    
    

    private Integer id;
    private String name;
    private String password;
    private String address;
    private String phone;
    private Department dept;
    ...
}
public class Department {
    
    

    private Integer deptId;
    private String deptName;
    ...
}    

数据库中包含两张表user表和department表。
user表包含id, name, password, address, phone, dept_id字段。
department表包含dept_id, dept_name字段。

UserDao.java中定义了一些查询方法。

public interface UserDao {
    
    

  	//查询所有用户
    public List<User> getUsers();

    // 返回的Map中key为对象的id,value为对象User
    @MapKey("id")
    public Map<Integer,User> getUsersMap();

    public User getUserById(Integer id);

    //根据范围查询,where id > ? and name like `%i%`之类
    public List<User> getUsersByCondition(User user);

    //where id in ids 的范围查询
    public List<User> getUsersByCollection(@Param("ids") List<Integer> ids);

    public int updateUser(User user);

    //使用set标签进行部分字段(如果该字段有值)的更新
    public int updateUserBySet(User user);

    public int deleteUser(Integer id);

    public int insertUser(User user);

}

dao接口的映射文件 UserDao.xml

<!--mapping标签的namespace指明用来处理哪个接口,
    然后需要在mybatis的全局配置文件mybatis_config.xml进行注册-->
<mapper namespace="com.philshao.dao.UserDao">
<!--  使用第三方缓存,bean类可以不实现序列化接口  -->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
<!--    select标签表示查询操作,id表示对应的查询方法,resultType表示查询的返回值,#{id}表示方法传入的参数-->
    <select id="getUserById" resultMap="myUser">
        select `id`,`name`,`password`,`address`,`phone`,user.`dept_id`,`dept_name`
        from user left join department
        on user.dept_id=department.dept_id
        where user.`id`=#{id}
    </select>
    
<!--  public List<User> getUsersByCondition(User user);
       where标签会将前面多余的 and 去除 -->
    <select id="getUsersByCondition" resultMap="myUser">
        select `id`,`name`,`password`,`address`,`phone`,user.`dept_id`,`dept_name`
        from user left join department
        on user.dept_id=department.dept_id
        <where>
            <if test="id != null">
                id > #{id}
            </if>
            <if test="name != null">
                and name like #{name}
            </if>
            <if test="address != null">
                and address like #{address}
            </if>
        </where>
    </select>

<!--   public List<User> getUsersByCollection(List<Integer> ids); -->
    <select id="getUsersByCollection" resultMap="myUser">
        select `id`,`name`,`password`,`address`,`phone`,user.`dept_id`,`dept_name`
        from user left join department
        on user.dept_id=department.dept_id
        where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

    <resultMap id="myUser" type="com.philshao.pojo.User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="password" column="password"/>
        <result property="address" column="address"/>
        <result property="phone" column="phone"/>
        <association property="dept" javaType="com.philshao.pojo.Department">
            <id property="deptId" column="dept_id"/>
            <result property="deptName" column="dept_name"/>
        </association>
    </resultMap>

<!--    public User getUsers(),返回值必须写容器中元素的类型-->
    <select id="getUsers" resultType="com.philshao.pojo.User">
        select * from user
    </select>

<!--     public Map<Integer,User> getUsersMap(),返回值类型必须写容器中value的类型-->
    <select id="getUsersMap" resultType="com.philshao.pojo.User">
        select * from user
    </select>

<!--    增删改不用填写返回值类型,mybatis自动判断,
        如果原方法的返回值类型是数值,则返回影响的行数;如果是布尔类型,则返回是否成功-->
    <update id="updateUser">
        update user
        set name=#{name},password=#{password},address=#{address},phone=#{phone}
        where id=#{id}
    </update>

<!--  public int updateUserBySet(User user); 使用set标签更新数据库 -->
    <update id="updateUserBySet">
        update user
        <set>
            <if test="name != null">
                name=#{name},
            </if>
            <if test="address != null">
                address=#{address},
            </if>
            <if test="password != null">
                password=#{password}
            </if>
        </set>
        <where>id=#{id}</where>
    </update>
  
    <!--添加数据-->
    <insert id="insertUser">
        insert into user (`name`,`password`,`address`,`phone`)
        values (#{name},#{password},#{address},#{phone})
    </insert>
  
    <!--删除数据-->
    <delete id="deleteUser">
        delete from user where id=#{id}
    </delete>

</mapper>

三、测试SSM

1)首页index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>首页</title>
  </head>
  <body>
  <a href="getUser?id=1">点击查询id为1的用户</a>
  </body>
</html>

2)测试成功页success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>访问成功</title>
</head>
<body>
<h1>success</h1>
${requestScope.user.name}<br/>
${requestScope.user.address}
</body>
</html>

3)前端控制器 UserController

@Controller
public class UserController {
    
    

    @Autowired
    private UserService userService;

    @RequestMapping("/getUser")
    public String getUser(@RequestParam("id")Integer id, Model model){
    
    
        User user = userService.getUser(id);
        model.addAttribute("user",user);
        return "success";
    }
}

4)业务逻辑组件 UserService

@Service
public class UserService {
    
    

    @Autowired
    private UserDao userDao;

    public User getUser(Integer id){
    
    

        return userDao.getUserById(id);
    }
}

然后就可以启动开始测试。

猜你喜欢

转载自blog.csdn.net/Longstar_L/article/details/108728318