MAVEN整合Spring+SpringMVC+Mybatis

本文介绍了如何使用MAVEN搭建JAVA-WEB项目,整合Spring、SpringMVC和Mybatis,无需手动配置DAO层,以及如何进行Junit测试、JSON输出、日志控制和代码注释规范。详细讲解了每个步骤,适合初学者学习。
摘要由CSDN通过智能技术生成

2016/1/20 14:47:28


原创,转载请注明出处

曾经看过《那些年我们一起追过的女孩》,片中有个比较经典的画面,至今记忆犹新,柯景腾多年后,做了一名作家,每天面对电脑码字,背后是一张张一闪而过的字幅“人生就是不停的战斗”

作为程序员,我想一生就是不停的和BUG做战斗了,新来的这家公司,用的很老的Spring+Struts2.0+JDBC的框架,非常的不好用,其中的问题可以陈述10条以上,但是限于当时的技术水平所限,不能达到也很正常,所以我萌生了一个推翻重写后台的想法(从这到正文部分纯属装逼的,大神绕过,新人还是需要看一哈,熟悉一下为什么是MAVEN)

JAVA这门语言,之前看一个漫画是这么形容的,C++是加农炮,威力强大,什么都能炸;JAVA是一个手机,它能打电话叫来各种炮,炸的你爹妈不认得,但是它的JAR存在着依赖关系,比如Spring中的对AspectJ和JSR的支持是基于AspectJ和其他的JAR包的,你用它之前必须要先有依赖的jar包;项目中有两个典型的jar就是如此

  • aopalliance-1.0.jar 它是SpringAOP的基础依赖包
  • hamcrest-core-1.1.jar 他是Junit依赖的jar包

那么问题来了,我要是打电话,请人帮我“炸楼”,就好比JAVA请JAR包,我是不是连它爸妈一起请?我是不是要配置所有的依赖包,答案NO,因为我可以借助MAVEN这个神器啊,它会自动解析包的依赖关系去自动下载

在这个项目的搭建和第一次用maven没有人帮助我的情况下,能做出来还是有些小激动,也学习到了很多新的知识,重新把Spring学习了一遍,进一步理解了XML配置文件,SpringIOC和SpringAOP,惊叹于Spring框架的神奇之处,自己也掌握了许多Spring相关的技术,例如:Spring是支持JSON的,我们可以直接在控制层方法加@ResponseBody,可以自动返回JSON对象,So Easy

本文作者所用:所有东西的版本

  • MyEClipse GA 2014
  • Spring 4.2.4(最新)
  • Mybatis 3.3.0(最新)

参考博客

http://blog.csdn.net/zhshulin/article/details/37956105
http://blog.csdn.net/l349440843/article/details/45788017
http://blog.csdn.net/zhshulin/article/details/37937365

本文主要介绍的技术:(大神绕过)

  1. MAVEN搭建JAVA-WEB项目
  2. Spring的配置文件
  3. Junit单元测试
  4. Spring整合JSON输出
  5. Spring整合Mybatis不需要写DAO层代码
  6. Log4j控制输出,主要介绍扩展方式写日志进数据库的方式
  7. 代码注释的规范,和一些MyEclipse的规范操作(个人觉得规范的)

作为程序界的老鸟,看到这篇文章就自动过滤之前这一段,不过本作也真诚的希望你们能为我提出建议,谢谢,言归正传,开始操练

1.MAVEN

  • Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。
  • Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发文时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。
  • 用MAVEN来管理jar包,不用一个一个去添加和下载jar包了,直接在maven配置文件中配置就可以了,maven可以帮助我们自动下载

1.1首先搭建一个maven项目

第一次新建MAVEN项目的筒子,你们在这里要稍微等一哈,MAVEN要去下载依赖

WEB项目点中上面的maven-archetype-webapp点击下一步


Group Id一般填公司的包名吧,第二个填公司名,其实我也不是很懂这个= =好像没有多大用

然后MAVEN就开始在US镜像仓库下载包和一些准备工作了你的MyEclipse的右下角,就会出现

至此,你的MAVEN项目就初步搭建好了

1.2那么接下来怎么搞

搭建好的MAVEN项目如下图

问题有两个,一个我,作为一个高逼格的程序员,一定要用最新版本的JRE环境,所以把项目构建改到最高版本,另外,报了一个 “javax.servlet.http.HttpServlet” was not found on the Java Build Path index.jsp错误,这是由于在index.jsp页面上缺少对JavaEE的支持,因此需要添加JavaEE的类库

  1. 右键工程–>properties–>JAVA Build Path–>Edit
  2. 在pox.xml中添加对JAVA EE的依赖

1.3最后是pom.xml的配置

