Spring+SpringMVC+MyBatis框架配置与踩坑笔记

前言

最近在使用Spring+SpringMVC+MyBatis做软件工程的课程项目,虽然之前有一次使用SSM框架的经历,但是还是要说,自己配置这个框架简直是太难了!在博客上不断查阅资料和搜索报错后,我终于把我项目的整体框架运行了起来,在这里我把在配置过程中的重要信息和遇到的错误记录下来,希望下一次的配置过程不要这么艰辛。

一. Spring+SpringMVC+MyBatis 项目整体框架

项目的整体框架如下图所示:

框架配置的过程主要参考的是这两篇博文:手把手搭建ssm框架ssm框架整合

关于每个文件夹,具体的作用,很多博文都有详尽的描述,在此不在赘述。

需要注意的是,最好在把所有结构配好之后,再在IDEA上右键文件夹,选择文件夹类型。如果提前把Java文件夹Make Directory as sources root(也就是让它的颜色变为蓝色),会出现无法在其目录下新建多个包的情况。

在此附上spring-mvc.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <!-- 扫描web相关的bean -->
    <context:component-scan base-package="ssm.controller"/>

    <!-- 开启SpringMVC注解模式 -->
    <mvc:annotation-driven/>

    <!-- 静态资源默认servlet配置 -->
    <mvc:default-servlet-handler/>

    <!-- 配置jsp 显示ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

二. 数据库连接配置与SQL语句

1. 基本配置

上述框架中,jdbc.properties的配置如下(IP和密码被隐藏)

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://0.0.0.0:3306/codejudger?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC

jdbc.username=root

jdbc.password=000000

c3p0.maxPoolSize=30

c3p0.minPoolSize=10

c3p0.autoCommitOnClose=false

c3p0.checkoutTimeout=10000

c3p0.acquireRetryAttempts=2

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

    <!-- 扫描service包下所有使用注解的类型 -->
    <context:component-scan base-package="ssm.service"/>

    <!-- 配置数据库相关参数properties的属性:${url} -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
        <property name="minPoolSize" value="${c3p0.minPoolSize}"/>
        <property name="autoCommitOnClose" value="${c3p0.autoCommitOnClose}"/>
        <property name="checkoutTimeout" value="${c3p0.checkoutTimeout}"/>
        <property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}"/>
    </bean>

    <!-- 配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 扫描model包 使用别名 -->
        <property name="typeAliasesPackage" value="ssm.model"/>
        <!-- 扫描sql配置文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!-- 配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 给出需要扫描Dao接口包 -->
        <property name="basePackage" value="ssm.dao"/>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置基于注解的声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

2. mapper文件配置

在mapper文件夹下,我们通过xml文件来实现对数据库的增删该查,一个示例文件如下:

扫描二维码关注公众号,回复: 8874513 查看本文章
<?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">

<mapper namespace="ssm.dao.IProblemDao">

    <select id="getAllProblems" resultType="Problem">SELECT * from problem</select>
    <select id="getProblemByID" resultType="Problem" parameterType="String">SELECT * from problem where uuid=#{uuid}</select>

</mapper>

namespace对应的是dao包中的接口,id是接口中方法的名称,parameterType是方法参数类型,returnType对应return值的类型,如果返回类型是List,这里returnType依然是List中元素的类型。

在这里,有一个小问题,我们写的SQL语句无法直观的看到对错,在这里,我们可以使用IDEA为我们提供的工具进行检查。

点击右侧的database,新建一个数据库连接,这样,我们就可以在配置文件中看到我们写的SQL语句是否合法了。

3. 连接云端数据库

显然对于一个正式的项目,配置一个远程数据库是十分有必要的,在Ubuntu服务器上配置MySQL可以参考这篇博文:服务器配置MySQL,但是按照教程配置好之后,本机依然连接不上MySQL。查阅了很多资料才明白,这是阿里云本身端口保护的原因,可以参考这篇博文的第三条——远程连接阿里云MySQL失败解决办法。要在阿里云控制台进行相关的配置。

三. 配置报错

1. MySQL版本不匹配报错

报错信息:'caching_sha2_password' cannot be loaded

报错原因:在本机,我使用的是MySQL 8.0+的版本,但是在pom.xml中我却用了5.0+的包,造成了版本的不匹配,修改相关配置如下:

    <!-- 数据库 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.11</version>
      <scope>runtime</scope>
    </dependency>

2. controller与service忘记加@

这里的报错很不小心,单纯的因为在controller与service类上面忘加@controller与@service

3. mapper中的sql语句区分大小写

报错内容:Cause: java.sql.SQLSyntaxErrorException: Table 'codejudger.Problem' doesn't exist

报错原因:最开始看到这个报错的时候感觉十分的违反常识,怎么可能找不到?并且IDEA也没有提示错误,在这篇博文:映射mybatis *mapper.xml文件中的SQL时需要区分大小写中,作者提到这里的SQL是区分大小写的,如果想不区分,应该使用接口方式映射SQL。因此我将所有的sql查询都改成了小写。

4. 生成的项目没有clean

在帮同学配置这个项目的时候,我发现我所有的改动都没有起到效果,因此怀疑是没有清理旧项目导致的,因此选择build,clean之后,果然,后来的配置全部生效了。这个问题我没有遇到过,但是依然提醒大家在遇到此类问题的时候,试着清理一下项目,会不会有奇效。

5. 找不到对应的Artifact

这个问题同样是在同学的电脑上遇见的。在配置了Tomcat之后,报错是没有找到生成的artifact。这个错误很好定位,肯定是生成的artifact名字不统一导致的。通过查看tomcat的configuration我发现,其寻找的包的名字和实际要导入的包的名字不一致。

我们都知道,使用别人的maven项目可以使用IDEA的import功能,这个问题的出现和import有关系。它继承了原来项目使用的artifact的名字,但是新项目在build的时候,它却生成了新名字的artifact。

四. 单元测试

要想做一个成功的项目,软件测试必不可少,这是我无数血泪的教训总结出来的经验,因此这次项目我一定要测试这个环节完成。我目前使用的是Junit工具,目前只写了对dao的测试,相关博文可以参考使用spring配合Junit进行单元测试的总结

其中的测试例子如下:

package daoTest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import ssm.dao.IUserInformationDao;
import ssm.model.User;
import ssm.model.UserInformation;

import javax.annotation.Resource;

import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-mvc.xml","classpath:spring-mybatis.xml"})
@Transactional
public class UserInformationDaoTest {
    @Resource
    private IUserInformationDao iUserInformationDao;

    @Test
    public void testSelect()
    {
        UserInformation userInformation = iUserInformationDao.getUserInformationByUserID("1");
        assertNotNull(userInformation);
    }

    @Test
    public void testUpdate()
    {
        UserInformation userInformation= iUserInformationDao.getUserInformationByUserID("1");
        userInformation.setTotalSubmitCount(100);
        iUserInformationDao.updateUserInformation(userInformation);
        UserInformation selectUserInformation = iUserInformationDao.getUserInformationByUserID("1");
        assertEquals(selectUserInformation.getTotalSubmitCount(),100);
    }


}

通过单元测试,我发现了大量的疏漏,这证明完善的测试必不可少。

全部测试通过,dao测试完成!

五. 项目源码

项目正在进行中,欢迎大家指正!

CodeJudger

发布了85 篇原创文章 · 获赞 100 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/caozixuan98724/article/details/88901607
今日推荐