Maven多模块,Dubbo分布式服务框架,SpringMVC,前后端分离项目,基础搭建,搭建过程出现的问题

Maven多模块,Dubbo分布式服务框架,SpringMVC,前后端分离项目,基础搭建,搭建过程出现的问题
现互联网公司后端架构常用到Spring+SpringMVC+MyBatis,通过Maven来构建。通过学习,我已经掌握了基本的搭建过程,写下基础文章为而后的深入学习奠定基础。

  首先说一下这篇文章的主要内容分为:

  1、Maven多模块项目的创建;

  2、Maven与SpringMVC的整合;

  3、Dubbo的环境配置及与整合;

  4、新手在整合过程易犯的错误。

  通过一个简单的demo来说明,大家多多指教,分享经验!

  一、Maven多模块项目的创建

    我们需要建立一个多模块的maven项目,其目录结构为

    

    其中student-api用于暴露接口;student-service用语处理业务逻辑及调用数据访问对象,返回相应数据;student-web主要用于提供dubbo服务,及其他db、spring、springMVC、mybatis等配置。这样设计能够将业务逻辑与数据访问隔离开,同时贴合了spring目标之一,就是允许我们在开发应用的程序时,能够遵循面向对象(OO)原则中的“针对接口编程”,很大程度上达到松耦合。这里将接口API隔离出来作为dubbo生产者的服务接口,供消费应用调用(在后续详细讲解)。

    1.新建Maven项目

    

      2.选择项目存放路径后,选择创建一个简单的maven项目

    

    3.填写GroupId和ArtifactId,注意选择或者填写版本号

     

    点击完成后,建立好了student-demo项目。之后删除项目src目录,打开pom.xml将<packaging>jar</packaging>修改为<packaging>pom</packaging>,pom表示它是一个被继承的模块。修改后的pom.xml如下

 

[html] view plain copy
 
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.   <modelVersion>4.0.0</modelVersion>  
  4.   
  5.   <groupId>com.student.demo</groupId>  
  6.   <artifactId>student-demo</artifactId>  
  7.   <version>1.0.0-SNAPSHOT</version>  
  8.   <packaging>pom</packaging>  
  9.   
  10.   <name>student-demo</name>  
  11.   <url>http://maven.apache.org</url>  
  12.   
  13.   <properties>  
  14.     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  15.   </properties>  
  16.   <!--模块建立好以后自动生成的-->  
  17.    <modules>  
  18.       <module>student-service</module>  
  19.       <module>student-api</module>  
  20.       <module>student-web</module>  
  21.   </modules>  
  22.   <dependencies>  
  23.     <dependency>  
  24.       <groupId>junit</groupId>  
  25.       <artifactId>junit</artifactId>  
  26.       <version>3.8.1</version>  
  27.       <scope>test</scope>  
  28.     </dependency>  
  29.   </dependencies>  
  30. </project>  

 

在建成的项目student-demo上右键选择Maven Module后创建子项目student-api。

    

    填写子模块名字:

    

    项目类型选择:

    

    点击完成,建立好第一个模块后,同样的过程建立好student-service模块和student-web模块,需要注意的是student-web选择的maven类型是:

    

    修改子模块项目目录中的pom.xml文件,把<groupId>XXX</groupId>和<version>1.0.0-SNAPSHOT</version>去掉,加上<packaging>jar</packaging>,因为groupId和version会继承student-demo中的groupId和version,packaging设置打包方式为jar。例如修改后的student-service模块的pom.xml如下:

 

[html] view plain copy
 
  1. <?xml version="1.0"?>  
  2. <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
  4.   <modelVersion>4.0.0</modelVersion>  
  5.   <parent>  
  6.     <groupId>com.student.demo</groupId>  
  7.     <artifactId>student-demo</artifactId>  
  8.     <version>1.0.0-SNAPSHOT</version>  
  9.   </parent>  
  10.     
  11.   <artifactId>student-service</artifactId>  
  12.   <packaging>jar</packaging>  
  13. </project>  

 

至此,maven多模块项目已经创建完成,现在我们需要在student-demo项目的pom中增加<dependencyManagement>标签定义可被子项目继承的第三方依赖包,打包配置,资源插件等,同时注意统一定义依赖的版本,避免冲突。这里还利用Maven配置了profiles,可根据情况增加不同的运行环境,并方便快捷地切换项目运行环境,目前我们只设置了dev开发环境。

 

