原创SpringMvc+Mybatis+Redis框架
Posted 刘岗强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创SpringMvc+Mybatis+Redis框架相关的知识,希望对你有一定的参考价值。
声明:
本人提供这个 SpringMVC + Mybatis + Redis 的Demo 本着学习的态度,如果有欠缺和不足的地方,给予指正,并且多多包涵.
PS:最近发现Spring Boot十分火但是了解了几次都觉得没意思,不知道大家对此有什么想法源码地址
框架运行环境:
Maven:3.3.9
Eclipse:MARS.2
JDK:1.8
Tomcat:8.0.36
功能介绍:
声明:
本人提供这个 SpringMVC + Mybatis + Redis 的Demo 本着学习的态度,如果有欠缺和不足的地方,给予指正,并且多多包涵.
PS:最近发现Spring Boot十分火但是了解了几次都觉得没意思,大家能给我说说为什么么?
框架使用环境:
Maven:3.3.9 Eclipse:MARS.2
JDK:1.8 Tomcat:8.0.36
框架包含内容:
一、权限控制
权限曾一度打算采用Shiro来实现,确实了解之后也发现了Shiro的强大,但是强大之余也发现自己并用不了那么多东西,其实现在权限大都采用RBAC(Role-Based Access Control)这种模型来实现的访问控制,本项目也是采用这种模型
来实现的访问控制。在这之前先介绍一下三个自定义注解
@RequiresRoles:在本系统代表必须具备某角色才能访问该方法 如果满足角色要求将不会继续判断权限
@RequiresPermission:在本系统代表必须具备某权限才能访问该方法 如果满足权限要求将不会继续判断操作
@RequiresOperation:在本系统代表必须具备某操作权限才能访问该方法 这是目前权限控制的最小颗粒,至于跟业务相关的权限只能在业务逻辑中判断了
而这些注解全作用于方法上
至于实现思路很简单,利用拦截器接管所有请求,然后根据用户携带的token(登录时会返回一个token作为用户的合法令牌)从缓存中获取用户信息并从数据库加载出改用户的角色和权限数据然后根据反射获取访问该方法的注解的值
比较是否满足 满足则继续执行 不满足则提示相关操作无权限之类的,这里我是把权限信息首次加载后放入缓存,系统内的高热点数据建议大家都放入缓存效率高得多,然后有地方修改对应用户的权限时清除改用户的权限缓存,具体
的请参照Spring Cache这里完全把Redis和Spring Cache结合在一起了 完全不需要代码来操作redis(除了业务中需要特殊处理的东西)
PS:关于RBAC附上一个博客地址,这里介绍得很好http://blog.csdn.net/painsonline/article/details/7183613/
二、日志异常提醒
日志采用的是slf4j,为啥配置文件就是log4j.xml大家可以百度一下这两个的关系,要求高一点的可以使用logback,基本的配置没啥技术难度,无非就是集成了网络上很多大咖的建议的综合体。
日志我除了控制台打印的之外,其他对INFO、WARN、ERROR三种日志进行了分类操作 每种日志分类写入并按天分割
然后对于错误级别及以上日志进行了特殊处理,发生错误及以上级别的日志都会进行邮件提醒,这里踩了很多坑,网络上也有教程 但是大多数都是同步发送邮件(SMTP其实超慢滴,同步你就死了)还有就是网络上的配置都是一个错误
发送一封邮件(这要是错误率低的系统还好,要是不成熟的话,每天报个千儿八百的错那你就哭了),你去百度一定会百度到很多说啥配置BufferSize就可以控制了之类的问题,跟你们打包票的说,这都是胡乱转载人家的帖子,人家原文
说的是写入日志的配置是这个意思(xml内我打了注释那几个)但是发送日志源码的意思是缓冲多少个Event事件(一个异常一个事件)然后超过这个BufferSize(默认512)设定的值之后覆盖之前的事件,就这个意思而已,人家判断发送邮件
的条件是event的级别是否为error。
所以这里我重写了他的SMTPAppender类,实现了ErrorSize参数,控制当多少个event事件发送一次,具体的请参考源码
三、Spring+Redis整合
这里就简单带过就是,重写了spring-data-redis里面的几个类,目的为了实现redis的访问自动延期,和为单用户登录提供了些方法
四、单用户登录(同一个用户只能在一个地方登录)
这里大家最好看源码,我登录里面调用了,自己跟踪去看看怎实现的(轮询缓存也可以实现,但是呵呵)
五、RSA分段加密
这个为啥要单独提出来呢!目前JDK中提供的最牛的加密算法了,虽然ECC比这更牛,可是JDK没整完,具体类在utils项目的rsa包内,类中提供了密钥对的生成、加密、解密、和转化为.Net格式的密钥等方法,并采用分段加密解密技术
突破了加密内容的长度限制,但是内容越多加密越慢!视场景而使用。
六、Spring Mail
这个网络上都有配置,我只是包装了些实体类简化调用
七、实体类校验
采用的是Hibernate Validator校验,但是它使用都尼玛要在方法中每个都去判断,这对我这类懒得XX的人来说肯定受不了,于是就用拦截器统一处理了,具体参照org.system.intercept.ValidInterceptor.java
八、自动分页
org.system.intercept.PaginationInterceptor.java 不多说拦截的是mybatis,如果设置了page和rows这两个分页参数那么我就和先查询总数放入实体类的total属性中并对接下了的查询limit操作,就这样
九、全局异常处理
org.system.exception.ExceptionResolver.java拦截所以异常并封装成json格式,没做全局页面的配置,拦截器中是根据返回是否是json来判断的,不是json原来该怎么做就怎么做不影响
十、多数据源配置
系统还实现了多数据源配置,使用起来可能会让你觉得异常简单,自定义了一个注解@DataSource 里面只需要填数据源名称就能切换了,可作用于类、方法上,还有就是提供了DataSourceContextHolder类,里面有相应方法可以在
业务逻辑中随时切换数据源 他们之前的优先级关系是DataSourceContextHolder>@DataSource(方法)>@DataSource(类)
十一、其他
好像没啥可以拿出来说的了,哦,对了,json解析器换成了fastjson,原因嘛百度fastjson和jackson就知道了,这里不是快了一点点,还有也配置了Spring Task 简单的定时任务,org.service.task.ServiceTask.java这里面有使用demo
框架结构:框架全采用maven管理 所以源码只有很小要是不会Maven就请自行补习
core:主要是些顶层的封装
annotation:自定义注解
这次主要包含两部分,第一是数据源相关的注解 第二是访问控制相关的权限注解
@DataSource:这是用来切换数据源的注解 作用于service层的实现类上或者方法上,这时改类或者该方法就使用该数据源进行操作,更详细的例子请参考项目源码里面的介绍。
package org.core.annotation.db;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author <font color="green"><b>Liu.Gang.Qiang</b></font>
* @date 2017年7月14日
* @version 1.0
* @description 多数据源注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target( ElementType.METHOD, ElementType.TYPE )
public @interface DataSource
/**
* @author <font color="red"><b>Liu.Gang.Qiang</b></font>
* @return @link String
* @date 2017年7月15日
* @version 1.0
* @description 数据源名称,来源Spring配置
*/
String value();
@RequiresRoles@RequiresPermission
@RequiresOperation
实现的类似于shiro的权限 但是比较简单不喜勿喷 没shiro强大,然后自己结合RBAC+Redis+ Intercept+Filter技术实现的,对于自己目前遇到的权限问题我用这个也完全够用了。至于为什么没用shiro并不是shiro不强大只是不太喜欢那么复杂的用法(虽然已经很简单了) 我是懒得出奇的人 不过还是建议大家多去学习shiro这个权限框架毕竟连Spring都推荐使用Shiro RBAC是一个数据库的设计模型简单理解为:用户-角色-权限-资源 这里不再多说有个网友帖子写得不错 点击打开链接 拦截器什么滴也不多说spring的核心之一
entity:实体类的父类很简单自己看源码就行
log4j:这里重写了log4j的SMTPAppender这个类 首先说说这个类是干嘛的 他是用来发送邮件的当报错时邮件通知管理员,具体的请参考我的另一篇博客,上面有详细介绍点击打开链接
mapper:所有mapper的父类 默认提供了几个常用的方法
message:提示语相关的东西 都不知道咋描述 就是为了代码中不允许有一个中文和硬编码的存在 当然自己也可以改改实现国际化
result:针对返回结果的格式的统一封装 题外话:这个框架完全是为了提供接口而生 所以很多什么页面跳转什么滴都没做只做了返回json这块 连异常都封装成JSON了所以有其他要求的只能自己修改修改了
servlet:主要封装了自定义的request请求,方便自己在处理业务之后修改参数
utils:看名字就知道一些常用的工具类 有什么身份证、经纬度、日期计算、DES和RSA加密、MD5之类的东西 具体请看代码类注解 我觉得我注解已经很多了
jedis:这里重写了spring-data-redis里面的RedisCache、RedisCachemanager两个类和封装了一些其他的类目的就是为了实现redis的自动续期和单用户登录功能(一个用户同时只能在一个地方登录)如果需要实现不同平台的单用户登录需要自己小改一下 在缓存中多加个平台标识就行了
platfoem:这是web项目 名字不必纠结 介绍下包的作用
org.task:系统的一些服务类 这里只有定时任务(Spring Task)
org.tools:Spring Mail和多数据源处理类
org.system:这就是业务的相关处理部分了 具体就不详细介绍了
框架的大致结构就介绍到这里 下面说一下配置的xml 有人说多 其实还还好,不喜欢多的可以合一下,两个就能解决了,我分开是为了更明显的区分
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>platform</display-name>
<!-- 声明Spring配置文件所在目录 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:applicationContext.xml,
classpath*:spring/*.xml
</param-value>
</context-param>
<!-- 防止发生java.beans.Introspector内存泄露,应将它配置在ContextLoaderListener的前面 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- 声明ContextLoaderListener监听器自动装配Spring配置文件信息 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 全局UTF-8编码过滤器 -->
<filter>
<filter-name>CharacterEncoding</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>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 判断访问权限 -->
<filter>
<filter-name>BaseSecurityFilter</filter-name>
<filter-class>org.system.intercept.BaseSecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BaseSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置Spring控制器 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
接下来是Spring的配置文件目录结构如下
applicationContext.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:task="http://www.springframework.org/schema/task" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="
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.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.xsd ">
<!-- 配置需要交给spring扫描管理的包,一般是包括整个项目的java文件的父包(由context提供) -->
<context:component-scan base-package="org.system,org.task" />
<!-- 配置需要交给spring扫描管理的文件,一般是项目的配置文件(由context提供) -->
<context:property-placeholder location="classpath:conf.properties" />
<!-- Mybatis分页拦截器 只适用于mysql -->
<bean name="PaginationInterceptor" class="org.system.intercept.PaginationInterceptor" />
<!--开启这个配置,spring才能识别@Scheduled注解 -->
<task:scheduler id="scheduler" pool-size="10" />
<task:executor id="executor" pool-size="5-10" queue-capacity="200" rejection-policy="CALLER_RUNS" />
<task:annotation-driven executor="executor" scheduler="scheduler" />
<!-- Spring上下文工具类 -->
<bean id="springContextUtil" class="org.tools.spring.SpringContextUtil" />
</beans>
db.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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd ">
<!-- 动态数据源 -->
<bean id="dataSource" class="org.tools.spring.db.DynamicDataSource">
<!-- 通过key-value关联数据源 -->
<property name="targetDataSources">
<map>
<entry value-ref="dataSourceOne" key="dataSourceOne" />
<entry value-ref="dataSourceTwo" key="dataSourceTwo" />
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceOne" />
</bean>
<!-- 配置数据源(一) -->
<bean name="dataSourceOne" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<!-- 基本配置 -->
<property name="driverClassName" value="$db1.driverClassName" />
<property name="url" value="$db1.url" />
<property name="username" value="$db1.user" />
<property name="password" value="$db1.password" />
<!-- 初始化时建立物理连接的个数 -->
<property name="initialSize" value="$db1.initialSize" />
<!-- 最小连接池数 -->
<property name="minIdle" value="$db1.minIdle" />
<!-- 最大连接池数量 -->
<property name="maxActive" value="$db1.maxActive" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="$db1.maxWait" />
</bean>
<!-- 配置数据源(二) -->
<bean name="dataSourceTwo" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<!-- 基本配置 -->
<property name="driverClassName" value="$db2.driverClassName" />
<property name="url" value="$db2.url" />
<property name="username" value="$db2.user" />
<property name="password" value="$db2.password" />
<!-- 初始化时建立物理连接的个数 -->
<property name="initialSize" value="$db2.initialSize" />
<!-- 最小连接池数 -->
<property name="minIdle" value="$db2.minIdle" />
<!-- 最大连接池数量 -->
<property name="maxActive" value="$db2.maxActive" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="$db2.maxWait" />
</bean>
<!-- 配置sqlSessionFactory(由mybatis-spring.jar提供支持) -->
<bean name="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置mybatis的默认选项 -->
<property name="configuration" ref="configuration" />
<!-- 配置拦截器用于Mybatis分页和总数查询,只实现Mysql -->
<property name="plugins" ref="PaginationInterceptor" />
</bean>
<!-- 支持注解事务模式 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<!-- 事务管理 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置声明式事务 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<bean id="dataSourceAspect" class="org.tools.spring.db.DataSourceAspect" />
<!-- 配置该声明式事务规则用于的切入点 步骤: 1.配置切入点 2.应用该声明式事务规则 -->
<aop:config proxy-target-class="true" expose-proxy="true">
<!-- 配置切入点 -->
<aop:pointcut id="transaction_pointcut" expression="execution(* org.system.service.*.impl..*.*(..))" />
<!-- 应用该声明式事务规则 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="transaction_pointcut" order="2" />
<aop:aspect ref="dataSourceAspect" order="1">
<!-- 拦截所有service方法 -->
<aop:pointcut id="dataSourcePointcut" expression="execution( * org.system.service.*.impl..*.*(..))" />
<aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
</aop:aspect>
</aop:config>
</beans>
mail.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" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd ">
<!-- 邮件发送器 -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<!-- 协议类型 -->
<property name="protocol" value="$mail.smtp.type" />
<!-- 服务器地址 -->
<property name="host" value="$mail.smtp.host" />
<!-- 服务器端口 -->
<property name="port" value="$mail.smtp.port" />
<!--用户名 -->
<property name="username" value="$mail.username" />
<!-- 用户密码 -->
<property name="password" value="$mail.password" />
<!-- 默认编码 -->
<property name="defaultEncoding" value="UTF-8" />
<!-- 其他配置 -->
<property name="javaMailProperties">
<props>
<!--是否验证密码 -->
<prop key="mail.smtp.auth">$mail.smtp.auth</prop>
<!-- 超时时间 -->
<prop key="mail.smtp.timeout">$mail.smtp.timeout</prop>
<!-- SSL类配置 -->
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<!-- 是否开启STARTTLS验证 -->
<prop key="mail.smtp.starttls.enable">$mail.smtp.starttls</prop>
</props>
</property>
</bean>
</beans>
mybatis.xml MyBatis配置
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd ">
<!-- Mybatis分页拦截器 只适用于MySQL -->
<bean name="PaginationInterceptor" class="org.system.intercept.PaginationInterceptor" />
<!-- mybatis默认选项配置 -->
<bean id="configuration" class="org.apache.ibatis.session.Configuration">
<property name="callSettersOnNulls" value="true" />
</bean>
<!-- Mapper接口所在包名,Spring会自动查找其下的Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.system.mapper..*" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
</beans>
redis.xml Redis相关配置 JDK8发不出去邮件的原因和解决方案请看点击打开链接
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.2.xsd">
<!-- redis pool相关配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最小空闲数 -->
<property name="minIdle" value="$redis.minIdle" />
<!-- 最大空闲数 -->
<property name="maxIdle" value="$redis.maxIdle" />
<!-- 最大连接数 -->
<property name="maxTotal" value="$redis.maxTotal" />
<!-- 最大等待时间 单位毫秒(ms) -->
<property name="maxWaitMillis" value="$redis.maxWaitMillis" />
<!-- 使用连接时测试连接是否可用 -->
<property name="testOnBorrow" value="$redis.testOnBorrow" />
</bean>
<!-- jedis客户端连接工厂 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="poolConfig" />
<property name="database" value="$redis.database" />
<property name="port" value="$redis.port" />
<property name="hostName" value="$redis.host" />
<property name="password" value="$redis.password" />
</bean>
<!-- redisTemplate模板 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- redis缓存管理器 -->
<bean id="cacheManager" class="org.jedis.RedisCacheManager">
<constructor-arg name="redisOperations" ref="redisTemplate" />
<!-- 是否事务提交,如果事务回滚,缓存也回滚,默认false -->
<property name="transactionAware" value="true" />
<!-- 设置缓存超时时间 已实现自动续期 如果不设置将永久存在 -->
<property name="expires">
<map>
<!-- 模块信息相关缓存配置 -->
<entry key="cache_module" value="1800" />
</map>
</property>
</bean>
<!-- 支持缓存注解 -->
<cache:annotation-driven cache-manager="cacheManager" />
</beans>
接下来是spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描要自动管理的包 -->
<context:component-scan base-package="org.system.controller.*.impl" />
<!-- 支持上传文件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 文件大小设置 最大50M -->
<property name="maxUploadSize" value="52428800" />
<!-- 文件默认编码 -->
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- 对模型视图名称的解析,在请求时模型视图名称添加前后缀 系统内没有涉及到页面跳转所以基本无用 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".html" />
</bean>
<!-- 实体类校验拦截器 -->
<bean id="validInterceptor" class="org.system.intercept.ValidInterceptor" />
<!-- 配置AOP切点 只拦截Controltroller -->
<aop:config>
<!--切入点 -->
<aop:pointcut id="validPoint" expression="execution(public * org.system.controller.*.impl..*.*(..))" />
<!--在该切入点使用自定义拦截器 -->
<aop:advisor pointcut-ref="validPoint" advice-ref="validInterceptor" />
</aop:config>
<!-- 指定自己定义的validator -->
<mvc:annotation-driven validator="validator">
<mvc:message-converters register-defaults="true">
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json;charset=UTF-8" />
<property name="features">
<array>
<value>WriteMapNullValue</value>
<value>WriteNullStringAsEmpty</value>
<value>WriteDateUseDateFormat</value>
</array>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 会 自动注册 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
<!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->
<property name="validationMessageSource" ref="messageSource" />
</bean>
<!-- 国际化的消息资源文件(本系统中主要用于显示/错误消息定制) -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames" value="classpath:properties/validator/validator" />
<property name="useCodeAsDefaultMessage" value="true" />
<property name="defaultEncoding" value="UTF-8" />
<property name="cacheSeconds" value="60" />
</bean>
<!-- 权限拦截器 -->
<mvc:interceptors>
<!-- 客户端安全访问拦截器 拦截所有请求-->
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="org.system.intercept.platform.BaseSecurityInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
接下来的是log4j.xml:也可以使用properties因为我使用的是异步发送邮件 我知道的只能用XML来配置 如果大家有properties配置能实现的麻烦通知下我 我其实比较喜欢properties
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<!--
%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%dyyyy/MM/dd HH:mm:ss,SSS。
%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
%t:输出产生该日志事件的线程名。
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。
%c:输出日志信息所属的类目,通常就是所在类的全名。
%M:输出产生日志信息的方法名。
%F:输出日志消息产生时所在的文件名称。
%L::输出代码中的行号。
%m::输出代码中指定的具体日志信息。
%n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"。
%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%:输出一个"%"字符。
另外,还可以在%与格式字符之间加上修饰符来控制其最小长度、最大长度、和文本的对齐方式。如:
1) c:指定输出category的名称,最小的长度是20,如果category的名称长度小于20的话,默认的情况下右对齐。
2)%-20c:"-"号表示左对齐。
3)%.30c:指定输出category的名称,最大的长度是30,如果category的名称长度大于30的话,就会将左边多出的字符截掉,但小于30的话也不会补空格。
-->
<!-- 控制台日志配置 -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-dyyyy-MM-dd HH:mm:ss [%p] [%c3.%M:%L] %m%n" />
</layout>
</appender>
<!-- info级别日志控制 -->
<appender name="info" class="org.apache.log4j.DailyRollingFileAppender">
<!-- 文件路径 -->
<param name="File" value="$catalina.home/logs/platform/info.log" />
<!-- 是否追加 -->
<param name="Append" value="true" />
<!-- 最低日志级别 -->
<param name="Threshold" value="INFO" />
<!-- 回滚日志后缀 -->
<param name="datePattern" value="'.'yyyy-MM-dd" />
<!-- 是否启用缓冲 当缓冲区数据达到一定大小再写入文件 默认8K -->
<!-- <param name="BufferedIO" value="true"/> <param name="BufferSize" value="8192"/> -->
<!-- 日志输出布局 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-dyyyy-MM-dd HH:mm:ss [%p] [%c.%M:%L] %m%n" />
</layout>
<!--限制输出级别 -->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- 最小级别 -->
<param name="LevelMax" value="INFO" />
<!-- 最大级别 -->
<param name="LevelMin" value="INFO" />
</filter>
</appender>
<!-- warn级别日志控制 -->
<appender name="warn" class="org.apache.log4j.DailyRollingFileAppender">
<!-- 文件路径 -->
<param name="File" value="$catalina.home/logs/platform/warn.log" />
<!-- 是否追加 -->
<param name="Append" value="true" />
<!-- 最低日志级别 -->
<param name="Threshold" value="WARN" />
<!-- 回滚日志后缀 -->
<param name="datePattern" value="'.'yyyy-MM-dd" />
<!-- 是否启用缓冲 当缓冲区数据达到一定大小再写入文件 默认8K -->
<!-- <param name="BufferedIO" value="true"/> <param name="BufferSize" value="8192"/> -->
<!-- 日志输出布局 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-dyyyy-MM-dd HH:mm:ss [%p] [%c.%M:%L] %m%n" />
</layout>
<!--限制输出级别 -->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- 最小级别 -->
<param name="LevelMax" value="WARN" />
<!-- 最大级别 -->
<param name="LevelMin" value="WARN" />
</filter>
</appender>
<!-- error级别日志控制 -->
<appender name="error" class="org.apache.log4j.DailyRollingFileAppender">
<!-- 文件路径 -->
<param name="File" value="$catalina.home/logs/platform/error.log" />
<!-- 是否追加 -->
<param name="Append" value="true" />
<!-- 最低日志级别 -->
<param name="Threshold" value="ERROR" />
<!-- 回滚日志后缀 -->
<param name="datePattern" value="'.'yyyy-MM-dd" />
<!-- 是否启用缓冲 当缓冲区数据达到一定大小再写入文件 默认8K -->
<!-- <param name="BufferedIO" value="true"/> <param name="BufferSize" value="8192"/> -->
<!-- 日志输出布局 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-dyyyy-MM-dd HH:mm:ss [%p] [%c.%M:%L] %m%n" />
</layout>
<!--限制输出级别 -->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- 最小级别 -->
<param name="LevelMax" value="ERROR" />
<!-- 最大级别 -->
<param name="LevelMin" value="ERROR" />
</filter>
</appender>
<!-- 发送日志文件到邮件 -->
<appender name="email" class="org.core.log4j.SMTPAppender">
<!-- 最小输出日志级别 -->
<param name="Threshold" value="ERROR" />
<!-- 缓冲Event个数默认512 当达到了多少个就覆盖以前的Event 而非网络上所说的缓冲数据大小 不看源码坑出血 -->
<param name="BufferSize" value="512" />
<!-- 错误个数默认一个 即出现错误就发送邮件 -->
<param name="ErrorSize" value="5" />
<!-- 发送邮件的协议类型 QQ使用smtps加密 163使用smtp -->
<param name="SMTPProtocol" value="smtps" />
<!-- 发送端口 QQ使用465 163使用25 -->
<param name="SMTPPort" value="465" />
<!-- 发送日志邮箱SMTP -->
<param name="SMTPHost" value="smtp.qq.com" />
<!-- 发送日志的邮箱 -->
<param name="From" value="自己填" />
<!-- 发送日志的邮箱用户名 -->
<param name="SMTPUsername" value="自己填" />
<!-- 发送日志的邮箱密码 -->
<param name="SMTPPassword" value="自己填" />
<!-- 日志邮件主题 -->
<param name="Subject" value="Platform项目异常通知" />
<!-- 日志邮件接收者 -->
<param name="To" value="自己填 多个用逗号隔开" />
<!-- 抄送邮件接受者 -->
<!-- <param name="Bcc" value="自己填 多个用逗号隔开" /> -->
<!-- 日志输出布局 -->
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-dyyyy-MM-dd HH:mm:ss [%p] [%c.%M:%L] %m%n" />
</layout>
</appender>
<!-- 异步发送邮件设置 -->
<appender name="asyncout" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="email" />
</appender>
<!-- 需要特殊处理的日志级别 -->
<logger name="org.springframework">
<level value="info" />
</logger>
<logger name="org.system">
<level value="debug" />
</logger>
<!-- 根路径设置 -->
<root>
<level value="info" />
<appender-ref ref="console" />
<appender-ref ref="info" />
<appender-ref ref="warn" />
<appender-ref ref="error" />
<appender-ref ref="asyncout" />
</root>
</log4j:configuration>
最后是conf.properties
如果对应的没变化就不需要改 后面提供的框架源码这块都会是错的请谅解
###数据库连接配置 包括多数据源
#驱动路径
db1.driverClassName=com.mysql.cj.jdbc.Driver
#URL连接地址
db1.url=jdbc:mysql://localhost:3306/temp?useUnicode=true&characterEncoding=utf8&mysqlEncoding=utf8&autoReconnect=true
#数据库用户名
db1.user=yxt
#数据库用户密码
db1.password=yxt315
#数据库连接池初始化大小
db1.initialSize=5
#数据库连接池最小连接数
db1.minIdle=2
#数据库连接池最大连接数
db1.maxActive=50
#数据库连接池连接等待超时时间
db1.maxWait=6000
#驱动路径
db2.driverClassName=com.mysql.cj.jdbc.Driver
#URL连接地址
db2.url=jdbc:mysql://localhost:3306/develop?useUnicode=true&characterEncoding=utf8&mysqlEncoding=utf8&autoReconnect=true
#数据库用户名
db2.user=yxt
#数据库用户密码
db2.password=123456
#数据库连接池初始化大小
db2.initialSize=5
#数据库连接池最小连接数
db2.minIdle=2
#数据库连接池最大连接数
db2.maxActive=50
#数据库连接池连接等待超时时间
db2.maxWait=6000
###邮件服务器设置
#协议类型
mail.smtp.type=smtps
#服务器地址
mail.smtp.host=smtp.qq.com
#服务器端口
mail.smtp.port=465
#是否验证账号密码
mail.smtp.auth=true
#是否启用TLS
mail.smtp.starttls=false
#连接超时时间
mail.smtp.timeout=25000
#用户名
mail.username=自己填
#用户密码<现在很多采用的是授权码>
mail.password=不告诉你
###Redis缓存配置
#缓存池最小空闲数
redis.minIdle=5
#缓存池最大空闲数
redis.maxIdle=100
#缓存池最大连接数
redis.maxTotal=300
#最大等待时间
redis.maxWaitMillis=3000
#使用连接时是否测试可用
redis.testOnBorrow=true
#主机地址
redis.host=不会告诉你IP
#主机端口
redis.port=6379
#主机密码
redis.password=123456
#数据库下标
redis.database=4
以上是关于原创SpringMvc+Mybatis+Redis框架的主要内容,如果未能解决你的问题,请参考以下文章
Shiro Demo 示例(SpringMVC-Mybatis-Shiro-redis)
使用专家构建,整合Dubbo+动物园管理员+SpringMVC+Spring+MyBatis+Redis支持分布式的高效率便捷开发框架
独孤九剑 《Maven+CMS+Redis+Solr+Linux+Nginx+Springmvc+Mybatis+单点登录》
分布式 Dubbo+Zookeeper+springmvc+mybatis+shiro+restful+activemq+redis