如果遇到环境配置的问题,可以参考博文:MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建

点开pom.xml配置你的项目maven依赖,坐等几分钟,maven会下载JAR,如果不下载,或者停止,就点开MyEclipse 找到 MAVEN4MyEclipse 把下载按钮打开,或者还原为默认的

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.zjx</groupId>
  <artifactId>zjx</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>zjx Maven Webapp</name>
  <url>http://maven.apache.org</url>

  <properties>  
        <!-- spring版本号 -->  
        <spring.version>4.2.4.RELEASE</spring.version>  
        <!-- mybatis版本号 -->  
        <mybatis.version>3.3.0</mybatis.version>  
        <!-- log4j日志文件管理包版本 -->  
        <slf4j.version>1.7.7</slf4j.version>
        <log4j.version>1.2.16</log4j.version>   
    </properties>

  <dependencies>

    <!-- 单元测试的依赖 --> 
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>   



        <!-- spring核心包 -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-core</artifactId>  
            <version>${spring.version}</version>  
        </dependency> 

        <!-- spring对web的支持 -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-web</artifactId>  
            <version>${spring.version}</version>  
        </dependency> 

        <!-- spring对ORM映射的支持-->   
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-oxm</artifactId>  
            <version>${spring.version}</version>  
        </dependency> 

        <!-- spring事务管理支持 -->   
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-tx</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <!-- spring对JDBC的支持 -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-jdbc</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <!-- spring对MVC框架的支持 -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-webmvc</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <!-- spring切面支持 -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-aop</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <!-- spring上下文支持 -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-context-support</artifactId>  
            <version>${spring.version}</version>  
        </dependency>  

        <!-- spring测试支持 -->  
        <dependency>  
            <groupId>org.springframework</groupId>  
            <artifactId>spring-test</artifactId>  
            <version>${spring.version}</version>  
        </dependency> 

        <!-- AspectJ支持 -->
        <dependency>
            <groupId>aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.5.4</version>
        </dependency> 
        <!-- 织入 -->
        <dependency>
            <groupId>aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.5.4</version>
        </dependency>

        <!-- mybatis核心包 -->  
        <dependency>  
            <groupId>org.mybatis</groupId>  
            <artifactId>mybatis</artifactId>  
            <version>${mybatis.version}</version>  
        </dependency>  
        <!-- mybatis对spring的支持 -->  
        <dependency>  
            <groupId>org.mybatis</groupId>  
            <artifactId>mybatis-spring</artifactId>  
            <version>1.2.3</version>  
        </dependency>  

        <!-- 导入Mysql数据库链接jar包 -->  
        <dependency>  
            <groupId>mysql</groupId>  
            <artifactId>mysql-connector-java</artifactId>  
            <version>5.1.30</version>  
        </dependency> 

        <!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 -->  
       <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

        <!-- JSTL标签类 -->  
        <dependency>  
            <groupId>jstl</groupId>  
            <artifactId>jstl</artifactId>  
            <version>1.2</version>  
        </dependency>  

        <!-- 日志文件管理包 --> 

        <!-- log start --> 
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency> 
        <dependency>  
            <groupId>log4j</groupId>  
            <artifactId>log4j</artifactId>  
            <version>${log4j.version}</version>  
        </dependency> 

        <!-- 格式化对象,方便输出日志 -->  
        <dependency>  
            <groupId>com.alibaba</groupId>  
            <artifactId>fastjson</artifactId>  
            <version>1.1.41</version>  
        </dependency> 

         <!-- 导入java ee jar 包 -->  
        <dependency>  
            <groupId>javax</groupId>  
            <artifactId>javaee-api</artifactId>  
            <version>7.0</version>  
        </dependency>  


        <dependency>  
            <groupId>org.slf4j</groupId>  
            <artifactId>slf4j-api</artifactId>  
            <version>${slf4j.version}</version>  
        </dependency>  

        <dependency>  
            <groupId>org.slf4j</groupId>  
            <artifactId>slf4j-log4j12</artifactId>  
            <version>${slf4j.version}</version>  
        </dependency>  


        <!-- log end -->

        <!-- 映入JSON支持 --> 

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.5.1</version>
        </dependency> 
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.5.1</version>
        </dependency>



        <!-- 文件上传 -->
        <dependency>  
            <groupId>commons-fileupload</groupId>  
            <artifactId>commons-fileupload</artifactId>  
            <version>1.3.1</version>  
        </dependency>  
        <dependency>  
            <groupId>commons-io</groupId>  
            <artifactId>commons-io</artifactId>  
            <version>2.4</version>  
        </dependency>  
        <dependency>  
            <groupId>commons-codec</groupId>  
            <artifactId>commons-codec</artifactId>  
            <version>1.9</version>  
        </dependency>  


  </dependencies>
  <build>
    <finalName>zjx</finalName>
  </build>