[html] view plain copy
 
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  3.   <modelVersion>4.0.0</modelVersion>  
  4.   
  5.   <groupId>com.student.demo</groupId>  
  6.   <artifactId>student-demo</artifactId>  
  7.   <version>1.0.0-SNAPSHOT</version>  
  8.   <packaging>pom</packaging>  
  9.   
  10.   <properties>  
  11.     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  12.     <dep.ver.lombok>1.16.10</dep.ver.lombok>  
  13.         <dep.ver.druid>1.0.1</dep.ver.druid>  
  14.         <dep.ver.mysql>5.1.21</dep.ver.mysql>  
  15.         <dep.ver.springframework>4.2.5.RELEASE</dep.ver.springframework>  
  16.         <dep.ver.mybatis>3.3.0</dep.ver.mybatis>  
  17.         <dep.ver.mybatis-spring>1.3.0</dep.ver.mybatis-spring>  
  18.         <dep.ver.pagehelper>4.1.6</dep.ver.pagehelper>  
  19.         <dep.ver.aspectjrt>1.5.4</dep.ver.aspectjrt>  
  20.         <dep.ver.aspectjweaver>1.8.0</dep.ver.aspectjweaver>  
  21.         <dep.ver.servlet>3.1.0</dep.ver.servlet>  
  22.         <dep.ver.orika-core>1.4.6</dep.ver.orika-core>  
  23.         <dep.ver.javassist>3.20.0-GA</dep.ver.javassist>  
  24.         <dep.ver.paranamer>2.7</dep.ver.paranamer>  
  25.         <dep.ver.concurrentlinkedhashmap-lru>1.4.2</dep.ver.concurrentlinkedhashmap-lru>  
  26.         <dep.ver.gson>2.2.4</dep.ver.gson>  
  27.         <dep.ver.guava>15.0</dep.ver.guava>  
  28.         <dep.ver.slf4j>1.7.21</dep.ver.slf4j>  
  29.         <dep.ver.logback>1.1.7</dep.ver.logback>  
  30.         <dep.ver.log4j>1.2.12</dep.ver.log4j>  
  31.         <dep.ver.slf4j-log4j12>1.7.5</dep.ver.slf4j-log4j12>  
  32.         <dep.ver.logback-ext-spring>0.1.2</dep.ver.logback-ext-spring>  
  33.         <dep.ver.dubbo>2.5.3</dep.ver.dubbo>  
  34.         <dep.ver.zookeeper>3.4.8</dep.ver.zookeeper>  
  35.         <dep.ver.zkclient>0.8</dep.ver.zkclient>  
  36.         <dep.ver.commons-lang3>3.1</dep.ver.commons-lang3>  
  37.         <dep.ver.jackson>1.9.12</dep.ver.jackson>  
  38.         <dep.ver.shiro>1.2.3</dep.ver.shiro>  
  39.         <dep.ver.freemarker>2.3.22</dep.ver.freemarker>  
  40.         <dep.ver.commons-beanutils>1.9.2</dep.ver.commons-beanutils>  
  41.         <dep.ver.junit>4.11</dep.ver.junit>  
  42.         <dep.ver.mockito>1.10.19</dep.ver.mockito>  
  43.         <dep.ver.joda-time>2.9.3</dep.ver.joda-time>  
  44.         <dep.ver.commons-collections4>4.1</dep.ver.commons-collections4>  
  45.         <dep.ver.httpclient>4.5.2</dep.ver.httpclient>  
  46.   
  47.         <dep.ver.fastjson>1.2.11</dep.ver.fastjson>  
  48.   
  49.         <plg.ver.maven-resources-plugin>2.7</plg.ver.maven-resources-plugin>  
  50.         <plg.ver.maven-compiler-plugin>2.5.1</plg.ver.maven-compiler-plugin>  
  51.         <plg.ver.maven-source-plugin>3.0.0</plg.ver.maven-source-plugin>  
  52.         <plg.ver.lombok-maven-plugin>1.14.8.0</plg.ver.lombok-maven-plugin>  
  53.   
  54.         <jdk.ver>1.8</jdk.ver>  
  55.         <encoding>UTF-8</encoding>  
  56.         <center.project.name>${project.artifactId}</center.project.name>  
  57.         <profiles.dir>src/profiles</profiles.dir>  
  58.         <jackson.version>2.6.0</jackson.version>  
  59.   </properties>  
  60.   <modules>  
  61.       <module>student-service</module>  
  62.       <module>student-api</module>  
  63.       <module>student-web</module>  
  64.   </modules>  
  65.     
  66.   <dependencies>  
  67.         <dependency>  
  68.             <groupId>org.hibernate</groupId>  
  69.             <artifactId>hibernate-validator</artifactId>  
  70.             <version>5.2.4.Final</version>  
  71.         </dependency>  
  72.     </dependencies>  
  73.     
  74.   <dependencyManagement>  
  75.         <dependencies>  
  76.             <!-- spring -->  
  77.             <dependency>  
  78.                 <groupId>org.springframework</groupId>  
  79.                 <artifactId>spring-core</artifactId>  
  80.                 <version>${dep.ver.springframework}</version>  
  81.                 <exclusions>  
  82.                     <exclusion>  
  83.                         <groupId>commons-logging</groupId>  
  84.                         <artifactId>commons-logging</artifactId>  
  85.                     </exclusion>  
  86.                 </exclusions>  
  87.             </dependency>  
  88.             <dependency>  
  89.                 <groupId>org.springframework</groupId>  
  90.                 <artifactId>spring-context</artifactId>  
  91.                 <version>${dep.ver.springframework}</version>  
  92.             </dependency>  
  93.             <dependency>  
  94.                 <groupId>org.springframework</groupId>  
  95.                 <artifactId>spring-context-support</artifactId>  
  96.                 <version>${dep.ver.springframework}</version>  
  97.             </dependency>  
  98.             <dependency>  
  99.                 <groupId>org.springframework</groupId>  
  100.                 <artifactId>spring-web</artifactId>  
  101.                 <version>${dep.ver.springframework}</version>  
  102.             </dependency>  
  103.             <dependency>  
  104.                 <groupId>org.springframework</groupId>  
  105.                 <artifactId>spring-webmvc</artifactId>  
  106.                 <version>${dep.ver.springframework}</version>  
  107.             </dependency>  
  108.             <dependency>  
  109.                 <groupId>org.springframework</groupId>  
  110.                 <artifactId>spring-jdbc</artifactId>  
  111.                 <version>${dep.ver.springframework}</version>  
  112.             </dependency>  
  113.             <dependency>  
  114.                 <groupId>org.springframework</groupId>  
  115.                 <artifactId>spring-tx</artifactId>  
  116.                 <version>${dep.ver.springframework}</version>  
  117.             </dependency>  
  118.             <dependency>  
  119.                 <groupId>org.springframework</groupId>  
  120.                 <artifactId>spring-aspects</artifactId>  
  121.                 <version>${dep.ver.springframework}</version>  
  122.             </dependency>  
  123.             <!-- spring -->  
  124.             <!-- db -->  
  125.             <dependency>  
  126.                 <groupId>com.alibaba</groupId>  
  127.                 <artifactId>druid</artifactId>  
  128.                 <version>${dep.ver.druid}</version>  
  129.             </dependency>  
  130.             <dependency>  
  131.                 <groupId>mysql</groupId>  
  132.                 <artifactId>mysql-connector-java</artifactId>  
  133.                 <version>${dep.ver.mysql}</version>  
  134.             </dependency>  
  135.             <!-- db -->  
  136.             <!-- mybatis -->  
  137.             <dependency>  
  138.                 <groupId>org.mybatis</groupId>  
  139.                 <artifactId>mybatis</artifactId>  
  140.                 <version>${dep.ver.mybatis}</version>  
  141.             </dependency>  
  142.             <dependency>  
  143.                 <groupId>org.mybatis</groupId>  
  144.                 <artifactId>mybatis-spring</artifactId>  
  145.                 <version>${dep.ver.mybatis-spring}</version>  
  146.             </dependency>  
  147.             <dependency>  
  148.                 <groupId>com.github.pagehelper</groupId>  
  149.                 <artifactId>pagehelper</artifactId>  
  150.                 <version>${dep.ver.pagehelper}</version>  
  151.             </dependency>  
  152.             <!-- mybatis -->  
  153.             <!-- apache -->  
  154.             <dependency>  
  155.                 <groupId>org.apache.commons</groupId>  
  156.                 <artifactId>commons-lang3</artifactId>  
  157.                 <version>${dep.ver.commons-lang3}</version>  
  158.             </dependency>  
  159.             <!-- apache -->  
  160.             <!-- commons-beanutils -->  
  161.             <dependency>  
  162.                 <groupId>commons-beanutils</groupId>  
  163.                 <artifactId>commons-beanutils</artifactId>  
  164.                 <version>${dep.ver.commons-beanutils}</version>  
  165.                 <exclusions>  
  166.                     <exclusion>  
  167.                         <groupId>commons-logging</groupId>  
  168.                         <artifactId>commons-logging</artifactId>  
  169.                     </exclusion>  
  170.                 </exclusions>  
  171.             </dependency>  
  172.             <!-- commons-beanutils -->  
  173.             <!-- log -->  
  174.             <dependency>  
  175.                 <groupId>org.slf4j</groupId>  
  176.                 <artifactId>slf4j-api</artifactId>  
  177.                 <version>${dep.ver.slf4j}</version>  
  178.             </dependency>  
  179.             <dependency>  
  180.                 <groupId>org.slf4j</groupId>  
  181.                 <artifactId>log4j-over-slf4j</artifactId>  
  182.                 <version>${dep.ver.slf4j}</version>  
  183.             </dependency>  
  184.             <dependency>  
  185.                 <groupId>org.slf4j</groupId>  
  186.                 <artifactId>jcl-over-slf4j</artifactId>  
  187.                 <version>${dep.ver.slf4j}</version>  
  188.             </dependency>  
  189.             <dependency>  
  190.                 <groupId>ch.qos.logback</groupId>  
  191.                 <artifactId>logback-classic</artifactId>  
  192.                 <version>${dep.ver.logback}</version>  
  193.             </dependency>  
  194.             <!-- log -->  
  195.             <!-- dubbo -->  
  196.             <dependency>  
  197.                 <groupId>com.alibaba</groupId>  
  198.                 <artifactId>dubbo</artifactId>  
  199.                 <version>${dep.ver.dubbo}</version>  
  200.                 <exclusions>  
  201.                     <exclusion>  
  202.                         <artifactId>spring</artifactId>  
  203.                         <groupId>org.springframework</groupId>  
  204.                     </exclusion>  
  205.                     <exclusion>  
  206.                         <artifactId>netty</artifactId>  
  207.                         <groupId>org.jboss.netty</groupId>  
  208.                     </exclusion>  
  209.                 </exclusions>  
  210.             </dependency>  
  211.             <!-- dubbo -->  
  212.             <!-- zookeeper -->  
  213.             <dependency>  
  214.                 <groupId>org.apache.zookeeper</groupId>  
  215.                 <artifactId>zookeeper</artifactId>  
  216.                 <version>${dep.ver.zookeeper}</version>  
  217.                 <exclusions>  
  218.                     <exclusion>  
  219.                         <groupId>log4j</groupId>  
  220.                         <artifactId>log4j</artifactId>  
  221.                     </exclusion>  
  222.                 </exclusions>  
  223.             </dependency>  
  224.             <dependency>  
  225.                 <groupId>com.101tec</groupId>  
  226.                 <artifactId>zkclient</artifactId>  
  227.                 <version>${dep.ver.zkclient}</version>  
  228.                 <exclusions>  
  229.                     <exclusion>  
  230.                         <groupId>log4j</groupId>  
  231.                         <artifactId>log4j</artifactId>  
  232.                     </exclusion>  
  233.                 </exclusions>  
  234.             </dependency>  
  235.             <!-- zookeeper -->  
  236.             <!-- jackson -->  
  237.             <dependency>  
  238.                 <groupId>org.codehaus.jackson</groupId>  
  239.                 <artifactId>jackson-core-asl</artifactId>  
  240.                 <version>${dep.ver.jackson}</version>  
  241.             </dependency>  
  242.             <dependency>  
  243.                 <groupId>org.codehaus.jackson</groupId>  
  244.                 <artifactId>jackson-mapper-asl</artifactId>  
  245.                 <version>${dep.ver.jackson}</version>  
  246.             </dependency>  
  247.             <!-- jackson -->  
  248.             <!-- aspectj -->  
  249.             <dependency>  
  250.                 <groupId>aspectj</groupId>  
  251.                 <artifactId>aspectjrt</artifactId>  
  252.                 <version>${dep.ver.aspectjrt}</version>  
  253.             </dependency>  
  254.             <dependency>  
  255.                 <groupId>org.aspectj</groupId>  
  256.                 <artifactId>aspectjweaver</artifactId>  
  257.                 <version>${dep.ver.aspectjweaver}</version>  
  258.             </dependency>  
  259.             <!-- aspectj -->  
  260.             <!-- servlet -->  
  261.             <dependency>  
  262.                 <groupId>javax.servlet</groupId>  
  263.                 <artifactId>javax.servlet-api</artifactId>  
  264.                 <version>${dep.ver.servlet}</version>  
  265.                 <scope>provided</scope>  
  266.             </dependency>  
  267.             <!-- servlet -->  
  268.             <!-- javassist -->  
  269.             <dependency>  
  270.                 <groupId>org.javassist</groupId>  
  271.                 <artifactId>javassist</artifactId>  
  272.                 <version>${dep.ver.javassist}</version>  
  273.             </dependency>  
  274.             <!-- javassist -->  
  275.             <!-- test start -->  
  276.             <dependency>  
  277.                 <groupId>junit</groupId>  
  278.                 <artifactId>junit</artifactId>  
  279.                 <version>${dep.ver.junit}</version>  
  280.                 <scope>test</scope>  
  281.             </dependency>  
  282.             <dependency>  
  283.                 <groupId>org.springframework</groupId>  
  284.                 <artifactId>spring-test</artifactId>  
  285.                 <version>${dep.ver.springframework}</version>  
  286.                 <scope>test</scope>  
  287.             </dependency>  
  288.             <dependency>  
  289.                 <groupId>org.mockito</groupId>  
  290.                 <artifactId>mockito-core</artifactId>  
  291.                 <version>${dep.ver.mockito}</version>  
  292.                 <scope>test</scope>  
  293.             </dependency>  
  294.             <!-- test end -->  
  295.             <!-- google -->  
  296.             <dependency>  
  297.                 <groupId>com.google.code.gson</groupId>  
  298.                 <artifactId>gson</artifactId>  
  299.                 <version>${dep.ver.gson}</version>  
  300.             </dependency>  
  301.             <dependency>  
  302.                 <groupId>com.google.guava</groupId>  
  303.                 <artifactId>guava</artifactId>  
  304.                 <version>${dep.ver.guava}</version>  
  305.             </dependency>  
  306.             <!-- google -->  
  307.             <!-- lombok -->  
  308.             <dependency>  
  309.                 <groupId>org.projectlombok</groupId>  
  310.                 <artifactId>lombok</artifactId>  
  311.                 <version>${dep.ver.lombok}</version>  
  312.             </dependency>  
  313.             <!-- lombok -->  
  314.             <dependency>  
  315.                 <groupId>org.apache.commons</groupId>  
  316.                 <artifactId>commons-collections4</artifactId>  
  317.                 <version>${dep.ver.commons-collections4}</version>  
  318.             </dependency>  
  319.             <dependency>  
  320.                 <groupId>org.apache.httpcomponents</groupId>  
  321.                 <artifactId>httpclient</artifactId>  
  322.                 <version>${dep.ver.httpclient}</version>  
  323.                 <exclusions>  
  324.                     <exclusion>  
  325.                         <groupId>commons-logging</groupId>  
  326.                         <artifactId>commons-logging</artifactId>  
  327.                     </exclusion>  
  328.                 </exclusions>  
  329.             </dependency>  
  330.         </dependencies>  
  331.     </dependencyManagement>  
  332.     
  333.   <profiles>  
  334.         <profile>  
  335.             <id>local</id>  
  336.             <build>  
  337.                 <resources>  
  338.                     <resource>  
  339.                         <directory>${profiles.dir}/local</directory>  
  340.                     </resource>  
  341.                 </resources>  
  342.             </build>  
  343.         </profile>  
  344.   
  345.         <profile>  
  346.             <id>dev</id>  
  347.             <build>  
  348.                 <resources>  
  349.                     <resource>  
  350.                         <directory>${profiles.dir}/dev</directory>  
  351.                     </resource>  
  352.                 </resources>  
  353.             </build>  
  354.         </profile>  
  355.     </profiles>  
  356.   
  357.     <build>  
  358.         <finalName>${center.project.name}</finalName>  
  359.   
  360.         <plugins>  
  361.             <plugin>  
  362.                 <groupId>org.apache.maven.plugins</groupId>  
  363.                 <artifactId>maven-resources-plugin</artifactId>  
  364.                 <version>${plg.ver.maven-resources-plugin}</version>  
  365.                 <configuration>  
  366.                     <encoding>${encoding}</encoding>  
  367.                 </configuration>  
  368.             </plugin>  
  369.             <plugin>  
  370.                 <groupId>org.apache.maven.plugins</groupId>  
  371.                 <artifactId>maven-compiler-plugin</artifactId>  
  372.                 <version>${plg.ver.maven-compiler-plugin}</version>  
  373.                 <configuration>  
  374.                     <source>${jdk.ver}</source>  
  375.                     <target>${jdk.ver}</target>  
  376.                     <encoding>${encoding}</encoding>  
  377.                 </configuration>  
  378.             </plugin>  
  379.             <plugin>  
  380.                 <artifactId>maven-source-plugin</artifactId>  
  381.                 <version>${plg.ver.maven-source-plugin}</version>  
  382.                 <configuration>  
  383.                     <attach>true</attach>  
  384.                 </configuration>   
  385.                 <executions>  
  386.                     <execution>  
  387.                         <phase>compile</phase>  
  388.                         <goals>  
  389.                             <goal>jar</goal>  
  390.                         </goals>  
  391.                     </execution>  
  392.                 </executions>  
  393.             </plugin>  
  394.         </plugins>  
  395.         <resources>  
  396.             <resource>  
  397.                 <directory>src/main/resources</directory>  
  398.                 <filtering>true</filtering>  
  399.             </resource>  
  400.         </resources>  
  401.     </build>  
  402. </project>  

 

