1.Spring配置: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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>frame</display-name> <!-- 读取spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml;classpath:spring-mybatis.xml;classpath:shiro-config.xml</param-value> </context-param> <!-- 防止发生java.beans.Introspector内存泄露,应将它配置在ContextLoaderListener的前面 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring Application Context Listener End --> <!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 --> <!-- 这里filter-name必须对应applicationContext.xml中定义的<bean id="shiroFilter"/> --> <!-- 使用[/*]匹配所有请求,保证所有的可控请求都经过Shiro的过滤 --> <!-- 通常会将此filter-mapping放置到最前面(即其他filter-mapping前面),以保证它是过滤器链中第一个起作用的 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 --> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Spring MVC Config Start --> <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-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern><!-- 拦截了所有包括静态资源文件,spring mvc中需要配置mvc:resources包含静态资源文件 --> </servlet-mapping> <!-- Spring MVC Config End --> <!-- WebAppRootKey 获取项目部署的根路径,将log4j日志输出到项目的路径下 --> <context-param> <param-name>webAppRootKey</param-name> <param-value>webapp.root</param-value> </context-param> <!-- Log4J 配置 Start --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>6000</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!-- Log4J 配置 End --> <!-- Spring 编码过滤器 start --> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Spring 编码过滤器 End --> <!--CXF配置 --> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/cxf/*</url-pattern> </servlet-mapping> <!-- 错误跳转页面 --> <!-- <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> --> </web-app>
2.Spring配置:applicationContext.xml
<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" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:context="http://www.springframework.org/schema/context" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <!-- 引入jdbc配置文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 扫描文件(自动将servicec层注入) --> <context:component-scan base-package="org.bsframe"/> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" abstract="false" lazy-init="false" autowire="default" > <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <bean id="helloWorldImpl" class="org.bsframe.web.cxf.HelloWorldServiceImpl"></bean> <!-- soap webservice --> <jaxws:endpoint id="helloWorld" implementor="#helloWorldImpl" address="/HelloWorld" ></jaxws:endpoint> <!-- <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxws:endpoint id="helloWorld" implementor="org.bsframe.web.cxf.HelloWorldServiceImpl" address="/HelloWorld" /> --> <!-- restful webservice --> <jaxrs:server id="rs1" address="/rs"> <jaxrs:serviceBeans> <ref bean="restSample" /> </jaxrs:serviceBeans> <jaxrs:providers> <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" /> </jaxrs:providers> </jaxrs:server> </beans>
3.Spring MVC配置:spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:solr="http://www.springframework.org/schema/data/solr" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd http://www.springframework.org/schema/data/solr http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd"> <!-- 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean --> <mvc:annotation-driven /> <!-- 配置spring处理静态资源文件 两种方案 --> <!--方案一: 使用服务器默认的defaultServlet --> <mvc:default-servlet-handler /> <!--(推荐方案)方案二: 把images/**映射到ResourceHttpRequestHandler进行处理 --> <mvc:resources mapping="/images/**" location="/images/" /> <mvc:resources mapping="/css/**" location="/css/" /> <mvc:resources mapping="/js/**" location="/js/" /> <mvc:resources mapping="/frame/**" location="/frame/" /> <mvc:resources mapping="/pages/**" location="/pages/" /> <!-- 注册解析注解所需要的几个bean --> <context:annotation-config /> <!-- 对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 需要更改 --> <context:component-scan base-package="org.bsframe.web.controller" /> <!-- 默认访问跳转到登录页面(即定义无需Controller的url<->view直接映射) --> <mvc:view-controller path="/" view-name="forward:/login.jsp" /> <!-- 避免IE在ajax请求时,返回json出现下载 --> <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <!-- 对模型视图添加前后缀 --> <!-- ViewResolver,负责为DispatcherServlet查找ModelAndView的视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/view/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" abstract="false" lazy-init="false" autowire="default" > <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> --> <!-- task任务扫描注解 --> <task:annotation-driven /> <!-- Solr setting --> <solr:repositories base-package="org.bsframe.web.repository" multicore-support="true" /> <solr:solr-server id="solrServer" url="http://locahost:8983/solr" /> <bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate" scope="singleton"> <constructor-arg ref="solrServer" /> </bean> <!-- <bean id="searchRepository" class="org.springframework.data.solr.example.repository.SolrProductRepository"> <property name="solrOperations" ref="solrTemplate" /> </bean> --> </beans>
4.log4j配置:log4j.properties
### direct log messages to stdout and logFile###
log4j.rootCategory=INFO, stdout,logFile
# OpenSymphony Stuff
log4j.logger.com.opensymphony=INFO
log4j.logger.org.apache.struts2=INFO
log4j.logger.org.apache.commons=INFO
# Spring Stuff
log4j.logger.org.springframework=INFO
log4j.logger.org.springframework.oxm=INFO
# Hibernate Stuff
log4j.logger.org.hibernate=INFO
log4j.logger.org.hibernate.type=INFO
log4j.logger.org.hibernate.tool.hbm2ddl=INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[u65F6u95F4:%d{yyyy-MM-dd hh:mm:ss}] [u7EA7u522B:%p] [u7C7B:%c] [u6D88u606F:%m] %n
log4j.appender.logFile=org.apache.log4j.RollingFileAppender
log4j.appender.logFile.File=/Users/zouhao/bsframe.log
#log4j.appender.logFile.File=${webapp.root}/WEB-INF/logs/frame-app.log
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[u65F6u95F4:%d{yyyy-MM-dd hh:mm:ss}] [u7EA7u522B:%p] [u7C7B:%c] [u6D88u606F:%m] %n
log4j.appender.logFile.MaxFileSize = 5MB
log4j.appender.logFile.MaxBackupIndex =3
5.Mybatis配置: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> <!-- 命名空间 --> <typeAliases> <!-- 类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余 --> <typeAlias alias="user" type="org.bsframe.entity.User" /> <!-- 在包 domain.blog 中的 Java Bean,在没有注解的情况下(@Alias("user")),会使用 Bean 的首字母小写的非限定类名来作为它的别名(如user) --> <package name="org.bsframe.entity" /> </typeAliases> <!-- <typeHandlers> --> <!-- <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> --> <!-- </typeHandlers> --> <plugins> <!-- 自定义分页Interceptor --> <!-- <plugin interceptor="org.bsframe.web.interceptor.StatementInterceptor"></plugin> --> <!-- <plugin interceptor="org.bsframe.web.interceptor.ResultSetInterceptor"></plugin> --> <!-- com.github.pagehelper为PageHelper类所在包名 ,使用PageHelper插件,与以上自定义的plugin只能选其一 --> <plugin interceptor="com.github.pagehelper.PageHelper"> <!-- 4.0.0以后版本可以不设置该参数 --> <!-- <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,orderBy,不配置映射的用默认值 --> <!-- 不理解该含义的前提下,不要随便复制该配置 --> <property name="params" value="pageNum=start;pageSize=limit;" /> <!-- 支持通过Mapper接口参数来传递分页参数 --> <property name="supportMethodsArguments" value="true" /> <!-- always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page --> <property name="returnPageInfo" value="check" /> </plugin> </plugins> <!-- 映射map --> <mappers> <package name="org.bsframe.dao" /> </mappers> </configuration>
6.Spring整合Mybatis:spring-mybatis.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <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> <!-- 连接池最大使用连接数 --> <property name="maxActive"> <value>20</value> </property> <!-- 初始化连接大小 --> <property name="initialSize"> <value>1</value> </property> <!-- 获取连接最大等待时间 --> <property name="maxWait"> <value>60000</value> </property> <!-- 连接池最大空闲 --> <property name="maxIdle"> <value>20</value> </property> <!-- 连接池最小空闲 --> <property name="minIdle"> <value>3</value> </property> <!-- 自动清除无用连接 --> <property name="removeAbandoned"> <value>true</value> </property> <!-- 清除无用连接的等待时间 --> <property name="removeAbandonedTimeout"> <value>180</value> </property> <!-- 连接属性 --> <property name="connectionProperties"> <value>clientEncoding=UTF-8</value> </property> </bean> <!-- mybatis文件配置,扫描所有mapper文件 --> <!-- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="dataSource" p:configLocation="classpath:mybatis-config.xml" p:mapperLocations="classpath:mapper/*.xml" /> --> <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> </bean> <!-- spring与mybatis整合配置,扫描所有dao --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" p:basePackage="org.bsframe.dao" p:sqlSessionFactoryBeanName="sqlSessionFactory" /> <!-- 对数据源进行事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" /> </beans>
7.数据源配置:jdbc.properties
jdbc_driverClassName=com.mysql.jdbc.Driver jdbc_url=jdbc:mysql://localhost:3306/bsframe?useUnicode=true&characterEncoding=utf-8 jdbc_username=root jdbc_password=
8.Shiro配置:shiro-config.xml
<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" xmlns:context="http://www.springframework.org/schema/context" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!-- 缓存管理器 使用Ehcache实现 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" /> </bean> <!-- <bean id="passwordHelper" class="com.shinowit.framework.security.PasswordHelper"> </bean> --> <!-- 凭证匹配器 --> <!-- <bean id="credentialsMatcher" class="com.shinowit.framework.security.credentials.RetryLimitSimpleCredentialsMatcher"> <constructor-arg ref="cacheManager" /> <property name="passwordHelper" ref="passwordHelper" /> </bean> --> <!-- Realm实现 --> <bean id="userRealm" class="org.bsframe.shiro.UserRealm"> <property name="cachingEnabled" value="true" /> <property name="authenticationCachingEnabled" value="true" /> <property name="authenticationCacheName" value="authenticationCache" /> <property name="authorizationCachingEnabled" value="true" /> <property name="authorizationCacheName" value="authorizationCache" /> </bean> <!-- 会话ID生成器 --> <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" /> <!-- 会话Cookie模板 --> <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="sid" /> <property name="httpOnly" value="true" /> <property name="maxAge" value="180000" /> </bean> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe" /> <property name="httpOnly" value="true" /> <property name="maxAge" value="2592000" /> <!-- 30天 --> </bean> <!-- rememberMe管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" /> <property name="cookie" ref="rememberMeCookie" /> </bean> <!-- 会话DAO --> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"> <property name="activeSessionsCacheName" value="shiro-activeSessionCache" /> <property name="sessionIdGenerator" ref="sessionIdGenerator" /> </bean> <!-- 会话验证调度器 --> <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler"> <property name="sessionValidationInterval" value="1800000" /> <property name="sessionManager" ref="sessionManager" /> </bean> <!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="globalSessionTimeout" value="1800000" /> <property name="deleteInvalidSessions" value="true" /> <property name="sessionValidationSchedulerEnabled" value="true" /> <property name="sessionValidationScheduler" ref="sessionValidationScheduler" /> <property name="sessionDAO" ref="sessionDAO" /> <property name="sessionIdCookieEnabled" value="true" /> <property name="sessionIdCookie" ref="sessionIdCookie" /> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <property name="sessionManager" ref="sessionManager" /> <property name="cacheManager" ref="cacheManager" /> <property name="rememberMeManager" ref="rememberMeManager" /> </bean> <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) --> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager" /> <property name="arguments" ref="securityManager" /> </bean> <!--下面的loginUrl有两个必要条件,一个登陆校验失败以后会强制客户端redirect到这个url, 另外一个是登陆的表单(含有用户名及密码)必须action到这个url --> <!-- 自定义的能够接收校验码的身份验证过滤器 跳转问题太他妈诡异了,不用了,自己写代码控制如何跳转了 <bean id="formAuthenticationFilter" class="com.shinowit.framework.security.filter.ValidFormAuthenticationFilter"> <property name="usernameParam" value="loginName"/> <property name="passwordParam" value="loginPass"/> <property name="loginUrl" value="/login/"/> </bean> --> <!-- Shiro的Web过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/login/" /> <property name="unauthorizedUrl" value="/unauthorized.jsp" /> <property name="filters"> <map> <entry key="authc"> <bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" /> </entry> </map> </property> <property name="filterChainDefinitions"> <value> /login.jsp = anon /user/** = anon /scheduleTaskJob = anon /category/** = anon /cxf/** = anon /services/** = anon /springrest/** = anon /question/** = anon /teacher/** = anon /** = authc </value> </property> </bean> <!-- Shiro生命周期处理器 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> </beans>
9.Ehcache缓存配置:ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache> <defaultCache maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="1200" timeToLiveSeconds="1200" overflowToDisk="false"> </defaultCache> <cache name="test" maxElementsInMemory="1000" maxElementsOnDisk="5000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="0"> </cache> </ehcache>
10.自定义Realm: UserRealm.java
package org.bsframe.shiro; import java.util.Set; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.bsframe.dao.UserDAO; import org.bsframe.entity.User; import org.springframework.beans.factory.annotation.Autowired; public class UserRealm extends AuthorizingRealm { @Autowired private UserDAO userDAO; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); Set<String> roles = userDAO.findUserRoles(username); authorizationInfo.setRoles(roles); Set<String> permissions = userDAO.findUserPermissions(username); authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // UsernamePasswordToken login_token = (UsernamePasswordToken) token; // // //校验码判断逻辑 // //取得用户输入的校验码 // String userInputValidCode = login_token.getValidCode(); // // //取得真实的正确校验码 // String realRightValidCode = (String) SecurityUtils.getSubject().getSession().getAttribute("rand"); // // if (null == userInputValidCode || !userInputValidCode.equalsIgnoreCase(realRightValidCode)) { // throw new ValidCodeException("验证码输入不正确"); // } //以上校验码验证通过以后,查数据库 String username = (String) token.getPrincipal(); User user = userDAO.findByUsername(username); if (user == null) { throw new UnknownAccountException();//没找到帐号 } if (Boolean.FALSE.equals(user.getEnable())) { throw new LockedAccountException(); //帐号锁定 } //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( user.getUsername(), //用户名 user.getPassword(), //密码 getName() //realm name ); return authenticationInfo; } @Override public void clearCachedAuthorizationInfo(PrincipalCollection principals) { super.clearCachedAuthorizationInfo(principals); } @Override public void clearCachedAuthenticationInfo(PrincipalCollection principals) { super.clearCachedAuthenticationInfo(principals); } @Override public void clearCache(PrincipalCollection principals) { super.clearCache(principals); } public void clearAllCachedAuthorizationInfo() { getAuthorizationCache().clear(); } public void clearAllCachedAuthenticationInfo() { getAuthenticationCache().clear(); } public void clearAllCache() { clearAllCachedAuthenticationInfo(); clearAllCachedAuthorizationInfo(); } }
11.自定义用户名密码Token: CustomUsernamePasswordToken.java
package org.bsframe.shiro; import org.apache.shiro.authc.UsernamePasswordToken; public class CustomUsernamePasswordToken extends UsernamePasswordToken { private static final long serialVersionUID = 1L; //用于存储用户输入的校验码 private String validCode; public CustomUsernamePasswordToken(String username, char[] password,boolean rememberMe, String host, String validCode) { //调用父类的构造函数 super(username,password,rememberMe,host); this.validCode=validCode; } public String getValidCode() { return validCode; } public void setValidCode(String validCode) { this.validCode = validCode; } }
12.Dao层代码示例: UserMapper.java
package org.bsframe.dao; import java.util.Set; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.bsframe.entity.User; public interface UserMaper{ /** * 添加新用户 * @param user * @return */ //使用UserMapper.xml文件配置sql语句 public User findByUsername(String username); @Insert("insert into user(username, password, nickname) values(#{username}, #{password}, #{nickname})") public int addUser(User user); @Select("select r.name from user u,role r,user_role ur where u.id = ur.userid and r.id = ur.roleid and u.username = #{username}") public Set<String> findUserRoles(String username); @Select("select p.url from user u, role r, permission p, user_role ur, role_permission rp where u.username= #{username} and u.id=ur.userid and r.id=ur.roleid and r.id=rp.roleid and p.id=rp.permissionid") public Set<String> findUserPermissions(String username); @Select("select * from user where nickname = #{nickname}") public User findByNickname(String nickname); @Select("select * from user where id = #{id}") public User findUserById(Integer id); }
13.Dao层Mapper配置文件: UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.bsframe.dao.UserDAO"> <select id="findByUsername" resultType="user"> select * from user where username = #{username} </select> </mapper>
14.Service代码示例: UserServiceImpl.java
package org.bsframe.service.impl; import org.bsframe.dao.UserDAO; import org.bsframe.entity.User; import org.bsframe.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService{ @Autowired private UserMapper userMapper; public int addUser(User user) { return userMapper.addUser(user); } public User findUserById(Integer id) { return userMapper.findUserById(id); } public User findByUsername(String name) { return userMapper.findByUsername(name); } }
15.Controller层代码示例:UserController.java
package org.bsframe.web.controller; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.bsframe.entity.Sysres; import org.bsframe.entity.User; import org.bsframe.service.impl.UserServiceImpl; import org.bsframe.web.util.VerifyCodeUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Controller @RequestMapping("/user") public class UserController extends BaseController{ @Autowired private UserServiceImpl userServiceImpl; @RequestMapping(value="/findByUsername" , method = RequestMethod.GET) public @ResponseBody User findByUsername(@RequestParam("name") String name){ return this.userServiceImpl.findByUsername(name); } @RequestMapping(value = "/login", method = RequestMethod.POST) public String isLogin(HttpServletRequest request) { String loginName = request.getParameter("username"); String loginPassword = request.getParameter("password"); HttpSession session = request.getSession(true); String errorMessage = ""; Subject user = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(loginName, loginPassword); token.setRememberMe(true); try { user.login(token); String userID = (String) user.getPrincipal(); session.setAttribute("USERNAME", userID); return "admin"; } catch (UnknownAccountException uae) { errorMessage = "用户认证失败:" + "username wasn't in the system."; } catch (IncorrectCredentialsException ice) { errorMessage = "用户认证失败:" + "password didn't match."; } catch (LockedAccountException lae) { errorMessage = "用户认证失败:" + "account for that username is locked - can't login."; } catch (AuthenticationException e) { errorMessage = "登录失败错误信息:" + e; e.printStackTrace(); token.clear(); } session.setAttribute("ErrorMessage", errorMessage); return "error"; } /** * 获取当前用户的用户名 * @return 跳转到展示当前用户姓名的页面 */ @RequestMapping(value = "/getCurrent", method = RequestMethod.GET) public ModelAndView getCurrent(HttpServletRequest request,HttpServletResponse response){ ModelAndView mv = new ModelAndView(); try { //获取当前用户的姓名 String userName = getLoginUserName(); //放入到request中 mv.addObject("userName", userName); //设置跳转页面 mv.setViewName("/top"); } catch (Exception e) { e.printStackTrace(); mv.addObject("message", "获取用户出错!"); mv.setViewName("/exception"); } return mv; } @RequestMapping(value="getMenu",method=RequestMethod.GET) public ModelAndView getMenu(HttpServletRequest request,HttpServletResponse response){ ModelAndView mav =new ModelAndView(); try{ List<Sysres> slist= new ArrayList<Sysres>(); Sysres s = new Sysres(); s.setId(1l); s.setName("通用类别管理"); s.setUrl("/category/toCategory"); s.setResdesc("toCategory"); s.setParentid(2l); slist.add(s); mav.setViewName("/left"); mav.addObject("menuList", slist); return mav; }catch(Exception e){ e.printStackTrace(); mav.addObject("message", "获取菜单出错!"); mav.setViewName("/exception"); return mav; } } /** * 用户登出 */ @RequestMapping(value="/logout",method=RequestMethod.GET) public String logout(HttpServletRequest request){ SecurityUtils.getSubject().logout(); String logout = InternalResourceViewResolver.FORWARD_URL_PREFIX + "/login.jsp"; return logout; } /** * 获取验证码图片和文本(验证码文本会保存在HttpSession中) */ @RequestMapping("/getVerifyCodeImage") public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException { //设置页面不缓存 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); String verifyCode = VerifyCodeUtil.generateTextCode(VerifyCodeUtil.TYPE_NUM_ONLY, 4, null); //将验证码放到HttpSession里面 request.getSession().setAttribute("verifyCode", verifyCode); System.out.println("本次生成的验证码为[" + verifyCode + "],已存放到HttpSession中"); //设置输出的内容的类型为JPEG图像 response.setContentType("image/jpeg"); BufferedImage bufferedImage = VerifyCodeUtil.generateImageCode(verifyCode, 90, 30, 3, true, Color.WHITE, Color.BLACK, null); //写给浏览器 ImageIO.write(bufferedImage, "JPEG", response.getOutputStream()); } }
13.Maven jar包管理:pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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> <parent> <groupId>com.zouhao</groupId> <artifactId>bsframe</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>com.zouhao</groupId> <artifactId>bsframe-moduel</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>bsframe-core</module> <module>bsframe-entity</module> <module>bsframe-dao</module> <module>bsframe-service</module> <module>bsframe-shiro</module> <module>bsframe-web</module> </modules> <properties> <spring.version>4.1.6.RELEASE</spring.version> <!-- mybatis版本号 --> <mybatis.version>3.2.4</mybatis.version> <!-- mybatis分页插件 --> <mybatis-pagehelper.version>4.0.3</mybatis-pagehelper.version> <!-- log4j日志文件管理包版本 --> <slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version> <commons-lang3.version>3.3</commons-lang3.version> <commons-collections.version>3.2.1</commons-collections.version> <!-- shiro版本号 --> <shiro.version>1.2.3</shiro.version> <ehcache.version>2.6.9</ehcache.version> <servlet-api.version>3.1.0</servlet-api.version> <cxf.version>2.7.8</cxf.version> </properties> <!-- 通用jar依赖管理,各个子项目都默认依赖 --> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- 日志文件管理包 --> <!-- log 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>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- log end --> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>${commons-collections.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <!-- 一般jar依赖管理,各个子项目按需依赖,不用使用version --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</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-webmvc</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-context-support</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-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${mybatis-pagehelper.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.29</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.1.0</version> </dependency> <!-- apache shior maven start --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>${ehcache.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-quartz</artifactId> <version>${shiro.version}</version> </dependency> <!-- apache shiro maven end --> <!-- cxf setting starting --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-core</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-simple</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-databinding-aegis</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-databinding-xmlbeans</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-databinding-jaxb</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-local</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-jms</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-management</artifactId> <version>${cxf.version}</version> </dependency> <!-- CXF REST SETTING --> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId> <version>2.0-m10</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-solr</artifactId> <version>1.5.2.RELEASE</version> </dependency> <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-core</artifactId> <version>5.4.0</version> </dependency> </dependencies> </dependencyManagement> </project>