</project>

所有的依赖包,和作用都注释清楚,至此,MAVEN的工作就完了,剩下的事情就是项目

2. Spring配置文件

首先,先几个题外话,所有人都知道程序分离是为了简化,人们习惯上把复杂的事情分解为若干个简单的事情处理,这就体现的是分层思想,所以程序上才有了MVC,才有了三层架构

当人们认知事物的高度达到一定程度之后,就会抓住事物的核心问题,也就是程序设计上常说的问题域,那么请看下面两个故事:

让时间回到2001年,地点是澳大利亚悉尼的Clarence Street有一家叫做Cirrus Technologies的公司,这是一家做J2EE企业级应用开发和咨询的公司,在会议桌上一个小伙子和老板正在进行着激烈的讨论。
小伙子:”老板,我总觉得开发的效率太低了,我用了EJB的Entity bean 1.1时,我总觉得我浪费了好多时间在处理Entity Bean的体系架构上,却没有花时间在核心业务逻辑的开发上,而且CMP给我们的限制太多了”。
老板:”Gavin,别傻了,EJB是业界的标准,也是最流行的技术,而且我们公司是IBM的合作伙伴。如果有问题,问题就是我们还没有适应这样的开发模式”。
小伙子:”不,我觉得肯定有更好的解决的方案。我们可以设计出比Entity Bean更好的方案”。
老板:”哦,Gavin,我知道你很聪明,开发水平也不错。但是开发这样的系统太难了,而且你根本就没有用SQL开发过任何数据库系统。不要想这样一个不现实的目标啦!”
小伙子皱了皱眉,说道:”不,我相信我有能力开发出这个系统。我的想法绝对是可行的。”
(注:以上场景纯属虚构,但至少以下内容完全属实:Gavin King开发hibernate的动机有两个:发现CMP太烂;赢得对老板的争执。Gavin King当时没有任何用SQL开发数据库的经验,Gavin King开发hibernate的第一件事是去街上买了本SQL基础的书)

也许Cirrus Technologies的老板做梦也想不到两年以后,这个小伙子开发出的那个产品会成为全世界最流行的O/R Mapping工具,而那个对SQL和数据库一窍不通的小伙子居然会成为全世界J2EE数据库解决方案的领导者。

这就是Gavin King,一个充满激情、脾气很倔、永不言败的人。他的成就也许全世界搞Java的人都知道:他是hibernate的创始人;他是EJB 3.0的Entity bean specification的实际领导人(sun任命的领导人应该是Linda DeMichiel);他也是那本经典的书hibernate in action的作者;他也参加了XDoclet和Middlegen的开发;他在全世界各种著名的会议(TheServerSide Symposium等)进行演讲和讲座。

2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。它的广告语是“我们已经学习了SQL,为什么我们还要学习HQL”;

故事给我的感触是,必须要学习新的技术,永远做第一个吃螃蟹的人,因为只有你知道了什么框架,有什么不足,你才会去改进,才会去发明新的框架,这也就是许多大牛,喜欢钻研技术,自己写框架,而不用别人现成的框架,小弟只是个渣渣,各位路过的大神勿喷,能指点我一二最好

不扯闲话:上配置(配置也体现了控制层和业务层分离的思想),因为项目开发的主要问题域在于业务逻辑的处理上,而不在DAO代码上,因此没有写DAO层,而交给Mybatis去自动控制,也体现了故事一种的思想,配置文档截图如下

  • applicationContext-action.xml 是专门配置持久层的
  • applicationContext-base.xml 是专门配置控制层的
  • jdbc.properties 是专门配置数据库连接的,这样配置提现分离和修改数据库的作用
  • log4j.properties 是专门配置日志输出和日志控制的
  • mybatis.cfg.xml 是为了提供ORM映射的配置,其中只需要配置一个类的别名,mapper已经移交Spring管理,但是个人嫌写类名麻烦,喜欢用别名
  • mybatis.cfg.xml 这个配置可以不要,看到有大神才用注解的方式,希望有大神路过不吝赐教

applicationContext-action.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:p="http://www.springframework.org/schema/p" 
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:tx="http://www.springframework.org/schema/tx" 
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:context="http://www.springframework.org/schema/context" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                            http://www.springframework.org/schema/aop
                            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
                            http://www.springframework.org/schema/tx
                            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
                            http://www.springframework.org/schema/mvc
                            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 

    <!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器,控制器全部放在这个包下 -->  
    <context:component-scan base-package="com.zjx.action">