在student-api中继承父pom的依赖,并且直接引入。

 

[html] view plain copy
 
  1. <?xml version="1.0"?>  
  2. <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
  4.   <modelVersion>4.0.0</modelVersion>  
  5.   <parent>  
  6.     <groupId>com.student.demo</groupId>  
  7.     <artifactId>student-demo</artifactId>  
  8.     <version>1.0.0-SNAPSHOT</version>  
  9.   </parent>  
  10.   <artifactId>student-api</artifactId>  
  11.    
  12.  <dependencies>  
  13.         <dependency>  
  14.             <groupId>com.alibaba</groupId>  
  15.             <artifactId>fastjson</artifactId>  
  16.             <version>${dep.ver.fastjson}</version>  
  17.         </dependency>  
  18.   
  19.         <dependency>  
  20.             <groupId>org.springframework</groupId>  
  21.             <artifactId>spring-context</artifactId>  
  22.         </dependency>  
  23.         <dependency>  
  24.             <groupId>org.springframework</groupId>  
  25.             <artifactId>spring-web</artifactId>  
  26.         </dependency>  
  27.         <dependency>  
  28.             <groupId>org.apache.httpcomponents</groupId>  
  29.             <artifactId>httpclient</artifactId>  
  30.         </dependency>  
  31.         <!-- google -->  
  32.         <dependency>  
  33.             <groupId>com.google.code.gson</groupId>  
  34.             <artifactId>gson</artifactId>  
  35.         </dependency>  
  36.         <dependency>  
  37.             <groupId>com.google.guava</groupId>  
  38.             <artifactId>guava</artifactId>  
  39.         </dependency>  
  40.         <!-- google -->  
  41.   
  42.     </dependencies>  
  43. </project>  

 

