• spring+mybatis+mina+logback框架搭建


    第一次接触spring,之前从来没有学过spring,所以算是赶鸭子上架,花了差不多一个星期来搭建,中间遇到各种各样的问题,一度觉得这个框架搭建非常麻烦,没有一点技术含量,纯粹就是配置,很低级!但随着搭建的完成,有一点点体会:框架可以让我们的代码更加像一个项目,而不是一个普普通通的作业,这在之前我们学生时代往往不会注意到这一点。我觉得这就是专业和业余的区别。当然,目前,我连spring入门可能都算不上,只是为了完成任务来搭建这套框架,但还是很有收获的,所以记录下这篇博客,给过来人参考。

    另外还有一个重要原因是,网上的框架搭建如spring+mybatis的博客,老实说,有很多明显有错误!最终竟然还能正确运行出结果,简直匪夷所思,还有的,缺少文件或者说明,会让刚学习spring的人摸不着头脑,尤其是你兴致勃勃地参考一篇博客,辛苦地搭建了一大半,结果到最后发现,有一个文件没有提供,有一个函数没有提供,有一个类没有提供。。。总之你无法继续下去,内心一定会非常奔溃!所以,我决定写这篇博客!

    关于spring的介绍,我就不多说了,我也是门外汉~我就说一下,我为什么要使用这几个框架,spring自然不必多说,mybatis是对数据库的封装,用来操作数据库,mina是对网络通信(如socket)的封装,logback是关于日志的框架。我要实现的是一个短信平台的验证系统,需要操作数据库,需要通过向第三方服务器发送短信,这几个功能可以由这些框架一一实现。

    参考博客:

    http://chenjc-it.iteye.com/blog/1402939

    http://www.cnblogs.com/nick-huang/p/3838326.html

    mybatis

    mybatis和spring整合需要的包有mybatis、mybatis-spring、数据库驱动包(oracle是ojdbcXXX.jar或者mysql,根据用到的数据库配置)和数据库连接池dbcp包。如果对数据库连接池不太清楚的,可以上网搜索。关于包的版本,我用的跟网上的一些也都不一样,所以大家也没必要纠结一定要用哪个版本的包,不过确实会存在版本过高或过低导致的问题,到时候注意一下就行了。包的下载,我强烈推荐一个网址:https://mvnrepository.com/,只要输入相关关键字就可以找到相应不同版本的包,非常方便!好了,现在开始搭建。假设,我已经用oracle创建了一个表-wkzf,表的字段有(telephone,starttime...),为了方便,我只列出这两个字段,这两个字段的类型都是NUMBER。telephone表示手机号,是11位,starttime表示发送短信的时间,它是毫秒,用来表示现在与 1970 年1月1日00:00:00.000的偏移量,这个可以很方便地计算一个验证码是否超过60秒,如果是日期如yy-mm-dd-hh这样的格式就不太好计算了。

    接下来,我们创建一个包,包名可以叫作com.xysj.mybatis.entity,包名的规则可以参考:http://www.runoob.com/java/java-package.html。这些小细节可以让你看起来更加专业。在这个包下面,我们可以创建一个实体类,用来与上面我们设计的表中的字段对应起来,代码如下:

     1 package com.xysj.mybatis.entity
     2 
     3 public class User {
     4     private long telephone;
     5     private long starttime;
     6 
     7     public long getTelephone()
     8     public void setTelephone(long telephone)
     9     ...
    10 }

    可以看到,我们实体类User当中,有两个私有变量,很显然分别对应表中的两个字段,然后还有get和set函数,分别用来对这些变量进行操作。

    接下来,我们定义一个接口类UserMapper,用来对数据库进行操作。同样,我们创建一个包:com.xysj.mybatis.mapper,在该包下面,创建一个java文件,代码如下:

    1 package com.xysj.mybatis.mapper
    2 
    3 import com.xysj.mybatis.User
    4 
    5 public interface UserMapper {
    6     public User selectUser(long telephone)
    7     public void insertUser(User user)
    8     ...
    9 }

    UserMapper只是一个接口类,那它的具体实现,即操作数据库的SQL语句在哪里呢?我们可以通过xml文件来进行配置,即具体的实现都写在xml文件当中。所以我们可以在整个工程的src目录下,创建一个UserMapper.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="com.xysj.mybatis.mapper.UserMapper">
    
        <select id="selectUser" resultType="user">
            select * from wkzf where telephone = #{telephone}
        </select>
        
        <insert id="insertUser" parameterType="user">
            insert into wkzf values(#{telephone},#{starttime})
        </insert>
    
    </mapper>

    需要注意的有几点:1)namespace后面填写的是包名+接口类名,一定不能错,错了,不像java有异常机制,可以捕捉异常,xml配置错了,很难发现,所以一定要小心!2)id后面的名字对应UserMapper.java中函数名,不能错!3)可能有人会疑问,为什么这里是“user”而不是“User”,我们定义的类是User啊,稍安勿躁,后面还有一个mybatis-configure.xml文件配置时,会对user进行说明,简单来说就是把User用了一个别名user。4)其他就是注意一些格式要求,#{}代表参数,对应着user中定义的变量。

    ok,现在对mybatis-configure.xml文件进行说明,代码如下:

     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE configuration
     3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
     4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
     5   
     6 <configuration>
     7 
     8     <!-- Register Alias -->
     9     <typeAliases>
    10         <typeAlias alias="user" type="com.xysj.mybatis.entity.User" />
    11     </typeAliases>
    12 
    13     <!-- Register Mapper -->
    14     <mappers>
    15         <!-- SQL Mapper -->
    16         <mapper resource="UserMapper.xml" />
    17     </mappers>
    18     
    19 </configuration>

    可以看到,我们对User取了一个别名user,这样就不需要把User的包名全部都写上了。同时,我们还关联了上面刚刚定义的UserMapper.xml文件。如果是单独的使用mybatis,用不到spring框架,这个xml文件中还应该声明DataSource的相关信息,好让mybatis知道与那个数据库连接。不过有了spring之后,这部分可以在spring-configure.xml文件中声明。

    接下来我们先创建一个包com.xysj.service,然后在包下创建一个UserService的类,代码如下:

     1 package com.xysj.service;
     2 
     3 import com.xysj.mybatis.entity.User;
     4 import org.mybatis.spring.SqlSessionTemplate;
     5 
     6 public class UserService {
     7     private SqlSessionTemplate  sqlSession;
     8     
     9     public SqlSessionTemplate getSqlSession() {
    10         return sqlSession;
    11     }
    12 
    13     public void setSqlSession(SqlSessionTemplate sqlSession) {
    14         this.sqlSession = sqlSession;
    15     }
    16     
    17     public UserInfo selectUser(long telephone) {
    18           User user = null;
    19           try {
    20                  user = (User) sqlSession.selectOne("com.xysj.mybatis.mapper.UserMapper.selectUser", telephone);
    21           } catch (Exception e) {
    22                  e.printStackTrace();
    23           }
    24         
    25           return user;
    26     }
    27 }

    注意selectOne中的函数第一个参数,一定要写完整!包名+接口名+函数名。之前,我这边没怎么搞懂,代码老是出错,我调试了很久才搞定!当然,这里只写了一个函数,你可以自己写insertUser、updateUser等函数,都是类似的。

    spring

    好了,现在我们开始配置spring-configure.xml文件,这个非常关键,一点也不能错,代码如下:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     default-autowire="byName"
     4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     5     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
     6 
     7     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
     8         <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
     9         <property name="url" value="jdbc:oracle:thin:@localhost:1521:SID" />
    10         <property name="username" value="xxxx" />
    11         <property name="password" value="xxxx" />
    12         <property name="maxActive" value="100"></property>
    13         <property name="maxIdle" value="30"></property>
    14         <property name="maxWait" value="500"></property>
    15         <property name="defaultAutoCommit" value="true"></property>
    16     </bean>
    17     
    18     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    19         <property name="configLocation" value="mybatis-configure.xml"></property>
    20         <property name="dataSource" ref="dataSource" />
    21     </bean>
    22     
    23     <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    24         <constructor-arg index="0" ref="sqlSessionFactory" />
    25     </bean>
    26     
    27     <bean id="userService" class="com.xysj.service.UserService">
    28        <property name="sqlSession" ref="sqlSessionTemplate" />
    29     </bean>
    30 
    31 </beans>

    需要注意的有几点:1)关于数据源的配置,因为用到了dbcp数据库连接池,所以需要相应的库(commons-dbcp-1.2.jar和commons-pool-1.4.jar ),localhost代表本机,如果你是远程连接到某一个数据库服务器上,则写服务器的IP地址,1521是端口号,SID是数据库名,记住是数据库名,不是表名!2)configLocation后面的value值填写正确,是mybatis的xml配置文件。3)最后一个bean,即“userService”后面的class处写正确,包名+类名。差不多要注意就是这几点,可能还有遗漏的,等到发现了再说。

    mina

    因为我们只是调用第三方的短信发送平台,所以我们只需要写一个客户端就行,不需要写服务端。总共有4个文件,我们可以先创建一个包:com.xysj.mina。第一个文件ClientHandle.java:

     1 package com.xysj.mina;
     2 
     3 import ...
     4 
     5 public class ClientHandle extends IoHandlerAdapter {
     6     private final static Log log = LogFactory.getLog(ClientHandle.class);
     7     
     8     @Override
     9     public void messageReceived(IoSession session, Object message) throws Exception {
    10         log.debug("客户端收到消息" + message.toString());
    11         super.messageReceived(session, message);
    12     }
    13     
    14     @Override
    15     public void messageSent(IoSession session, Object message) throws Exception {
    16         log.debug("客户端发送消息" + message.toString());
    17         super.messageSent(session, message);
    18     }
    19     
    20     @Override
    21     exceptionCaught
    22     sessiogCreated
    23     sessionOpened
    24     sessionClosed
    25     sessionIdle
    26 }

    因为我们公司是在云桌面开发的,所有的代码和开发环境都在思杰的云桌面上,没有办法拷贝下来,所以只能手打,错误在所难免啊~我也没有办法,import后面的内容省略了,一般你敲完代码,eclipse会提示需要import哪些类,一些重载的函数我也省略了,函数里的内容基本上都差不多,除了一些参数不一样。还有网上搜一下,也能找到这些函数的实现,这里我就不一一敲了。都是手工敲的,难免会有一些代码会敲错,如果出错,请大家指出来哈!第二个文件CodeFactory.java:

     1 package com.xysj.mina;
     2 
     3 import ...
     4 
     5 public class CodeFactory implements ProtocolCodecFactory {
     6     private XmlDecoder xmldecoder = null;
     7     private XmlEncoder xmlencoder = null;
     8     
     9     public CodeFactory() {
    10         this(Charset.defaultCharset());
    11     }
    12     
    13     public codeFactory(Charset charset) {
    14         this.xmldecoder = new XmlDecoder(charset);
    15         this.xmlencoder = new XmlEncoder(charset);
    16     }
    17     
    18     @Override
    19     public ProtocolDecoder getDecoder(IoSession session) throws Exception {
    20         return xmldecoder
    21     }
    22     
    23     @Override
    24     public ProtocolEncoder getEncoder(IoSession session) throws Exception {
    25         return xmlencoder
    26     }
    27 }

    从字面意思不难发现,一个是编码,一个是解码,当你把消息发送出去前(即调用messageSent函数前),需要先编码。当你收到消息及messageReceived响应时,会先进行解码。所以接下来就是对这两部分分别进行实现,网上也有响应的代码,也可以参考,老实说mian这部分我也不是很清楚,正如我前面所说的,我只是先搭建了这么一个框架,然后把代码调通,以后有时间,再慢慢深入了解这些框架。好了,首先是XmlDecoder.java:

     1 package com.xysj.mina;
     2 
     3 import ...
     4 
     5 public class XmlDecoder extends CumulativeProtocolDecoder {
     6     private final static Log log = LogFactory.getLog(XmlDecoder.class);
     7     private final Charset charset;
     8     
     9     public XmlDecoder(Charset charset) {
    10         this.charset = charset;
    11     }
    12     
    13     @Override
    14     protected boolean doDecode(IoSession session, IoBuffer in,
    15             ProtocolDecoderOutput out) throws Exception {
    16             CharsetDecoder decoder = charset.newDecoder();
    17             IoBuffer ioBuffer = IoBuffer.allocate(3072).setAutoExpand(true);
    18             log.info(“开始解码”);
    19             
    20             byte[] b = new byte[in.limit()];
    21             in.get(b);
    22             
    23             Charset charset = Charset.forName("GBK");
    24             ByteBuffer buf = ByteBuffer.wrap(b);
    25             CharBuffer cbuf = charset.decoder(buf);
    26             log.debug("客户端收到消息" + cbuf.toString());
    27             
    28             while(in.hasRemaining()) {
    29                 byte bte = in.get();
    30                 ioBuffer.put(bte);
    31                 if(bte == '
    ') {
    32                     ioBuffer.flip();
    33                     byte[] bt = new byte[ioBuffer.limit()];
    34                     ioBuffer.get(bt);
    35                     String message = new String(bt, decoder.charset());
    36                     ioBuffer = IoBuffer.allocate(100).setAutoExpand(true)limit
    37                     out.write(message);
    38                 }
    39             }
    40             return true;
    41             }
    42 }

    有了解码的,还有编码的XmlEncode.java:

     1 package com.xysj.mina;
     2 
     3 import ...
     4 
     5 public class XmlEncoder extends ProtocolEncoderAdapter {
     6     
     7     private final Charset charset;
     8     
     9     public XmlEncoder(Charset charset) {
    10         this.charset = charset;
    11     }
    12     
    13     @Override
    14     protected void encode(IoSession session, Object obj,
    15             ProtocolEncoderOutput out) throws Exception {
    16             CharsetEncoder encoder = charset.newEncoder();
    17             IoBuffer io = IoBuffer.allocate(100).setAutoExpand(true);
    18             
    19             io.putString(obj.toString(), encoder);
    20             io.put((byte)'
    ');
    21             io.put((byte)'
    ');
    22             io.flip();
    23             out.write(io);
    24     }
    25 }

    好了,关于mina的四个文件都已经写好了,关键是编码和解码的实现,感觉这是要按照相同的格式才行。如果要配置mina的服务器的话,还需要创建响应的xml配置文件,大家自己上网搜找。我们这里只涉及客户端的代码。

    logback

    日志框架,这个一句话说明就行了,相信大家看上面的代码看到这一行代码:private final static Log log = LogFactory.getLog(类名.class)。然后,在函数中,只要加上log.info()或者log.debug()就可以生成相应的日志。当然,生成的日志放在哪里,日志是什么样的格式,日志的名字等等信息都需要在logback的xml配置文件中声明,logback.xml文件如下:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <configuration debug="false">
     3 <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
     4 <property name="LOG_HOME" value="/log" />
     5 <!-- 控制台输出 -->
     6 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     7 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
     8 <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
     9 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    10 </encoder>
    11 </appender>
    12 <!-- 按照每天生成日志文件 -->
    13 <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    14 <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    15 <!--日志文件输出的文件名-->
    16 <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
    17 <!--日志文件保留天数-->
    18 <MaxHistory>30</MaxHistory>
    19 </rollingPolicy>
    20 <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    21 <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
    22 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    23 </encoder>
    24 <!--日志文件最大的大小-->
    25 <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
    26 <MaxFileSize>10MB</MaxFileSize>
    27 </triggeringPolicy>
    28 </appender>
    29 
    30 <!-- 日志输出级别 -->
    31 <root level="INFO">
    32 <appender-ref ref="STDOUT" />
    33 </root>
    34 </configuration>

    logback的配置文件,我直接从网上拷贝下来的,参考的网址是:http://www.cnblogs.com/warking/p/5710303.html。我的云桌面上的配置文件跟这个差不多,一行一行敲下来肯定不现实,所以直接从网上找了一个类似的。有些地方可以自己改一改,比如日志生成的路径啊,日志名字啊等等,还是很容易理解的。

    OK,终于到最后了!是不是感觉这些框架配置起来挺麻烦的,一点错误都不能有,一旦xml中出错,查找起来还比较麻烦,因为没有报错机制啊,也不能设置断点一行一行查看,所有细心非常重要!接下来我们需要写一个测试类,用来测试上面所有的框架。简单点,就test.java:

    test的目的是调用上面框架,代码也不少,一个一个敲实在是太麻烦,所以就贴图片了,格式会比较乱,但也没有办法。OK,到此,关于这个框架的搭建就差不多了。最后想说的是,后面的路还很长,我还是一个java初学者,需要努力加油!

    日志

    1.2017.9.11正式发布第一版本

  • 相关阅读:
    移动端适配原理浅析
    springMVC框架下——通用接口之图片上传接口
    Nginx服务器
    sql sever和mysql 卸载及oracle安装
    高清图片爬取
    中国部分大学排名爬虫
    selenium和PhantomJS的安装
    NYOJ2—括号配对问题
    爬虫之小说爬取
    数据库系统概论书本基础知识
  • 原文地址:https://www.cnblogs.com/fxl-njfu/p/7449390.html
Copyright © 2020-2023  润新知