<!--  如果使用包含采用该配置       <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> -->
<!--  如果使用过滤采用该配置   <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> -->
    </context:component-scan>

     <!--避免IE执行AJAX时,返回JSON出现下载文件 -->  
    <bean id="mappingJacksonHttpMessageConverter"  
        class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">  
        <property name="supportedMediaTypes">  
            <list>  
                <!-- 设置返回的编码和解析方式 -->
                <value>text/html;charset=UTF-8</value>  
            </list>  
        </property>  
    </bean>  
    <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->  
    <bean  
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
        <property name="messageConverters">  
            <list>  
                <ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON转换器 -->  
            </list>  
        </property>  
    </bean>  


    <!-- 定义跳转的文件的前后缀 ,视图模式配置-->  
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->  
        <property name="prefix" value="/WEB-INF/jsp/" />  
        <property name="suffix" value=".jsp" />  
    </bean>  

    <!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->  
    <bean id="multipartResolver"    
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">    
        <!-- 默认编码 -->  
        <property name="defaultEncoding" value="utf-8" />    
        <!-- 文件大小最大值 -->  
        <property name="maxUploadSize" value="10485760000" />    
        <!-- 内存中的最大值 -->  
        <property name="maxInMemorySize" value="40960" />    
    </bean>   

</beans>
applicationContext-base.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:p="http://www.springframework.org/schema/p" 
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:tx="http://www.springframework.org/schema/tx" 
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:context="http://www.springframework.org/schema/context" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                            http://www.springframework.org/schema/aop
                            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
                            http://www.springframework.org/schema/tx
                            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
                            http://www.springframework.org/schema/mvc
                            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <!-- 自动扫描 -->  
    <context:component-scan base-package="com.zjx" />  

    <!-- 引入配置文件 -->  
    <bean id="propertyConfigurer"  
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
        <property name="location" value="classpath:jdbc.properties" />  
    </bean> 

    <!-- 配置数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">  
        <property name="driverClassName" value="${jdbc.driver}" />  
        <property name="url" value="${jdbc.url}" />  
        <property name="username" value="${jdbc.username}" />  
        <property name="password" value="${jdbc.password}" />  
        <!-- 初始化连接大小 -->  
        <property name="initialSize" value="${jdbc.initialSize}"></property>  
        <!-- 连接池最大数量 -->  
        <property name="maxActive" value="${jdbc.maxActive}"></property>  
        <!-- 连接池最大空闲 -->  
        <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
        <!-- 连接池最小空闲 -->  
        <property name="minIdle" value="${jdbc.minIdle}"></property>  
        <!-- 获取连接最大等待时间 -->  
        <property name="maxWait" value="${jdbc.maxWait}"></property>  
    </bean>  

    <!-- spring和MyBatis整合-->  
    <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
        <property name="dataSource" ref="dataSource" />  

        <!-- 指明mybatis主配置文件路径 -->
        <property name="configLocation" value="classpath:mybatis.cfg.xml"></property>
        <!-- 指明mybatis的映射位置 -->
        <property name="mapperLocations">
            <list>
                <value>classpath:orm/*.xml</value>
            </list>
        </property>
    </bean>

    <!-- 配置SqlSession模版类,SqlSessionTemplate是线程安全类 -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
        <constructor-arg  ref="sessionFactory"></constructor-arg>       
    </bean>

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 允许使用注解配置事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/> 

    <!-- 扫描spring注解类 -->
    <context:component-scan base-package="com.zjx">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

</beans>
jdbc.properties
jdbc.driver=org.gjt.mm.mysql.Driver
#定义连接的URL地址,设置编码集,允许多条SQL语句操作
jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&amp;allowMultiQueries=true
jdbc.username=root  
jdbc.password=82651205
#定义初始连接数  
jdbc.initialSize=10  
#定义最大连接数  
jdbc.maxActive=20  
#定义最大空闲  
jdbc.maxIdle=20  
#定义最小空闲  
jdbc.minIdle=10 
#定义最长等待时间  
jdbc.maxWait=60000  
log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=warn, stdout

#log4j.logger.org.hibernate=info
#log4j.logger.org.hibernate=debug

### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug

### log just the SQL
#log4j.logger.org.hibernate.SQL=debug

### log JDBC bind parameters ###
#log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug

### log schema export/update ###
#log4j.logger.org.hibernate.tool.hbm2ddl=debug

### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug

### log cache activity ###
#log4j.logger.org.hibernate.cache=debug

### log transaction activity
#log4j.logger.org.hibernate.transaction=debug

### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

################################################################################
########文件记录日志的方式

##定义LOG输出级别  
#log4j.rootLogger=INFO,Console,File  
##定义日志输出目的地为控制台  
#log4j.appender.Console=org.apache.log4j.ConsoleAppender  
#log4j.appender.Console.Target=System.out  
##可以灵活地指定日志输出格式,下面一行是指定具体的格式  
#log4j.appender.Console.layout = org.apache.log4j.PatternLayout  
#log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n  
#  
##文件大小到达指定尺寸的时候产生一个新的文件  
#log4j.appender.File = org.apache.log4j.RollingFileAppender  
##指定输出目录  
#log4j.appender.File.File = logs/ssm.log  
##定义文件最大大小  
#log4j.appender.File.MaxFileSize = 10MB  
## 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志  
#log4j.appender.File.Threshold = ALL  
#log4j.appender.File.layout = org.apache.log4j.PatternLayout  
#log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c]%m%n

################################################################################
########数据库记录日志的方式
log4j.logger.com.zjx.util=error,database
log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.URL=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8
log4j.appender.database.driver=org.gjt.mm.mysql.Driver
log4j.appender.database.user=root
log4j.appender.database.password=82651205
log4j.appender.database.sql=INSERT INTO t_log(content,logDate) VALUES ('%m','%d{yyyy-MM-dd}')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
log4j.appender.database.layout.ConversionPattern=%m
mybatis.cfg.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>    
    <typeAliases>
        <!-- 如果还有其余的映射类,则继续添加 -->
        <typeAlias type="com.zjx.bean.UserBean" alias="user"/>
    </typeAliases>


</configuration>  
UserBean.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">
<mapper namespace="user">
    <!-- 结果集映射 -->
    <resultMap type="user" id="userMap">
        <result property="passWord" column="pwd"/>
    </resultMap>
    <select id="findById" parameterType="int" resultMap="userMap">
        select * from t_user where id = #{id};
    </select>

    <!-- 字段模糊的动态语句 -->
    <sql id="paramSql">
        <if test="userName !=null and userName != ''">
             and userName like '%${userName}%' 
        </if>
    </sql>

    <select id="findPage" resultMap="userMap">
        select * from t_user
        where 1=1 <include refid="paramSql"></include> 
        limit #{start},#{pageSize}
    </select>
    <select id="findCount" resultType="int">
        select count(*) from t_user where 1=1 <include refid="paramSql"></include>
    </select>


</mapper>

3.Junit测试

表自己建好,我也懒

那么首先书写实体:

package com.zjx.bean;

import java.sql.Date;


/** 
  * @Description 用户实体类
  * @author tony_kanper
  * @date 2016年1月20日 上午11:30:32 
  * @version V1.0 
  * 
  */