在student-service中添加继承依赖,添加对student-api的依赖。

 

[html] view plain copy
 
  1. <?xml version="1.0"?>  
  2. <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
  4.   <modelVersion>4.0.0</modelVersion>  
  5.   <parent>  
  6.     <groupId>com.student.demo</groupId>  
  7.     <artifactId>student-demo</artifactId>  
  8.     <version>1.0.0-SNAPSHOT</version>  
  9.   </parent>  
  10.   <artifactId>student-service</artifactId>  
  11.   
  12.   <dependencies>  
  13.         <dependency>  
  14.             <groupId>com.student.demo</groupId>  
  15.             <artifactId>student-api</artifactId>  
  16.             <version>1.0.0-SNAPSHOT</version>  
  17.         </dependency>  
  18.   
  19.         <dependency>  
  20.             <groupId>com.alibaba</groupId>  
  21.             <artifactId>fastjson</artifactId>  
  22.             <version>${dep.ver.fastjson}</version>  
  23.         </dependency>  
  24.   
  25.         <!-- oss相关依赖 -->  
  26.         <dependency>  
  27.             <groupId>com.aliyun.oss</groupId>  
  28.             <artifactId>aliyun-sdk-oss</artifactId>  
  29.             <version>2.0.7</version>  
  30.             <exclusions>  
  31.                 <exclusion>  
  32.                     <groupId>commons-logging</groupId>  
  33.                     <artifactId>commons-logging</artifactId>  
  34.                 </exclusion>  
  35.             </exclusions>  
  36.         </dependency>  
  37.         <!-- oss相关依赖 结束 -->  
  38.   
  39.         <!-- db -->  
  40.         <dependency>  
  41.             <groupId>com.alibaba</groupId>  
  42.             <artifactId>druid</artifactId>  
  43.         </dependency>  
  44.         <dependency>  
  45.             <groupId>mysql</groupId>  
  46.             <artifactId>mysql-connector-java</artifactId>  
  47.         </dependency>  
  48.         <!-- db -->  
  49.   
  50.         <!-- mybatis -->  
  51.         <dependency>  
  52.             <groupId>org.mybatis</groupId>  
  53.             <artifactId>mybatis</artifactId>  
  54.         </dependency>  
  55.         <dependency>  
  56.             <groupId>org.mybatis</groupId>  
  57.             <artifactId>mybatis-spring</artifactId>  
  58.         </dependency>  
  59.         <dependency>  
  60.             <groupId>com.github.pagehelper</groupId>  
  61.             <artifactId>pagehelper</artifactId>  
  62.         </dependency>  
  63.         <!-- mybatis -->  
  64.   
  65.         <!-- spring配置 -->  
  66.         <dependency>  
  67.             <groupId>org.springframework</groupId>  
  68.             <artifactId>spring-core</artifactId>  
  69.         </dependency>  
  70.         <dependency>  
  71.             <groupId>org.springframework</groupId>  
  72.             <artifactId>spring-context</artifactId>  
  73.         </dependency>  
  74.         <dependency>  
  75.             <groupId>org.springframework</groupId>  
  76.             <artifactId>spring-webmvc</artifactId>  
  77.         </dependency>  
  78.         <dependency>  
  79.             <groupId>org.springframework</groupId>  
  80.             <artifactId>spring-jdbc</artifactId>  
  81.         </dependency>  
  82.         <dependency>  
  83.             <groupId>org.springframework</groupId>  
  84.             <artifactId>spring-context-support</artifactId>  
  85.         </dependency>  
  86.         <dependency>  
  87.             <groupId>org.springframework</groupId>  
  88.             <artifactId>spring-tx</artifactId>  
  89.         </dependency>  
  90.         <dependency>  
  91.             <groupId>org.springframework</groupId>  
  92.             <artifactId>spring-aspects</artifactId>  
  93.         </dependency>  
  94.         <!-- spring配置 -->  
  95.   
  96.         <!-- jackson -->  
  97.         <!-- <dependency> -->  
  98.         <!-- <groupId>org.codehaus.jackson</groupId> -->  
  99.         <!-- <artifactId>jackson-core-asl</artifactId> -->  
  100.         <!-- </dependency> -->  
  101.         <!-- <dependency> -->  
  102.         <!-- <groupId>org.codehaus.jackson</groupId> -->  
  103.         <!-- <artifactId>jackson-mapper-asl</artifactId> -->  
  104.         <!-- </dependency> -->  
  105.         <dependency>  
  106.             <groupId>com.fasterxml.jackson.core</groupId>  
  107.             <artifactId>jackson-core</artifactId>  
  108.             <version>${jackson.version}</version>  
  109.         </dependency>  
  110.         <dependency>  
  111.             <groupId>com.fasterxml.jackson.core</groupId>  
  112.             <artifactId>jackson-databind</artifactId>  
  113.             <version>${jackson.version}</version>  
  114.         </dependency>  
  115.         <dependency>  
  116.             <groupId>com.fasterxml.jackson.core</groupId>  
  117.             <artifactId>jackson-annotations</artifactId>  
  118.             <version>${jackson.version}</version>  
  119.         </dependency>  
  120.         <!-- jackson -->  
  121.   
  122.         <!-- log -->  
  123.         <dependency>  
  124.             <groupId>org.slf4j</groupId>  
  125.             <artifactId>slf4j-api</artifactId>  
  126.         </dependency>  
  127.         <dependency>  
  128.             <groupId>ch.qos.logback</groupId>  
  129.             <artifactId>logback-classic</artifactId>  
  130.         </dependency>  
  131.         <dependency>  
  132.             <groupId>org.slf4j</groupId>  
  133.             <artifactId>log4j-over-slf4j</artifactId>  
  134.         </dependency>  
  135.         <dependency>  
  136.             <groupId>org.slf4j</groupId>  
  137.             <artifactId>jcl-over-slf4j</artifactId>  
  138.         </dependency>  
  139.         <!-- log -->  
  140.   
  141.         <!-- google -->  
  142.         <dependency>  
  143.             <groupId>com.google.guava</groupId>  
  144.             <artifactId>guava</artifactId>  
  145.         </dependency>  
  146.         <!-- <dependency> -->  
  147.         <!-- <groupId>com.google.code.gson</groupId> -->  
  148.         <!-- <artifactId>gson</artifactId> -->  
  149.         <!-- </dependency> -->  
  150.         <!-- google -->  
  151.   
  152.         <dependency>  
  153.             <groupId>org.apache.commons</groupId>  
  154.             <artifactId>commons-lang3</artifactId>  
  155.         </dependency>  
  156.   
  157.         <dependency>  
  158.             <groupId>commons-beanutils</groupId>  
  159.             <artifactId>commons-beanutils</artifactId>  
  160.         </dependency>  
  161.   
  162.         <dependency>  
  163.             <groupId>javax.servlet</groupId>  
  164.             <artifactId>javax.servlet-api</artifactId>  
  165.         </dependency>  
  166.   
  167.         <dependency>  
  168.             <groupId>org.javassist</groupId>  
  169.             <artifactId>javassist</artifactId>  
  170.         </dependency>  
  171.   
  172.         <!-- aspectj -->  
  173.         <dependency>  
  174.             <groupId>aspectj</groupId>  
  175.             <artifactId>aspectjrt</artifactId>  
  176.         </dependency>  
  177.         <dependency>  
  178.             <groupId>org.aspectj</groupId>  
  179.             <artifactId>aspectjweaver</artifactId>  
  180.         </dependency>  
  181.         <!-- aspectj -->  
  182.   
  183.         <!-- dubbo -->  
  184.         <dependency>  
  185.             <groupId>com.alibaba</groupId>  
  186.             <artifactId>dubbo</artifactId>  
  187.             <exclusions>  
  188.                 <exclusion>  
  189.                     <artifactId>spring</artifactId>  
  190.                     <groupId>org.springframework</groupId>  
  191.                 </exclusion>  
  192.                 <exclusion>  
  193.                     <artifactId>netty</artifactId>  
  194.                     <groupId>org.jboss.netty</groupId>  
  195.                 </exclusion>  
  196.             </exclusions>  
  197.         </dependency>  
  198.         <dependency>  
  199.             <groupId>org.apache.zookeeper</groupId>  
  200.             <artifactId>zookeeper</artifactId>  
  201.             <exclusions>  
  202.                 <exclusion>  
  203.                     <groupId>org.slf4j</groupId>  
  204.                     <artifactId>slf4j-log4j12</artifactId>  
  205.                 </exclusion>  
  206.             </exclusions>  
  207.         </dependency>  
  208.         <dependency>  
  209.             <groupId>com.101tec</groupId>  
  210.             <artifactId>zkclient</artifactId>  
  211.             <exclusions>  
  212.                 <exclusion>  
  213.                     <groupId>org.slf4j</groupId>  
  214.                     <artifactId>slf4j-log4j12</artifactId>  
  215.                 </exclusion>  
  216.             </exclusions>  
  217.         </dependency>  
  218.         <!-- dubbo -->  
  219.   
  220.         <dependency>  
  221.             <groupId>org.apache.httpcomponents</groupId>  
  222.             <artifactId>httpclient</artifactId>  
  223.         </dependency>  
  224.   
  225.         <dependency>  
  226.             <groupId>cglib</groupId>  
  227.             <artifactId>cglib</artifactId>  
  228.             <version>3.1</version>  
  229.         </dependency>  
  230.     </dependencies>  
  231. </project>  

 

