• 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
  • 相关阅读:
    【VUE】数据库动态渲染标签,并且动态绑定事件与激活图标
    Linux shell select
    ceph介绍和安装
    C# 保存网络图片至本地项目中
    CS229 斯坦福大学机器学习复习材料(数学基础)
    SPRING.NET FRAMEWORK 3.0 GA啦
    U盘装机神器
    一行css让网页风格变成暗黑模式
    vue3 自学(一)基础知识学习和搭建一个脚手架
    windows使用nvm管理node不同版本
  • 原文地址:https://www.cnblogs.com/liu2-/p/8954089.html
Copyright © 2020-2023  润新知