public class UserBean {
    /**
     * id
     */
    private int id;
    /**
     * 用户名
     */
    private String userName;
    /**
     * 生日
     */
    private Date birthday;
    /**
     * 密码
     */
    private String passWord;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    @Override
    public String toString() {
        return "UserBean [id=" + id + ", userName=" + userName + ", birthday="
                + birthday + ", passWord=" + passWord + "]";
    }
    public UserBean(String userName, Date birthday, String passWord) {
        super();
        this.userName = userName;
        this.birthday = birthday;
        this.passWord = passWord;
    }
    public UserBean() {
        super();
    }

}

业务接口Service

package com.zjx.service;

import com.zjx.bean.CutPageBean;
import com.zjx.bean.UserBean;

/** 
  * @Description: 用户业务接口
  * @author tony_kanper
  * @date 2016年1月20日 上午11:30:50 
  * @version V1.0 
  * 
  */
public interface IUserService {
    /**
     * 每页显示记录数
     */
    public final int PAGESIZE = 10;
    /**
     * @Desciption 按照用户id查找该用户
     * @param id 用户id
     * @return 用户实体
     */
    public UserBean findById(int id);


    /**
     * @Description 按照页码和用户姓名模糊字查找用户分页对象
     * @param pageNO 页码
     * @param userName 用户姓名模糊字
     * @return 分页对象
     */
    public CutPageBean<UserBean> findByItem(int pageNO,String userName);
}

业务接口实现类ServiceImpl超类和具体实现类

package com.zjx.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Service;

import com.zjx.bean.CutPageBean;
/** 
  * @Description 所有业务实现类的超类
  * @author tony_kanper
  * @date 2016年1月20日 上午11:31:07 
  * @version V1.0 
  *
  * @param <T> 通用泛型
  */
@Service
public class BaseService<T> {
    /**
     * SqlSesion模板类
     */
    @Resource
    protected SqlSessionTemplate session;