在student-web中继承依赖,添加对student-api,student-service的依赖。注意子项目依赖版本都为<version>1.0.0-SNAPSHOT</version>

 

[html] view plain copy
 
  1. <?xml version="1.0"?>  
  2. <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
  4.   <modelVersion>4.0.0</modelVersion>  
  5.   <parent>  
  6.     <groupId>com.student.demo</groupId>  
  7.     <artifactId>student-demo</artifactId>  
  8.     <version>1.0.0-SNAPSHOT</version>  
  9.   </parent>  
  10.   <artifactId>student-web</artifactId>  
  11.   <packaging>war</packaging>  
  12.   <dependencies>  
  13.         <dependency>  
  14.             <groupId>junit</groupId>  
  15.             <artifactId>junit</artifactId>  
  16.         </dependency>  
  17.       
  18.         <dependency>  
  19.             <groupId>com.student.demo</groupId>  
  20.             <artifactId>student-api</artifactId>  
  21.             <version>1.0.0-SNAPSHOT</version>  
  22.         </dependency>  
  23.         <dependency>  
  24.             <groupId>com.student.demo</groupId>  
  25.             <artifactId>student-service</artifactId>  
  26.             <version>1.0.0-SNAPSHOT</version>  
  27.         </dependency>  
  28.     </dependencies>  
  29.   <build>  
  30.     <finalName>student-web</finalName>  
  31.   </build>  
  32. </project>  

 

  二、Maven与SpringMVC的整合

    1.第一部分已经在项目pom文件中配置了spring的相关依赖

    2.在student-web项目根路径上添加profiles源目录及配置文件

     注意是建立源文件不是普通文件夹。

     

     然后在此源文件夹下建立普通文件夹props,用于存放配置文件。在props下新建db-config.properties资源文件,用于配置mysql,其配置内容为:

