前面文章讲了创建一个maven聚合工程。接下来讲一下maven里面集成spring mvc+mybatis+dubbo+zookeeper。本章内容只讲配置,不讲原理性的东西,不理解的地方多百度就清楚了。
上章地址:http://www.cnblogs.com/MrLimy/p/8342026.html
为了方便,本章内容所依赖的jar包都放在父工程。
打开demo工程的pom.xml文件添加依赖,本章只添加spring、redis、dubbo的依赖。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.hpsoft.demo</groupId> <artifactId>demo</artifactId> <version>0.0.1</version> <packaging>pom</packaging> <modules> <module>demo_web</module> <module>demo_service</module> </modules> <properties> <!-- spring版本号 --> <spring.version>3.2.4.RELEASE</spring.version> <!-- log4j日志文件管理包版本 --> <slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version> <!-- junit版本号 --> <junit.version>4.10</junit.version> <!-- mybatis版本号 --> <mybatis.version>3.2.1</mybatis.version> <!-- shiro版本号 --> <shiro.version>1.2.2</shiro.version> <!-- 打包编码错误加下面这行 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- 添加Spring依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!--单元测试依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- logback start --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>org.logback-extensions</groupId> <artifactId>logback-ext-spring</artifactId> <version>0.1.1</version> </dependency> <!--spring单元测试依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <!--mybatis依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- mybatis/spring包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.0</version> </dependency> <!-- mysql驱动包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.29</version> </dependency> <!-- 添加分布插件的包pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>4.0.0</version> </dependency> <!-- 添加json的依赖包 --> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.3</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-commons</artifactId> <version>1.6.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.4.1.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.34</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.0.1.Final</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.9</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.0.Final</version> </dependency> <!-- redis开始 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.3.0.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.4.2</version> </dependency> <!-- redis结束 --> <!-- dubbo开始 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> <exclusions> <exclusion> <artifactId>spring</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> </dependency> <!-- dubbo结束 --> <!-- zookeeper開始 --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.10</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <!-- zookeeper結束 --> </dependencies> <build> <!-- 配置将properties时的变量用pom.xml里的变量赋值替换 --> <resources> <resource> <directory>src/main/resources</directory> <targetPath>${basedir}/target/classes</targetPath> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <targetPath>${basedir}/target/resources</targetPath> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> <!-- </plugins> --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1.1</version> <configuration> <warSourceExcludes>${warExcludes}</warSourceExcludes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.4.3</version> <configuration> <testFailureIgnore>true</testFailureIgnore> </configuration> </plugin> <plugin> <inherited>true</inherited> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId> maven-project-info-reports-plugin </artifactId> </plugin> </plugins> </build> <profiles> <!-- 开发环境 --> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <!-- 以下配置properties中用到一些变量,如数据库连接参数、日志打印等 --> <properties> <!-- 数据库源设置 --> <jdbc_driverClassName>com.mysql.jdbc.Driver</jdbc_driverClassName> <jdbc_url>jdbc:mysql://localhost:3306/learning</jdbc_url> <jdbc_username>root</jdbc_username> <jdbc_password>123456</jdbc_password> <!-- 日志打印的设置 --> <log.moduleName>ssm-project</log.moduleName> <log.base>logs</log.base> <log.other.level>INFO</log.other.level> <log.root.level>INFO</log.root.level> <log.stdout.ref><![CDATA[<appender-ref ref="stdout" />]]></log.stdout.ref> </properties> </profile> </profiles> </project>
service_web工程web.xml的配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>logbackConfigLocation</param-name> <param-value>classpath:logback.xml</param-value> </context-param> <listener> <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<context-param> <param-name>contextConfigLocation</param-name> <!-- xml配置文件交给Spring监听器初始化 --> <param-value>classpath:application.xml</param-value> </context-param> <!-- SpringEncodingFilter --> <filter> <filter-name>SpringEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SpringEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- SpringEncodingFilter --> <context-param> <param-name>webAppRootKey</param-name> <param-value>webapp.root</param-value> </context-param> <error-page> <error-code>404</error-code> <location>/WEB-INF/errorpage/404.jsp</location> </error-page> <error-page> <error-code>405</error-code> <location>/WEB-INF/errorpage/405.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/WEB-INF/errorpage/500.jsp</location> </error-page> <welcome-file-list> <welcome-file>/WEB-INF/view/index.jsp</welcome-file> </welcome-file-list> </web-app>
从web.xml里我们看出需要加载的几个xml文件spring-mvc.xml、classpath:logback.xml、classpath:application.xml
在web工程下的resources里添加这几个xml文件。
spring-mvc.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <!-- 扫描controller(controller层注入) --> <context:component-scan base-package="com.ngt.controller" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan> <!-- 会自动注册了validator ConversionService --> <mvc:annotation-driven validator="validator" conversion-service="conversionService" content-negotiation-manager="contentNegotiationManager"> <mvc:message-converters register-defaults="true"> <!-- StringHttpMessageConverter编码为UTF-8,防止乱码 --> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8"/> <property name = "supportedMediaTypes"> <list> <bean class="org.springframework.http.MediaType"> <constructor-arg index="0" value="text"/> <constructor-arg index="1" value="plain"/> <constructor-arg index="2" value="UTF-8"/> </bean> <bean class="org.springframework.http.MediaType"> <constructor-arg index="0" value="*"/> <constructor-arg index="1" value="*"/> <constructor-arg index="2" value="UTF-8"/> </bean> </list> </property> </bean> <!-- 避免IE执行AJAX时,返回JSON出现下载文件 --> <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> </list> </property> <!--<property name="serializerFeature">--> <!--这个地方加上这个功能吧,能自己配置一些东西,比如时间的格式化,null输出""等等--> <!--</property>--> </bean> </mvc:message-converters> <mvc:argument-resolvers> <bean class="org.springframework.data.web.PageableHandlerMethodArgumentResolver" /> </mvc:argument-resolvers> </mvc:annotation-driven> <!-- 内容协商管理器 --> <!--1、首先检查路径扩展名(如my.pdf);2、其次检查Parameter(如my?format=pdf);3、检查Accept Header--> <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <!-- 扩展名至mimeType的映射,即 /user.json => application/json --> <property name="favorPathExtension" value="true"/> <!-- 用于开启 /userinfo/123?format=json 的支持 --> <property name="favorParameter" value="true"/> <property name="parameterName" value="format"/> <!-- 是否忽略Accept Header --> <property name="ignoreAcceptHeader" value="false"/> <property name="mediaTypes"> <!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用 --> <value> json=application/json xml=application/xml html=text/html </value> </property> <!-- 默认的content type --> <property name="defaultContentType" value="text/html"/> </bean> <!-- 当在web.xml 中 DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源 --> <mvc:default-servlet-handler /> <!-- 静态资源映射 --> <!-- 对模型视图添加前后缀 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/view/" p:suffix=".jsp"/> <!-- 这里设置静态的资源 --> <mvc:resources location="/WEB-INF/static/" mapping="/static/**" /> </beans>
application.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册--> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> </bean> <!-- 引入jdbc配置文件 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:properties/*.properties</value> <!--要是有多个配置文件,只需在这里继续添加即可 --> </list> </property> </bean> <!-- 扫描注解Bean --> <context:component-scan base-package="com.ngt.*"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 激活annotation功能 --> <context:annotation-config /> <!-- 激活annotation功能 --> <context:spring-configured /> <!-- 注解事务配置 --> <!-- 类型转换及数据格式化 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/> <!-- 配置数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>${jdbc_driverClassName}</value> </property> <property name="url"> <value>${jdbc_url}</value> </property> <property name="username"> <value>${jdbc_username}</value> </property> <property name="password"> <value>${jdbc_password}</value> </property> </bean> <!-- 自动扫描了所有的XxxxMapper.xml对应的mapper接口文件,这样就不用一个一个手动配置Mpper的映射了,只要Mapper接口类和Mapper映射文件对应起来就可以了。 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.ngt.*" /> </bean> <!-- 配置Mybatis的文件 ,mapperLocations配置**Mapper.xml文件位置,configLocation配置mybatis-config文件位置--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath:mapper/**/*.xml"/> <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" /> </bean> <import resource="redis-config.xml"/> <bean id="redisUtils" class="com.ngt.common.RedisUtils"></bean> </beans>
由application.xml中可以看出我们需要的一些其他配置文件及bean,首先是jdbc的properties、mybatis-config.xml、redis-config.xml 、RedisUtils
先贴上 logback.xml:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- 尽量别用绝对路径,如果带参数不同容器路径解释可能不同,以下配置参数在pom.xml里 --> <property name="log.root.level" value="${log.root.level}" /> <!-- 日志级别 --> <property name="log.other.level" value="${log.other.level}" /> <!-- 其他日志级别 --> <property name="log.base" value="${log.base}" /> <!-- 日志路径,这里是相对路径,web项目eclipse下会输出到eclipse的安装目录下,如果部署到linux上的tomcat下,会输出到tomcat/bin目录 下 --> <property name="log.moduleName" value="${log.moduleName}" /> <!-- 模块名称, 影响日志配置名,日志文件名 --> <property name="log.max.size" value="100MB" /> <!-- 日志文件大小,超过这个大小将被压缩 --> <!--控制台输出 --> <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method\(\):%L -%msg%n</Pattern> </encoder> </appender> <!-- 用来保存输出所有级别的日志 --> <appender name="file.all" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${log.base}/${log.moduleName}.log</File><!-- 设置日志不超过${log.max.size}时的保存路径,注意如果 是web项目会保存到Tomcat的bin目录 下 --> <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${log.base}/archive/${log.moduleName}_all_%d{yyyy-MM-dd}.%i.log.zip </FileNamePattern> <!-- 文件输出日志 (文件大小策略进行文件输出,超过指定大小对文件备份) --> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>${log.max.size}</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <!-- 日志输出的文件的格式 --> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method\(\):%L -%msg%n</pattern> </layout> </appender> <!-- 这也是用来保存输出所有级别的日志 --> <appender name="file.all.other" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${log.base}/${log.moduleName}_other.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${log.base}/archive/${log.moduleName}_other_%d{yyyy-MM-dd}.%i.log.zip </FileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>${log.max.size}</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{56}.%method\(\):%L -%msg%n</pattern> </layout> </appender> <!-- 只用保存输出error级别的日志 --> <appender name="file.error" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${log.base}/${log.moduleName}_err.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${log.base}/archive/${log.moduleName}_err_%d{yyyy-MM-dd}.%i.log.zip </FileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>${log.max.size}</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{56}.%method\(\):%L - %msg%n</pattern> </layout> <!-- 下面为配置只输出error级别的日志 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 --> <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 --> <!-- 添加附加的appender,最多只能添加一个 --> <appender name="file.async" class="ch.qos.logback.classic.AsyncAppender"> <discardingThreshold>0</discardingThreshold> <queueSize>256</queueSize> <includeCallerData>true</includeCallerData> <appender-ref ref="file.all" /> </appender> <appender name="file.async.other" class="ch.qos.logback.classic.AsyncAppender"> <discardingThreshold>0</discardingThreshold> <queueSize>256</queueSize> <includeCallerData>true</includeCallerData> <appender-ref ref="file.all.other" /> </appender> <!-- 为某个包下的所有类的指定Appender 这里也可以指定类名称例如:com.aa.bb.ClassName --> <logger name="com.ngt" additivity="false"> <level value="${log.root.level}" /> <appender-ref ref="stdout" /> <appender-ref ref="file.async" /><!-- 即com.ngt包下级别为 ${log.root.level}的才会使用file.async来打印 --> <appender-ref ref="file.error" /> </logger> <!-- root将级别为${log.root.level}及大于${log.root.level}的日志信息交给已经配置好的名为“Console”的appender处理,“Console”appender将信息打印到Console,其它同理 --> <root level="${log.root.level}"> <appender-ref ref="stdout" /> <!-- 标识这个appender将会添加到这个logger --> <appender-ref ref="file.async.other" /> <appender-ref ref="file.error" /> </root> </configuration>
jdbc.properties:
jdbc_driverClassName =${jdbc_driverClassName}
jdbc_url=${jdbc_url}
jdbc_username=${jdbc_username}
jdbc_password=${jdbc_password}
mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下: properties?, settings?, typeAliases?, typeHandlers?, objectFactory?,objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers? --> <plugins> <!-- com.github.pagehelper为PageHelper类所在包名 --> <plugin interceptor="com.github.pagehelper.PageHelper"> <property name="dialect" value="mysql"/> <!-- 该参数默认为false --> <!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 --> <!-- 和startPage中的pageNum效果一样--> <property name="offsetAsPageNum" value="true"/> <!-- 该参数默认为false --> <!-- 设置为true时,使用RowBounds分页会进行count查询 --> <property name="rowBoundsWithCount" value="true"/> <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 --> <!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)--> <property name="pageSizeZero" value="true"/> <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 --> <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 --> <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 --> <property name="reasonable" value="false"/> <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 --> <!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 --> <!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 --> <!-- 不理解该含义的前提下,不要随便复制该配置 --> <property name="params" value="pageNum=start;pageSize=limit;"/> </plugin> </plugins> </configuration>
redis-config.xml :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:redis="http://www.springframework.org/schema/redis" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis-1.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 载入redis.properties,这里要特别注意,如果有多个properties文件,必须用逗号分开,不能写成两个 <context:property-placeholder/> --> <context:property-placeholder location="classpath:properties/redis.properties" /> <!-- 配置JedisPoolConfig相关参数 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="32"></property> <property name="maxIdle" value="6"></property> <property name="testOnBorrow" value="true" /> </bean> <!-- 配置redis服务器信息 --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy"> <property name="poolConfig" ref="jedisPoolConfig"></property> <property name="hostName" value="${redis.host}"></property> <property name="port" value="${redis.port}"></property> <property name="database" value="${redis.database}"></property> <property name="timeout" value="15000"></property> <property name="usePool" value="true"></property> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory"></property> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> <!--开启事务--> <property name="enableTransactionSupport" value="true"/> </bean> </beans>
redis.properties:
#redis settings
redis.database=0
redis.keyPrefix=ngt
redis.host=localhost
redis.port=6379
com.ngt.service.RedisUtils:
package com.ngt.common; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @Service public class RedisUtils { @Autowired private RedisTemplate<String, Object> redisTemplate ; /** * 设置redisTemplate */ @Resource public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } //=============================common============================ /** * 指定缓存失效时间 * @param key 键 * @param time 时间(秒) * @return */ public boolean expire(String key,long time){ try { if(time>0){ redisTemplate.expire(key, time, TimeUnit.SECONDS); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据key 获取过期时间 * @param key 键 不能为null * @return 时间(秒) 返回0代表为永久有效 */ public long getExpire(String key){ return redisTemplate.getExpire(key,TimeUnit.SECONDS); } /** * 判断key是否存在 * @param key 键 * @return true 存在 false不存在 */ public boolean hasKey(String key){ try { return redisTemplate.hasKey(key); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除缓存 * @param key 可以传一个值 或多个 */ @SuppressWarnings("unchecked") public void del(String ... key){ if(key!=null&&key.length>0){ if(key.length==1){ redisTemplate.delete(key[0]); }else{ redisTemplate.delete(CollectionUtils.arrayToList(key)); } } } //============================String============================= /** * 普通缓存获取 * @param key 键 * @return 值 */ public Object get(String key){ return key==null?null:redisTemplate.opsForValue().get(key); } /** * 普通缓存放入 * @param key 键 * @param value 值 * @return true成功 false失败 */ public boolean set(String key,Object value) { try { redisTemplate.opsForValue().set(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 普通缓存放入并设置时间 * @param key 键 * @param value 值 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 * @return true成功 false 失败 */ public boolean set(String key,Object value,long time){ try { if(time>0){ redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); }else{ set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 递增 * @param key 键 * @param by 要增加几(大于0) * @return */ public long incr(String key, long delta){ if(delta<0){ throw new RuntimeException("递增因子必须大于0"); } return redisTemplate.opsForValue().increment(key, delta); } /** * 递减 * @param key 键 * @param by 要减少几(小于0) * @return */ public long decr(String key, long delta){ if(delta<0){ throw new RuntimeException("递减因子必须大于0"); } return redisTemplate.opsForValue().increment(key, -delta); } //================================Map================================= /** * HashGet * @param key 键 不能为null * @param item 项 不能为null * @return 值 */ public Object hget(String key,String item){ return redisTemplate.opsForHash().get(key, item); } /** * 获取hashKey对应的所有键值 * @param key 键 * @return 对应的多个键值 */ public Map<Object,Object> hmget(String key){ return redisTemplate.opsForHash().entries(key); } /** * HashSet * @param key 键 * @param map 对应多个键值 * @return true 成功 false 失败 */ public boolean hmset(String key, Map<String,Object> map){ try { redisTemplate.opsForHash().putAll(key, map); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * HashSet 并设置时间 * @param key 键 * @param map 对应多个键值 * @param time 时间(秒) * @return true成功 false失败 */ public boolean hmset(String key, Map<String,Object> map, long time){ try { redisTemplate.opsForHash().putAll(key, map); if(time>0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @return true 成功 false失败 */ public boolean hset(String key,String item,Object value) { try { redisTemplate.opsForHash().put(key, item, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 向一张hash表中放入数据,如果不存在将创建 * @param key 键 * @param item 项 * @param value 值 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 * @return true 成功 false失败 */ public boolean hset(String key,String item,Object value,long time) { try { redisTemplate.opsForHash().put(key, item, value); if(time>0){ expire(key, time); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 删除hash表中的值 * @param key 键 不能为null * @param item 项 可以使多个 不能为null */ public void hdel(String key, Object... item){ redisTemplate.opsForHash().delete(key,item); } /** * 判断hash表中是否有该项的值 * @param key 键 不能为null * @param item 项 不能为null * @return true 存在 false不存在 */ public boolean hHasKey(String key, String item){ return redisTemplate.opsForHash().hasKey(key, item); } /** * hash递增 如果不存在,就会创建一个 并把新增后的值返回 * @param key 键 * @param item 项 * @param by 要增加几(大于0) * @return */ public double hincr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item, by); } /** * hash递减 * @param key 键 * @param item 项 * @param by 要减少记(小于0) * @return */ public double hdecr(String key, String item,double by){ return redisTemplate.opsForHash().increment(key, item,-by); } //============================set============================= /** * 根据key获取Set中的所有值 * @param key 键 * @return */ public Set<Object> sGet(String key){ try { return redisTemplate.opsForSet().members(key); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 根据value从一个set中查询,是否存在 * @param key 键 * @param value 值 * @return true 存在 false不存在 */ public boolean sHasKey(String key,Object value){ try { return redisTemplate.opsForSet().isMember(key, value); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将数据放入set缓存 * @param key 键 * @param values 值 可以是多个 * @return 成功个数 */ public long sSet(String key, Object...values) { try { return redisTemplate.opsForSet().add(key, values); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 将set数据放入缓存 * @param key 键 * @param time 时间(秒) * @param values 值 可以是多个 * @return 成功个数 */ public long sSetAndTime(String key,long time,Object...values) { try { Long count = redisTemplate.opsForSet().add(key, values); if(time>0) expire(key, time); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 获取set缓存的长度 * @param key 键 * @return */ public long sGetSetSize(String key){ try { return redisTemplate.opsForSet().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 移除值为value的 * @param key 键 * @param values 值 可以是多个 * @return 移除的个数 */ public long setRemove(String key, Object ...values) { try { Long count = redisTemplate.opsForSet().remove(key, values); return count; } catch (Exception e) { e.printStackTrace(); return 0; } } //===============================list================================= /** * 获取list缓存的内容 * @param key 键 * @param start 开始 * @param end 结束 0 到 -1代表所有值 * @return */ public List<Object> lGet(String key,long start, long end){ try { return redisTemplate.opsForList().range(key, start, end); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取list缓存的长度 * @param key 键 * @return */ public long lGetListSize(String key){ try { return redisTemplate.opsForList().size(key); } catch (Exception e) { e.printStackTrace(); return 0; } } /** * 通过索引 获取list中的值 * @param key 键 * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 * @return */ public Object lGetIndex(String key,long index){ try { return redisTemplate.opsForList().index(key, index); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value) { try { redisTemplate.opsForList().rightPush(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, Object value, long time) { try { redisTemplate.opsForList().rightPush(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List<Object> value) { try { redisTemplate.opsForList().rightPushAll(key, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 将list放入缓存 * @param key 键 * @param value 值 * @param time 时间(秒) * @return */ public boolean lSet(String key, List<Object> value, long time) { try { redisTemplate.opsForList().rightPushAll(key, value); if (time > 0) expire(key, time); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 根据索引修改list中的某条数据 * @param key 键 * @param index 索引 * @param value 值 * @return */ public boolean lUpdateIndex(String key, long index,Object value) { try { redisTemplate.opsForList().set(key, index, value); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 移除N个值为value * @param key 键 * @param count 移除多少个 * @param value 值 * @return 移除的个数 */ public long lRemove(String key,long count,Object value) { try { Long remove = redisTemplate.opsForList().remove(key, count, value); return remove; } catch (Exception e) { e.printStackTrace(); return 0; } } class ObjectsTranscoder{ public <T> byte[] serialize(List<T> value) { if (value == null) { throw new NullPointerException("Can't serialize null"); } byte[] rv=null; ByteArrayOutputStream bos = null; ObjectOutputStream os = null; try { bos = new ByteArrayOutputStream(); os = new ObjectOutputStream(bos); for(T t : value){ os.writeObject(t); } os.writeObject(null); os.close(); bos.close(); rv = bos.toByteArray(); } catch (IOException e) { throw new IllegalArgumentException("Non-serializable object", e); } finally { close(os); close(bos); } return rv; } } public void close(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception e) { } } } }
redis 和 mybatis测试这里就不写了。写一下关于dubbo的例子
首先在网上找一个dubbo-admin-2.5.3的war包 用一个tomcat 部署起来
在application.xml新增配置
dubbo-provider.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd "> <!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello-world-provider" /> <!-- 使用multicast广播注册中心暴露服务地址 --> <!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> --> <!-- 使用zookeeper注册中心暴露服务地址 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 和本地bean一样实现服务 --> <bean id="demoService" class="com.ngt.service.impl.DubboTestServiceImpl" /> <!-- 声明需要暴露的服务接口 --> <dubbo:service interface="com.ngt.service.DubboTestService" ref="demoService" /> </beans>
在demo_service工程下写一个接口,测试提供者是否配置成功
package com.ngt.service; public interface DubboTestService { public String hello(String name); }
package com.ngt.service.impl; import org.springframework.stereotype.Service; import com.ngt.service.DubboTestService; @Service public class DubboTestServiceImpl implements DubboTestService { @Override public String hello(String name) { return "hello"+name; } }
运行demo_web工程,查看http://localhost:8088/dubbo-admin-2.5.3的服务治理中的提供者有没有接口信息
附上一张项目结构图
有了提供者,下面准备配置一个消费者来调用接口。在demo下新建一个web子工程demo_consumer。
把demo_web工程下的配置文件全部拷贝到demo_consumer工程下,打开pom.xml添加demo_service的依赖。
dubbo-customer.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd "> <!-- 提供方应用信息,用于计算依赖关系 --> <dubbo:application name="hello-world-customer" /> <!-- 使用zookeeper注册中心暴露服务地址 --> <dubbo:registry address="zookeeper://localhost:2181" /> <dubbo:reference id="demoService" interface="com.ngt.service.DubboTestService"/> </beans>
写一个控制器消费demoService接口
package com.ngt.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.ngt.service.DubboTestService; @Controller public class TestDubbo { @Resource(name="demoService") private DubboTestService dubboTestService; @RequestMapping("/testDubbo") public @ResponseBody String sayHello(){ return dubboTestService.hello("demo"); } }