    /**
     * @Description 所有的查询分页对象的超类方法
     * @param pageNO 页码
     * @param pageSize 每页显示记录数
     * @param paramMap 需要查询的字段集合
     * @param listSql 查询某页记录的SQL语句
     * @param countSql 查询总记录数的SQL语句
     * @return 分页对象
     */
    public CutPageBean<T> cutpage(int pageNO, int pageSize,
            Map<String, Object> paramMap, String listSql, String countSql) {
        CutPageBean<T> cutBean = new CutPageBean<T>();
        if (paramMap == null) {
            paramMap = new HashMap<String, Object>();
        }
        // 设置查询的起始页
        paramMap.put("start", (pageNO - 1) * pageSize);
        // 设置查询页开始向后的记录数
        paramMap.put("pageSize", pageSize);

        // 查询Mybatis配置文件下,命名空间内的查询结果
        List<T> list = this.session.selectList(listSql, paramMap);
        cutBean.setList(list);

        // 设置总记录数
        int count = this.session.selectOne(countSql, paramMap);
        cutBean.setCount(count);

        // 设置总页数
        cutBean.setTotalPage(count / pageSize);
        if (count % pageSize != 0) {
            cutBean.setTotalPage(count / pageSize + 1);
        }
        return cutBean;
    }

}

具体实现类如下

package com.zjx.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.zjx.bean.CutPageBean;
import com.zjx.bean.UserBean;
import com.zjx.service.IUserService;
/** 
  * @Description 用户业务实现类 
  * @author tony_kanper
  * @date 2016年1月20日 上午11:50:57 
  * @version V1.0 
  * 
  */
@Service
public class UserServiceImpl extends BaseService<UserBean> implements IUserService {

    @Override
    public UserBean findById(int id) {
        // 测试切面类是否完成错误记录进入数据库时,解除注释
        // throw new NullPointerException();
        return session.selectOne("user.findById", id);
    }

    @Override
    public CutPageBean<UserBean> findByItem(int pageNO, String userName) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("userName", userName);
        return cutpage(pageNO, PAGESIZE, paramMap, "user.findPage", "user.findCount");
    }

}

测试类:

测试类超类:

package com.zjx.test;

import org.junit.After;
import org.junit.Before;
import org.springframework.beans.BeansException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StringUtils;


public class UnitTestBase {
    /**
     * 相对路径应用上下文
     */
    private ClassPathXmlApplicationContext context;

    /**
     * XML文件的存放路径
     */
    private String springXmlPath;

    public UnitTestBase() {

    }