1 database.database=mysql
2 database.driverClassName=com.mysql.jdbc.Driver
3 database.url=jdbc:mysql://172.0.0.1:3306/student_data?characterEncoding=utf8
4 database.user=root
5 database.password=root
6 database.show_sql=true

     在mysql数据库中建立一张简单的student数据表,其结构为:

     

     3.在student-web的src/main/resources目录中新建spring文件夹,新建spring-base.xml和spring-dispatcher.xml。其中值得说明一下的是,spring监听器ContextLoaderListener和控制器DispatcherServlet会加载应用上下文。其中上下文参数contextConfigLocation的value值是根应用上下文路径classpath:spring/spring-base.xml,它会被ContextLoaderListener加载bean定义。spring-base.xml中的内容为:

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.         http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.         http://www.springframework.org/schema/aop  
  8.         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd  
  9.         http://www.springframework.org/schema/context   
  10.         http://www.springframework.org/schema/context/spring-context-4.0.xsd">  
  11.   
  12.     <!-- 开启aspectj自动注解 -->  
  13.     <aop:aspectj-autoproxy proxy-target-class="true" />  
  14.   
  15.     <context:component-scan base-package="org.student" />  
  16.     <context:annotation-config />  
  17.   
  18.     <!-- 配置文件加载 -->  
  19.     <bean id="propertyConfigurer"  
  20.         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  21.         <property name="order" value="1" />  
  22.         <property name="ignoreUnresolvablePlaceholders" value="true" />  
  23.         <property name="locations">  
  24.             <list>  
  25.                 <value>classpath:props/db-config.properties</value>  
  26.             </list>  
  27.         </property>  
  28.     </bean>  
  29.     <import resource="classpath:spring/spring-db.xml" />  
  30. </beans>  

 

     同样DispatcherServlet会从classpath:spring/spring-dispatcher.xml加载它的bean。

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.                         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  7.                         http://www.springframework.org/schema/context  
  8.                         http://www.springframework.org/schema/context/spring-context-3.0.xsd   
  9.                         http://www.springframework.org/schema/mvc   
  10.                         http://www.springframework.org/schema/mvc/spring-mvc.xsd">  
  11.   
  12.     <mvc:annotation-driven>  
  13.         <mvc:message-converters>  
  14.             <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter " />  
  15.         </mvc:message-converters>  
  16.     </mvc:annotation-driven>  
  17.   
  18.     <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />  
  19.     <!-- 相当于注册了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter两个bean,配置一些messageconverter。即解决了@Controller注解的使用前提配置 -->  
  20. </beans>  

 

   4.在Web.xml中声明DispatcherServlet

     SpringMVC所有请求都会通过一个前端控制器DispatcherServlet,通过这个控制器将请求委托给应用程序的其它执行单元来处理,所以需要通过web.xml来注册。打开student-web项目目录下src/main/webapp/WEB-INF/web.xml,修改web.xml

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns="http://java.sun.com/xml/ns/javaee"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
  5.     id="schedule-console" version="3.0">  
  6.     <display-name>student-web</display-name>  
  7.   
  8.     <!-- web.xml中加载顺序是 context-param -> listener -> filter -> servlet -->  
  9.     <!-- spring基础配置文件位置 -->  
  10.     <context-param>  
  11.         <param-name>contextConfigLocation</param-name>  
  12.         <param-value>classpath:spring/spring-base.xml</param-value>  
  13.     </context-param>  
  14.   
  15.     <!-- Spring监听 -->  
  16.     <listener>  
  17.         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  18.     </listener>  
  19.     <!-- 设置servlet编码开始 -->  
  20.     <filter>  
  21.         <filter-name>characterEncodingFilter</filter-name>  
  22.         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
  23.         <init-param>  
  24.             <param-name>encoding</param-name>  
  25.             <param-value>UTF-8</param-value>  
  26.         </init-param>  
  27.         <init-param>  
  28.             <param-name>forceEncoding</param-name>  
  29.             <param-value>true</param-value>  
  30.         </init-param>  
  31.     </filter>  
  32.     <filter-mapping>  
  33.         <filter-name>characterEncodingFilter</filter-name>  
  34.         <url-pattern>/*</url-pattern>  
  35.     </filter-mapping>  
  36.     <!-- 设置servlet编码结束 -->  
  37.     <servlet>  
  38.         <servlet-name>dispatcher</servlet-name>  
  39.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  40.         <init-param>  
  41.             <param-name>contextConfigLocation</param-name>  
  42.             <param-value>classpath:spring/spring-dispatcher.xml</param-value>  
  43.         </init-param>  
  44.     </servlet>  
  45.     <servlet-mapping>  
  46.         <servlet-name>dispatcher</servlet-name>  
  47.         <url-pattern>/</url-pattern>  
  48.     </servlet-mapping>  
  49. </web-app>  

 

     5.spring与Mybatis的整合

     在student-web的src/main/resources目录中新建mybatis文件夹,再在此目录新建mybatis.xml和mapper文件夹。在spring文件夹下新建spring-db.xml用于spring加载mybatis配置。spring-db.xml内容如下:

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
  7.         http://www.springframework.org/schema/context     
  8.         http://www.springframework.org/schema/context/spring-context-4.0.xsd  
  9.         http://www.springframework.org/schema/tx   
  10.         http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">  
  11.   
  12.     <!-- 采用druid作为连接池 -->  
  13.     <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"  
  14.         init-method="init" destroy-method="close">  
  15.         <!-- 基本属性 url、user、password -->  
  16.         <property name="driverClassName" value="${database.driverClassName}" />  
  17.         <property name="url" value="${database.url}" />  
  18.         <property name="username" value="${database.user}" />  
  19.         <property name="password" value="${database.password}" />  
  20.   
  21.         <!-- 配置初始化大小、最小、最大 -->  
  22.         <property name="initialSize" value="1" />  
  23.         <property name="minIdle" value="1" />  
  24.         <property name="maxActive" value="20" />  
  25.   
  26.         <!-- 配置获取连接等待超时的时间 -->  
  27.         <property name="maxWait" value="60000" />  
  28.   
  29.         <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->  
  30.         <property name="timeBetweenEvictionRunsMillis" value="60000" />  
  31.   
  32.         <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->  
  33.         <property name="minEvictableIdleTimeMillis" value="300000" />  
  34.         <property name="validationQuery" value="SELECT 'x'" />  
  35.         <property name="testWhileIdle" value="true" />  
  36.         <property name="testOnBorrow" value="false" />  
  37.         <property name="testOnReturn" value="false" />  
  38.   
  39.         <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->  
  40.         <property name="poolPreparedStatements" value="true" />  
  41.         <property name="maxPoolPreparedStatementPerConnectionSize"  
  42.             value="20" />  
  43.   
  44.         <!-- 配置监控统计拦截的filters -->  
  45.         <property name="filters" value="stat" />  
  46.     </bean>  
  47.   
  48.     <!-- 配置mybatis的sqlSessionFactory -->  
  49.     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  50.         <property name="dataSource" ref="dataSource" />  
  51.         <property name="configLocation" value="classpath:mybatis/mybatis.xml" />  
  52.         <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml" />  
  53.     </bean>  
  54.   
  55.     <!-- mybatis mapper接口扫描 -->  
  56.     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  57.         <property name="basePackage" value="org.student.service.mapper" />  
  58.         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />  
  59.     </bean>  
  60.   
  61.     <bean id="transactionManager"  
  62.         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  63.         <property name="dataSource" ref="dataSource" />  
  64.     </bean>  
  65.   
  66.     <!-- 开启@Transactional事务注解 -->  
  67.     <tx:annotation-driven transaction-manager="transactionManager" />  
  68. </beans>  

 

    三、Dubbo的环境配置及与整合

     我们已经搭建好student-demo项目来作为provider,为其它服务提供接口,所以我们需要先配置好dubbo提供者,PS:这里不会讲解zookeeper的搭建,请自行百度。其项目结构为:

      

     1.首先在student-web中配置dubbo

     由于我们已经在student-demo中添加了dubbo和zookeeper的相关依赖,下一步字啊resources目录中建立dubbo文件夹,再新建dubbo-producer.xml,同时在profiles的dev环境中添加dubbo-producer.properties配置文件,设置zookeeper注册中心暴露服务地址,配置group分组,服务端口,注册中心请求超时时间(毫秒)和版本。其中组别+接口地址+版本号唯一的标识了一个接口。文件内容为:

1 student-registry-address=172.0.0.1:2181
2 student-group=student-min
3 student-service-port=22026
4 student-timeout=120000
5 student-version=1.0.0

     这样我们就可以来配置dubbo-producer.xml

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:context="http://www.springframework.org/schema/context"  
  4.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans  
  7.     http://www.springframework.org/schema/beans/spring-beans.xsd      
  8.     http://www.springframework.org/schema/beans   
  9.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  10.     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  11.     http://code.alibabatech.com/schema/dubbo   
  12.     http://code.alibabatech.com/schema/dubbo/dubbo.xsd">  
  13.       
  14.     <context:property-placeholder location="classpath:props/dubbo-producer.properties" ignore-unresolvable="true"/>  
  15.       
  16.     <dubbo:application name="provider-student-demo"/>  
  17.     <dubbo:registry address="${student-registry-address}" protocol="zookeeper"/>  
  18.     <dubbo:protocol name="dubbo" port="${student-service-port}" accesslog="true" />  
  19. </beans>  

 

     2.写一个简单的服务接口

     1)首先在student-service中建立Student实体类

 

[java] view plain copy
 
  1. package org.student.bean;  
  2.   
  3. public class Student {  
  4.     private Long id;  
  5.     private String name;  
  6.     private Integer age;  
  7.     public Long getId() {  
  8.         return id;  
  9.     }  
  10.     public void setId(Long id) {  
  11.         this.id = id;  
  12.     }  
  13.     public String getName() {  
  14.         return name;  
  15.     }  
  16.     public void setName(String name) {  
  17.         this.name = name;  
  18.     }  
  19.     public Integer getAge() {  
  20.         return age;  
  21.     }  
  22.     public void setAge(Integer age) {  
  23.         this.age = age;  
  24.     }  
  25.       
  26. }  

 

     2)同时在student-api中建立与实体bean对应的DTO类实现Serializable接口,并重写toString方法。一般为了不破坏实体类和数据库表一一对应的接口,我们会新建一个DTO实体类,并且加入一些冗余的字段,作为前后端的传输对象。

 

[java] view plain copy
 
  1. package org.student.api.dto;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. public class StudentDTO implements Serializable{  
  6.       
  7.     private static final long serialVersionUID = 1L;  
  8.     private Long id;  
  9.     private String name;  
  10.     private Integer age;  
  11.     public Long getId() {  
  12.         return id;  
  13.     }  
  14.     public void setId(Long id) {  
  15.         this.id = id;  
  16.     }  
  17.     public String getName() {  
  18.         return name;  
  19.     }  
  20.     public void setName(String name) {  
  21.         this.name = name;  
  22.     }  
  23.     public Integer getAge() {  
  24.         return age;  
  25.     }  
  26.     public void setAge(Integer age) {  
  27.         this.age = age;  
  28.     }  
  29.       
  30.     @Override  
  31.     public String toString() {  
  32.         return "id = " + id + ", name = " + name + ",age = " + age;  
  33.     }  
  34. }  

 

     3)在student-api中建立StudentApi接口,值得注意的是@service注解中的对象

 

[java] view plain copy
 
  1. package org.student.api;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.student.api.dto.StudentDTO;  
  6.   
  7. public interface StudentApi {  
  8.     List<StudentDTO> listStudents();  
  9. }  

 

      4)在dubbo-producer.xml中注册StudentApi,添加配置:

<dubbo:service interface="org.student.api.StudentApi" ref="studentApi"   group="${student-group}" version="${student-version}" timeout="${student-timeout}" />

     5)从service业务逻辑层子模块开始编写接口实现,新建在student-service中新建StudentBiz实现StudentApi接口

 

[java] view plain copy
 
  1. package org.student.service.biz;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.beans.factory.annotation.Autowired;  
  8. import org.springframework.stereotype.Service;  
  9. import org.student.api.StudentApi;  
  10. import org.student.api.dto.StudentDTO;  
  11. import org.student.bean.Student;  
  12. import org.student.service.StudentService;  
  13.   
  14. import com.google.common.collect.Lists;  
  15.   
  16. @Service("studentApi")  
  17. public class StudentBiz implements StudentApi{  
  18.     private Logger logger = LoggerFactory.getLogger(StudentBiz.class);  
  19.       
  20.     @Autowired  
  21.     private StudentService studentService;  
  22.       
  23.     @Override  
  24.     public List<StudentDTO> listStudents() {  
  25.         List<Student> listStudent = studentService.listStudent();  
  26.         List<StudentDTO> listStudentDTO = Lists.newArrayList();  
  27.         for(Student student: listStudent){  
  28.             StudentDTO studentDTO = new StudentDTO();  
  29.             studentDTO.setId(student.getId());  
  30.             studentDTO.setAge(student.getAge());  
  31.             studentDTO.setName(student.getName());  
  32.             listStudentDTO.add(studentDTO);  
  33.         }  
  34.         return listStudentDTO;  
  35.     }  
  36. }  

 

     6)在student-service中创建service层接口StudentService

 

[java] view plain copy
 
  1. package org.student.service;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.stereotype.Service;  
  6. import org.student.bean.Student;  
  7.   
  8. @Service  
  9. public interface StudentService {  
  10.   
  11.     List<Student> listStudent();  
  12.       
  13. }  

 

   7)在student-service中实现StudentService接口

 

[java] view plain copy
 
  1. package org.student.service.impl;  
  2.   
  3. import java.util.List;  
  4.   
  5. import javax.annotation.Resource;  
  6.   
  7. import org.springframework.stereotype.Service;  
  8. import org.student.bean.Student;  
  9. import org.student.service.StudentService;  
  10. import org.student.service.mapper.StudentMapper;  
  11.   
  12. @Service("studentService")  
  13. public class StudentServiceImpl implements StudentService{  
  14.   
  15.     @Resource  
  16.     private StudentMapper studentMapper;  
  17.       
  18.     @Override  
  19.     public List<Student> listStudent() {  
  20.         List<Student> listStudent = studentMapper.listStudent();  
  21.         return listStudent;  
  22.     }  
  23.   
  24. }  

 

        8)在student-service中创建数据层StudentMapper接口

 

[java] view plain copy
 
  1. package org.student.service.mapper;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.student.bean.Student;  
  6.   
  7. public interface StudentMapper {  
  8.     List<Student> listStudent();  
  9. }  

 

     9)在student-web中创建实体映射的XML文件,注意StudentMapper类与sql ID的对应关系

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >  
  3. <mapper namespace="org.student.service.mapper.StudentMapper">  
  4.     <!--查询字段-->  
  5.     <sql id="columns">  
  6.         a.id,  
  7.         a.name,  
  8.         a.age  
  9.     </sql>  
  10.   
  11.     <!--查询结果集-->  
  12.     <resultMap id="beanMap" type="org.student.bean.Student">  
  13.         <result property="id" column="id"/>  
  14.         <result property="name" column="name"/>  
  15.         <result property="age" column="age"/>  
  16.     </resultMap>  
  17.   
  18.   
  19.     <!--根据主键获取实体-->  
  20.     <select id="listStudent" resultMap="beanMap">  
  21.         SELECT  
  22.         <include refid="columns"/>  
  23.         FROM  
  24.         student a  
  25.     </select>  
  26.   
  27. </mapper>  

 

     dubbo提供者已创建完成,创建完成子应用结构为

   


1)dubbo-consumer.properties的service-group应该与提供者一致,否者找不到提供者方的接口。

同时pom.xml中需要增加对的依赖

[html] view plain copy
 
  1. <dependency>  
  2.     <groupId>com.student.demo</groupId>  
  3.     <artifactId>student-api</artifactId>  
  4.     <version>1.0.0-SNAPSHOT</version>  
  5. </dependency>  
[html] view plain copy
 
  1. student-registry-address=172.0.0.1:2181  
  2. student-service-group=student-min  
  3. student-service-version=1.0.0  
  4. student-service-timeout=120000  

 

   2)spring-dubbo-consumer.xml的配置及接口调用方式

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"  
  5.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.     http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.     http://www.springframework.org/schema/beans  
  8.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  9.     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  
  10.     http://code.alibabatech.com/schema/dubbo  
  11.     http://code.alibabatech.com/schema/dubbo/dubbo.xsd">  
  12.        
  13.     <dubbo:application name="consumer-student-test" />  
  14.   
  15.     <dubbo:registry address="${student-registry-address}" protocol="zookeeper" />  
  16.       
  17.       
  18.     <dubbo:reference id="studentApi" interface="org.student.api.StudentApi"  
  19.         group="${student-service-group}" version="${student-service-version}"  
  20.         check="false" />  
  21.       
  22. </beans>  

 

3)调用者的controller层 

[java] view plain copy
 
  1. package org.student.controller;  
  2.   
  3. import javax.annotation.Resource;  
  4.   
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.web.bind.annotation.RequestMapping;  
  8. import org.springframework.web.bind.annotation.RequestMethod;  
  9. import org.springframework.web.bind.annotation.RestController;  
  10. import org.student.api.StudentApi;  
  11.   
  12. @RestController  
  13. @RequestMapping("/student")  
  14. public class StudentController {  
  15.     private static Logger logger = LoggerFactory.getLogger(StudentController.class);  
  16.   
  17.     @Resource  
  18.     private StudentApi studentApi;  
  19.       
  20.     @RequestMapping(path = "/listStudent", method = RequestMethod.POST)  
  21.     public void listStudent(){  
  22.         logger.info("get students...");  
  23.         logger.info("the data are " + studentApi.listStudents());  
  24.     }  
  25. }  

 

4)服务器同时启动provider和consumer,会看到启动信息

       

[java] view plain copy
 
  1. <span style="white-space:pre">    </span>查看zookeeper注册中心发现提供者消费者都已成功注册  
[java] view plain copy
 
  1. <span style="white-space:pre">    </span><img src="https://img-blog.csdn.net/20161110162252922?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="800" height="30" alt="" />  
[java] view plain copy
 
  1. <span style="white-space:pre">    </span><img src="https://img-blog.csdn.net/20161110162424347?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="800" height="90" alt="" />  
     5)测试接口

[java] view plain copy
 
  1. 由于我并没有写view层来展示数据,现在只能通过控制台的日志信息来简单测试接口。(logback的用法不做解释)利用浏览器post请求访问  
  2. ://172.0.0.1:8080/student-test/student/listStudent,控制台输出为  
[java] view plain copy
 
  1. [http-nio-8080-exec-2] INFO  2016-11-07 18:33:24.450 o.s.c.StudentController[24] - get students...  
  2. [DubboServerHandler-172.28.19.7:22026-thread-2] INFO  2016-11-07 18:33:24.729 d.a.o.s.a.StudentApi[58] -  [DUBBO] [2016-11-07 18:3:24] 172.28.19.7:56346 -> 172.28.19.7:22026 - student-min/org.student.api.StudentApi:1.0.0 listStudents() , dubbo version: 2.5.3, current host: 127.0.0.1  
  3. [http-nio-8080-exec-2] INFO  2016-11-07 18:33:25.026 o.s.c.StudentController[25] - the data are [id = 1, name = 张三,age = 20]  

 

四、新手在整合过程易犯的错误。

  1.ClassNotFound异常

 

[html] view plain copy
 
  1. 严重: Error configuring application listener of class org.springframework.web.context.ContextLoaderListener  
  2. java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener  
  3.     at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1332)  
  4.     at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1166)  
  5.     at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:518)  
  6.     at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:499)  
  7.     at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:118)  
  8.     at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4764)  
  9.     at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5303)  
  10.     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)  
  11.     at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1407)  
  12.     at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1397)  
  13.     at java.util.concurrent.FutureTask.run(FutureTask.java:266)  
  14.     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)  
  15.     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)  
  16.     at java.lang.Thread.run(Thread.java:745)  

 

eclipse会自动将deployment assembly指定的工程,打成jar包,放入到web-inf/lib目录下,tomcat在发布项目的时候没有同时发布maven依赖所添加的jar包,但是如果在deployment assembly没有配置相应的依赖包,就会抛出异常。解决方法:项目 —> properties -> Deployment Assembly -> Add -> Java Build Path Entries -> 选择Maven Dependencies -> Finish -> OK 把对应的Maven依赖包也发布到tomcat,调试时会自动把那些jar发布到指定目录下,tomcat也能找到那些jar了。

    另外,同样的报错可能由于不同的原因造成,如果没有激活Maven profile也会报这种错误,激活profile的方式有很多,通过命令首先需要在pom.xml中用<profiles>配置(详细配置请查看上文)再通过命令行:

mvn install -Pdev #激活dev环境

      也可以通过eclipse的配置:项目-->properties-->Maven-->填写profile名-->apply-->finish

        

      2.启动student-web,spring创建bean对象失败

 

[html] view plain copy
 
  1. 十一月 07, 2016 8:19:24 下午 org.apache.catalina.core.StandardContext listenerStart  
  2. 严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener  
  3. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.student.api.StudentApi': Cannot resolve reference to bean 'studentApi' while setting bean property 'ref'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'studentApi' is defined  
  4. at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)  
  5.     ...  
  6. at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)  
  7.     ...  
  8. Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'studentApi' is defined  
  9. at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698)  
  10. at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1175)  
  11. at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)  
  12. at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)  
  13. at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)  
  14.     ...  
  15.        

 

 spring有强大的注解帮助我们简化很大部分代码,并降低的耦合。@Autowired或@Resource在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过@Autowired或@Resource为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。以前通过在spring文件中配置<bean>的方式被移除,仅需要添加一行 <context:component-scan/> 配置就解决所有问题了——Spring XML 配置文件得到了极致的简化。<context:component-scan/> 的 base-package 属性指定了需要扫描的类包,类包及其递归子包中所有的类都会被处理。解决:在spring-base.xml中添加

<context:component-scan base-package="org.student" />

      3.消费者访问dubbo接口被拒绝

 

[html] view plain copy
 
  1. 严重: Servlet.service() for servlet [dispatcher] in context with path [] threw exception [Request processing failed; nested exception is com.alibaba.dubbo.rpc.RpcException: Forbid consumer 172.0.0.1 access service org.student.api.StudentApi from registry 172.0.0.1:2181 use dubbo version 2.5.3, Please check registry access list (whitelist/blacklist).] with root cause  
  2. com.alibaba.dubbo.rpc.RpcException: Forbid consumer 172.0.0.1 access service org.student.api.StudentApi from registry 172.0.0.1:2181 use dubbo version 2.5.3, Please check registry access list (whitelist/blacklist). at com.alibaba.dubbo.registry.integration.RegistryDirectory.doList(RegistryDirectory.java:579) at com.alibaba.dubbo.rpc.cluster.directory.AbstractDirectory.list(AbstractDirectory.java:73) at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.list(AbstractClusterInvoker.java:260) at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:219) at com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:72) at com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:52) at com.alibaba.dubbo.common.bytecode.proxy0.listStudents(proxy0.java) at org.student.controller.StudentController.listStudent(StudentController.java:25) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498)  
  3. ....  

 

 如果消费者访问的接口路径不正确,则无法调用接口。出现这种错误是我没有把消费者的组设置成提供者的组,解决方法是group保持一致

             

       4.访问所有接口都报404错误 

 

[html] view plain copy
 
  1. INFO  2016-11-08 12:42:28.507 o.s.w.s.DispatcherServlet[488] - FrameworkServlet 'dispatcher': initialization started  
  2. INFO  2016-11-08 12:42:28.518 o.s.w.c.s.XmlWebApplicationContext[578] - Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Tue Nov 08 12:42:28 CST 2016]; parent: Root WebApplicationContext  
  3. INFO  2016-11-08 12:42:28.519 o.s.b.f.x.XmlBeanDefinitionReader[317] - Loading XML bean definitions from class path resource [spring/spring-dispatcher.xml]  
  4. INFO  2016-11-08 12:42:28.657 o.s.b.f.s.DefaultListableBeanFactory[839] - Overriding bean definition for bean 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping' with a different definition: replacing [Root bean: class [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Root bean: class [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]  
  5. ...  
  6. INFO  2016-11-08 12:42:29.545 o.s.w.s.m.m.a.RequestMappingHandlerAdapter[532] - Looking for @ControllerAdvice: WebApplicationContext for namespace 'dispatcher-servlet': startup date [Tue Nov 08 12:42:28 CST 2016]; parent: Root WebApplicationContext  
  7. INFO  2016-11-08 12:42:29.810 o.s.w.s.v.v.VelocityConfigurer[140] - ClasspathResourceLoader with name 'springMacro' added to configured VelocityEngine  
  8. INFO  2016-11-08 12:42:30.193 o.s.w.s.DispatcherServlet[507] - FrameworkServlet 'dispatcher': initialization completed in 1684 ms  
  9. WARN  2016-11-08 12:42:30.206 o.s.w.s.PageNotFound[1136] - No mapping found for HTTP request with URI [/student/listStudent] in DispatcherServlet with name 'dispatcher'  

 

  这个错误我找了很久才发现,并不是简单的访问路径错误。仔细查看日志信息会发现spring加载dispatcher的过程,截取在web.xml中配置

<!--spring加载-->
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/spring-base.xml</param-value>
</context-param>
...
<!--springMVC加载-->
<servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-dispatcher.xml</param-value>
        </init-param>
</servlet>
<servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
</servlet-mapping>

      在Tomcat启动时,web.xml中加载顺序是 context-param -> listener -> filter -> servlet,ContextLoaderListener基于Web上下文级别的监听器在启动服务器时就创建ApplicationContext并且将配置的Spring Bean加载到XML中。DispatcherServlet是一个请求分发控制器,所有匹配的URL都会通过该Servlet分发执行,在创建Servlet对象时会初始化Spring MVC相关配置。spring-dispatcher.xml中定义了控制器映射,使用Controller+RequestMapping注解映射时,相关controller组件扫描要定义在spring-dispatcher.xml中,而非spring-base.xml中。依据这样的分析,我去查看了student-test项目中spring-dispatcher.xml和spring-base.xml的配置,发现spring-base.xml配置了

<context:component-scan base-package="org.student"/>

      而在spring-dispatcher.xml中未配置扫描路径。所以spring无法加载controller中的映射,自然会404了,解决方式则是在spring-dispatcher.xml中加上扫描。

      至此,这是所有我想介绍的内容,欢迎大家批评指正,转载请注明出处http://www.cnblogs.com/blueness-sunshine/p/6015965.html,另外想要源码的朋友可以留言,谢谢。

      博客推荐:

        http://blessht.iteye.com/blog/2121845

        http://www.cnblogs.com/szlbm/p/5512931.html

        http://blog.csdn.net/congcong68/article/details/41113239

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013098329/article/details/53116084
个人分类: DobboMavenspringMVC
posted @ 2018-04-26 17:47  小b菜菜  阅读(417)  评论(0编辑  收藏  举报