    public UnitTestBase(String springXmlPath){
        this.springXmlPath = springXmlPath;
    }
    /**
     * 加载XML文件
     */
    @Before
    public void before(){
        if (StringUtils.isEmpty(springXmlPath)) {
            springXmlPath = "classpath*:spring-*.xml";
        }
        try {
            // 多个xml文件用逗号或者空格符隔开,均可加载
            context = new ClassPathXmlApplicationContext(springXmlPath.split("[,\\s]+"));
            context.start();
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
    /**
     * 销毁
     */
    @After
    public void after(){
        context.destroy();
    }

    /**
     * @param beanId SpringXML文件中的bean的id
     * @return 该bean的id对应下的实例,默认单例
     */
    @SuppressWarnings("unchecked")
    protected <T extends Object> T getBean(String beanId){
        try {
            return(T)context.getBean(beanId);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @param clazz 通过类模板获取该类
     * @return 该类的实例,默认单例
     */
    protected <T extends Object> T getBean(Class<T> clazz){
        try {
            return context.getBean(clazz);
        } catch (BeansException e) {
            e.printStackTrace();
            return null;
        }
    }
}

测试类

package com.zjx.test;

import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

import com.zjx.service.IUserService;

@RunWith(BlockJUnit4ClassRunner.class)
public class Test extends UnitTestBase{
    public Test() {
        super("classpath:applicationContext-base.xml");
    }
    @org.junit.Test
    public void testUnit(){ 
        IUserService service = super.getBean("userServiceImpl");
        System.out.println(service.findByItem(1, "张"));
    }

}

这样测试,免去了注释实现类中的测试类的麻烦,并且在pom.xml中设置了scope它仅在测试时引入这个包,实际使用时,并不会用到

<!-- 单元测试的依赖 --> 
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.10</version>
  <scope>test</scope>
</dependency>   

4.Spring整合JSON输出

也许小伙伴会问,不是说好了,要来玩JSON吗?

<!--避免IE执行AJAX时,返回JSON出现下载文件 -->  
<bean id="mappingJacksonHttpMessageConverter"  
    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">  
    <property name="supportedMediaTypes">  
        <list>  
            <!-- 设置返回的编码和解析方式 -->
            <value>text/html;charset=UTF-8</value>  
        </list>  
    </property>  
</bean>  
<!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->  
<bean  
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
    <property name="messageConverters">  
        <list>  
            <ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON转换器 -->  
        </list>  
    </property>  
</bean>  

Spring对JSON的支持也挺恶心的,如果Spring的版本足够高,他对JSON的支持会用到配置文件中的MappingJackson2HttpMessageConverter,注意这个Jackson2,如果你按着ctrl没链接,那么把2删除,说明你用的Spring版本是之前的,你用的json版本1也都足够了,如果你只能用2,那么,你的pom.xml中必须加入2.0版本以上的依赖,对此Spring上的说明也是这样的,楼主看了很久的源码= =,快给我点赞

<!-- 映入JSON2.5支持 --> 

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.5.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.1</version>
</dependency> 
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.5.1</version>
</dependency>

由图可知,在类的注释上最后一行,说明MappingJackson2HttpMessageConverter兼容Jackson 2.1和更高版本,之所以贴出来说,是想说明看源码很重要,也想说明我不是乱说的

接下来写一个JSP页面发送AJAX请求试试

<%@ page language="java" pageEncoding="UTF-8"%>
<html>
<body>
<h2>Hello World!</h2>
<hr/>
<a href="/zjx/user/nextPage.do">去看看用户页</a>
<script type="text/javascript" src="/zjx/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
    $(function(){
        $.post("/zjx/user/findById.do","id=1",function(data){
                alert(data);
                });
    });

</script>
</body>
</html>

action控制层:

package com.zjx.action;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.zjx.bean.CutPageBean;
import com.zjx.bean.UserBean;
import com.zjx.service.IUserService;

/** 
  * @Description 用户控制器
  * @author tony_kanper
  * @date 2016年1月20日 上午11:33:46 
  * @version V1.0 
  * 
  */
@Controller
@RequestMapping("/user")
public class UserAction {
    /**
     * 注入的业务接口
     */
    @Resource
    private IUserService service;

    /**
     * @Description 根据视图层传入的id调用业务方法查找到用户后采用转换为JSON对象返回
     * @param id 用户id
     * @return 用户实体的JSON对象
     */
    @RequestMapping("/findById")
    @ResponseBody//Spring集成的JSON,可以将Model转换为JSON对象存放在HttpServletResponse中
    private UserBean findById(int id){
        return service.findById(id);    
    }
    /**
     * @Description 按照页码和姓名模糊字查找某页全部用户对象
     * @param pageNO 页码
     * @param userName 用户姓名模糊字
     * @return 某页全部用户对象(JSON)
     */
    @RequestMapping("/findByPageAndName")
    @ResponseBody
    private CutPageBean<UserBean> findByPageAndName(int pageNO,String userName){
        return service.findByItem(pageNO, userName);
    } 
    /**
     * @Description 测试是否跳转去WEB-INF目录下的jsp页面
     * @return 返回视图的名称
     */
    @RequestMapping("/nextPage")
    private String nextPage(){
        return "allUserPage";
    }
}

嘿,通过测试,还真的在页面拿到了JSON数据呢,好神奇啊

5.Spring整合Mybatis不需要写DAO层代码

话说,倪们看到我写了DAO层代码了吗?因为DAO已经写到UserBean.xml中和配置里了,要是不懂这个XML里面怎么写SQL语句,就网上或者买书看看,不多说;

这里值得一提的是,我用了SqlSessionTemplate这个类,这个类有点搞笑,他是自动管理的,也就是说,他的创建销毁是不必依赖Spring的,也就是说,当SQL模版类查询结束之后,他自己就知道关闭了,而懂点SpringIOC的筒子都知道,bean默认是单例的,那么要是他自己关了,或者别人又用了这个类,并发的访问扎个办?答案是:你知道Mybatis的工程师有多骚不?

这个SqlSessionTemplate的注释是这个意思,他是线程安全的,是受Spring管理的,和Spring事务管理器一起工作保证只用在一个当前的线程,它也是Spring管理下的事务内;此外,它管理会话的生命周期,包括关闭,提交或回滚基于Spring事务配置必要的

看到这里,也就是说,Mybatis的工程师们,把这个棘手的问题甩给Spring去管,他们就当甩手掌柜了啊,反正有mybatis-spring.jar这个提供对Spring支持的神器在

<!-- mybatis对spring的支持 -->  
<dependency>  
    <groupId>org.mybatis</groupId>  
    <artifactId>mybatis-spring</artifactId>  
    <version>1.2.3</version>  
</dependency> 

也正是如此,我们在配置base的时候,会将模版类设置为多例,我问骚年你为何如此勇敢,因为它是线程安全的,也受Spring的管理

<!-- 配置SqlSession模版类,SqlSessionTemplate是线程安全类 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
    <constructor-arg  ref="sessionFactory"></constructor-arg>       
</bean>

另外,就算你不写这个多例,也不影响,最多报个警告

WARN DisposableBeanAdapter:364 - Invocation of destroy method ‘close’ failed on bean with name ‘sqlSession’: java.lang.UnsupportedOperationException: Manual close is not allowed over a Spring managed SqlSession

这个警告是说,在Spring管理下的sqlSession是不允许自己关闭的

PS:如果有大神找到其中更深的缘由,请不吝赐教

6. Log4j控制输出

关于Log4j的东西,网上太多了,各位慢慢看,个人觉得这篇博文蛮不错

Log4j配置详解

关于扩展输出的,我用的是AOP方式

工具类如下:

package com.zjx.util;

import java.sql.Date;
import java.text.SimpleDateFormat;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;


/** 
  * @Description 日志处理类
  * @author tony_kanper
  * @date 2016年1月20日 上午11:39:48 
  * @version V1.0 
  * 
  */
@Service
@Aspect
public class LogRecord {

    /**
     * 日期格式化输出对象
     */
    private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
    /**
     * 日志对象
     */
    private Logger log = Logger.getLogger(LogRecord.class);

    /**
     * @Description 在方法抛出异常之后,记录异常信息,并将异常信息以error等级封装到log对象中
     * @param point 切入点
     * @param e 方法抛出的异常
     */
    @AfterThrowing(value = "execution(* com.zjx.service.impl.*.*(..))", throwing = "e")
    public void writeLog(JoinPoint point, Exception e) {
        // 得到目标对象的类名
        String className = point.getTarget().getClass().getName();
        // 得到目标对象的方法名
        String methodName = point.getSignature().getName();

        // 当前日期
        String timeStr = df.format(new Date(System.currentTimeMillis()));
        // 得到异常类信息
        String exceptionStr = e.getClass().getName();

        String info = timeStr+" 在"+className+"的 "+methodName+"()方法,抛出"+exceptionStr+"异常";
        //System.out.println(info);
        log.error(info);
    }
}

一旦在com.zjx.service.impl包下的所有类的所有方法抛出异常之后,都会向log日志对象写入错误信息,并且在log4j配置文档中写入数据库,经测试无误

PS:对于环绕通知,和其它通知方式,关于订单类的记录,有大神会的,希望给我一个DEMO谢谢

附上邮箱:tony_kanper@hotmail.com

7.代码注释的规范

之前的项目也不是无可挽救,但是代码实在是太糟糕了,没用注释,或者关键性的注释用单行注释而不用文档注释,这对于代码阅读是相当困难的

对于文档注释,可以生成Javadoc,同时,当鼠标浮动到具有文档注释的类/方法/变量时,能提供说明,简单粗暴

通常我们可以在Myeclipse中配置你的注释样本

如图,我的文件注释上,拥有标题,包,文件描述,作者创建日期等信息

当然,你也可以通过Edit编辑你的输出样式

然后你可以按住Alt+Shirft+J快速在相应位置生成注释

最后你只需要填就是了

程序员一定要养成写注释的习惯,不关多大的公司,就说国内的支付宝,别个写对外接口不也一样写好的文档注释和代码的单行注释,我等菜鸟,更应该如此,这更多的是为了今后的程序员便于维护,而不是为了你看懂(当然你肯定希望别人写好注释)

8.最后

花了很多时间学习这些,最后的收获也蛮大,希望能遇到更多志同道合的朋友

项目中容易遇到的问题主要有这些,有的问题之前我已经提到了

  1. MAVEN环境变量的配置,在path中加入%MAVEN_HOME%\bin;如果还需要配置jar包的仓库可以参看博文MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建
  2. 对于SqlSession报错的问题,要加多例
  3. 对于Spring配置文件读取jdbc.properties文件时,报错,有可能是mySQL的权限验证问题,它会默认使用系统的userName,解决方案有两种,一种参看博文mysql启动问题access denied for user ‘root’@’localhost’(using password:YES) 另一种是找到mysql安装目录,在my.ini中,以记事本打开的文末添加–skip-grant-tables
  4. 对于Spring版本较低的,Json,可以用如下依赖



    org.codehaus.jackson
    jackson-mapper-asl
    1.9.13

  5. MAVEN仓库传送门MAVEN仓库,你只需要像百度一样在搜索栏中输入jar,它们自动会为你找到最新版本jar包依赖

  6. Myeclipse GA 2014的下载门,做为程序员肯定要用最新版的哇,遇到问题去解决就是了,不要怕遇到问题而用旧版,很多过时方法和不支持的东西,新的东西,永远更多插件支持,永远兼容旧版http://www.my-eclipse.cn/
  7. 如果有兴趣,可以关注我的CSDN http://blog.csdn.net/kang82651204/

本文源码:
http://download.csdn.net/detail/kang82651204/9412243

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值