一、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_2_5.xsd" id="WebApp_ID" version="2.5">
<!-- SpringMVC配置 开始 -->
<!-- Spring MVC 核心控制器 DispatcherServlet 配置 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 拦截所有/的请求,交给DispatcherServlet处理-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- SpringMVC配置 结束 -->
<!-- Spring配置 开始 -->
<!-- 配置Spring配置文件路径、将Shiro的配置文件交给Spring监听器初始化 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/spring-application.xml,classpath*:/spring/spring-shiro.xml</param-value>
</context-param>
<!-- 配置Spring上下文监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置Spring字符编码过滤器 -->
<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>
<!-- 只要发起的操作是一次HTTP请求,比如请求某个URL发起了一个GET请求、表单提交方式为POST时提交表单则发起了一个POST请求、
表单提交方式为GET时提交表单则发起了一次GET请求、一次重定向则前后相当于发起了两次请求,这些情况下有几次请求就会走几次指定过滤器 -->
<dispatcher>REQUEST</dispatcher>
<!-- 只有当当前页面是通过请求转发转发过来的场景,才会走指定的过滤器 -->
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- Spring配置 结束 -->
<!-- shiro配置 开始 -->
<!-- 由于项目通过Spring管理,因此所有的配置原则上都是交给Spring。
DelegatingFilterProxy的功能是通知Spring将所有的Filter交给ShiroFilter管理。 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- shiro配置 结束 -->
</web-app>
二、spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
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">
<!-- 自动扫描且只扫描@Controller -->
<context:component-scan base-package="com" use-default-filters="false">
<!-- 平台的controller,可以写多个 -->
<!-- type="aspectj" expression为AspectJ語法 例如:org.example..*Service+
type="regex" 表达式为正则表达式语法 例如:org\.example\.Default.* (.表示所有字符,而\.才表示真正的.字符)
-->
<context:include-filter type="aspectj" expression="com.jy.controller..*Controller"/>
</context:component-scan>
<!-- 对静态资源文件的访问
补充说明:多个HandlerMapping的执行顺序问题:
DefaultAnnotationHandlerMapping的order属性值是:0
<mvc:resources/ >自动注册的 SimpleUrlHandlerMapping的order属性值是: 2147483646
<mvc:default-servlet-handler/>自动注册的SimpleUrlHandlerMapping的order属性值是:2147483647
spring会先执行order值比较小的。
当访问一个a.jpg图片文件时,先通过DefaultAnnotationHandlerMapping 来找处理器,一定是找不到的,我们没有叫a.jpg的Action。
再按order值升序找,由于最后一个SimpleUrlHandlerMapping 是匹配"/**"的,所以一定会匹配上,再响应图片。
-->
<!-- 对静态资源文件的访问 方式1:SpringMVC3.0之后推荐使用 -->
<mvc:default-servlet-handler/>
<!-- 对静态资源文件的访问 方式2:SpringMVC3.0之前推荐使用 -->
<!--<mvc:resources mapping="/static/**" location="/static/" /> -->
<!--<mvc:resources mapping="/plugins/**" location="/plugins/" />
<mvc:resources mapping="/uploadFiles/**" location="/uploadFiles/" /> -->
<!-- freemarker的配置 -->
<!-- 配置freeMarker模板加载地址 -->
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/views/" />
<property name="defaultEncoding" value="utf-8" />
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">1</prop>
<prop key="locale">zh_CN</prop>
<prop key="datetime_format">yyyy-MM-dd</prop>
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="number_format">#.##</prop>
<prop key="auto_import">/manager/include/macro.ftl as ms</prop>
</props>
</property>
</bean>
<!-- FreeMarker视图解析 如返回student。。在这里配置后缀名ftl和视图解析器。。 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"></property>
<property name="suffix" value=".ftl" />
<property name="contentType" value="text/html;charset=utf-8" />
<property name="allowRequestOverride" value="true" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="exposeSpringMacroHelpers" value="true" />
<!-- 给视图解析器配置优先级,你可以给之后jsp视图解析器的值配为2 -->
<property name="order" value="1" />
</bean>
<!-- springmvc试图解析器 -->
<bean id="JSPviewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
<property name="order" value="2" />
</bean>
<mvc:annotation-driven>
<!--
<context:component-scan/>标签是告诉Spring 来扫描指定包下的类,并注册被@Component,@Controller,@Service,@Repository等注解标记的组件。
而<mvc:annotation-driven/>是告知Spring,我们启用注解驱动。
然后Spring会自动为我们注册几个Bean到工厂中,来处理我们的请求。
最重要的就是RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
第一个是HandlerMapping的实现类,它会处理@RequestMapping 注解,并将其注册到请求映射表中。
第二个是HandlerAdapter的实现类,它是处理请求的适配器,说白了,就是确定调用哪个类的哪个方法,并且构造方法参数,返回值。
-->
<!--
四种内置标签:
message-converters 出参转换 ,配置了@ResponseBody注解的时候才会生效
argument-resolvers 入参转换
async-support 异步支持
return-value-handlers
-->
<mvc:message-converters register-defaults="true">
<!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>text/json;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 默认编码 -->
<property name="defaultEncoding" value="utf-8" />
<!-- 文件大小最大值 -->
<property name="maxUploadSize" value="1048576000" />
<!-- 内存中的最大值 -->
<property name="maxInMemorySize" value="40960" />
</bean>
<!--
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.jy.interceptor.ActionInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
-->
</beans>
三、spring-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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<description>Spring Configuration</description>
<!-- 启用注解 -->
<!--
当我们需要使用注解模式时,直接在Spring配置文件中定义这些Bean显得比较笨拙,例如:
使用@Autowired注解,必须事先在Spring容器中声明AutowiredAnnotationBeanPostProcessor的Bean
使用@Required注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean
这样的声明未免太不优雅,而Spring为我们提供了一种极为方便注册这些BeanPostProcessor的方式,
即使用<context:annotation- config/>
隐式地向 Spring容器注册AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、
CommonAnnotationBeanPostProcessor以及PersistenceAnnotationBeanPostProcessor这4个BeanPostProcessor。
-->
<context:annotation-config />
<!-- 启动组件扫描,排除@Controller组件,该组件由SpringMVC配置文件扫描 -->
<!-- 使用注解时一般都会配置扫描包路径选项,即<context:component-scan/>。
该配置项其实也包含了自动注入上述Processor的功能,因此当使用<context:component-scan/>后,即可将<context:annotation-config/>省去,但必须要配置全!
以防万一,还是同时声明的好。 -->
<context:component-scan base-package="com.jy">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<import resource="spring-datasource.xml"/>
</beans>
spring-datasource.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/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"
default-lazy-init="true">
<!-- 数据源配置, 使用应用服务器的数据库连接池 -->
<!--<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/${jndi.name}" />-->
<!-- 读取数据库配置文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath*:/spring/dbconfig.properties" />
<!-- 配置数据源 -->
<bean name="mysqlDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.mysql.driver}"/>
<property name="url" value="${jdbc.mysql.url}" />
<property name="username" value="${jdbc.mysql.username}" />
<property name="password" value="${jdbc.mysql.password}" />
<!-- 如果数据源的defaultAutoCommit设置为True了,那么方法中如果自己捕获了异常,事务是不会回滚的,
如果没有自己捕获异常则事务会回滚 -->
<property name="defaultAutoCommit" value="true"></property>
<!-- 初始化连接数量 -->
<property name="initialSize" value="${druid.initialSize}" />
<!-- 最大并发连接数 -->
<property name="maxActive" value="${druid.maxActive}" />
<!-- 最大空闲连接数 -->
<!-- <property name="maxIdle" value="${druid.maxIdle}" /> -->
<!-- 最小空闲连接数 -->
<property name="minIdle" value="${druid.minIdle}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${druid.maxWait}" />
<!-- 超过时间限制是否回收 -->
<property name="removeAbandoned" value="${druid.removeAbandoned}" />
<!-- 超过时间限制多长; -->
<property name="removeAbandonedTimeout" value="${druid.removeAbandonedTimeout}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}" />
<!-- 用来检测连接是否有效的sql,要求是一个查询语句-->
<property name="validationQuery" value="${druid.validationQuery}" />
<!-- 申请连接的时候检测 -->
<property name="testWhileIdle" value="${druid.testWhileIdle}" />
<!-- 申请连接时执行validationQuery检测连接是否有效,配置为true会降低性能 -->
<property name="testOnBorrow" value="${druid.testOnBorrow}" />
<!-- 归还连接时执行validationQuery检测连接是否有效,配置为true会降低性能 -->
<property name="testOnReturn" value="${druid.testOnReturn}" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="${druid.poolPreparedStatements}" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="${druid.maxPoolPreparedStatementPerConnectionSize}" />
<!--属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
监控统计用的filter:stat
日志用的filter:log4j
防御SQL注入的filter:wall -->
<property name="filters" value="${druid.filters}" />
</bean>
<!-- MyBatis配置 -->
<bean id="mysqlSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- dataSource属性是必须指定的,它表示用于连接数据库的数据源 -->
<property name="dataSource" ref="mysqlDataSource" />
<!--
用于指定Mybatis的配置文件位置。如果指定了该属性,那么会以该配置文件的内容作为配置信息构建对应的SqlSessionFactoryBuilder,
但是后续属性指定的内容会覆盖该配置文件里面指定的对应内容。
-->
<property name="configLocation" value="classpath:/spring/mybatis-config.xml" />
<!-- 自动扫描entity实体类目录, 省掉xml里的手工配置
它一般对应我们的实体类所在的包,这个时候会自动取对应包中,不包括包名的简单类名,作为,包括包名的别名。
User 作为com.jy.entiry.user.User 的别名。
多个package之间可以用逗号或者分号等来进行分隔。(value的值一定要是包的全名)
-->
<property name="typeAliasesPackage" value="com.jy.entity" />
<!-- 显式指定Mapper文件位置
它表示我们的Mapper文件存放的位置,当我们的Mapper文件跟对应的Mapper接口处于同一位置的时候可以不用指定该属性的值
-->
<property name="mapperLocations">
<list>
<value>classpath:/mybatis/**/**/*Mapper.xml</value>
</list>
</property>
<!-- 数组类型,用来指定Mybatis的Interceptor -->
<property name="plugins"><array><ref bean="pagePlugin" /></array></property>
</bean>
<!-- 分页配置-->
<bean id="pagePlugin" class="com.jy.common.mybatis.PageInterceptor">
<property name="properties">
<props>
<prop key="databaseType">mysql</prop>
</props>
</property>
</bean>
<!-- 分页配置end-->
<!-- 这段配置会扫描basePackage下所有以@JYBatis标识的 接口,然后spring内部 创建各自接口的动态代理类。(动态代理:代理类在程序运行时被创建 。)
理解1:Mapper接口生成代理注入到Spring
理解2:Spring创建的代理类实现了 Mapper接口,并且注入到Spring
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="mysqlSqlSessionFactory"/>
<property name="basePackage" value="com.jy.repository" />
<!-- 优化速度-->
<property name="annotationClass" value="com.jy.repository.base.JYBatis"/>
</bean>
<!-- 配置声明式事务管理器 -->
<bean id="mysqlTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="mysqlDataSource" />
</bean>
<!-- 拦截器方式配置事务 -->
<tx:advice id="mysqlTransactionAdvice" transaction-manager="mysqlTransactionManager">
<tx:attributes>
<!-- 对save,insert,update,delete 开头的方法进行事务管理,只要有异常就回滚 -->
<tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
<!-- find,select,count开头的方法,开启只读,提高数据库访问性能 -->
<tx:method name="find*" read-only="true" />
<tx:method name="select*" read-only="true"/>
<tx:method name="count*" read-only="true"/>
<!-- 对其他方法 使用默认的事务管理 -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<!-- 定义切入点 -->
<aop:pointcut id="mysqlTransactionPointcut" expression="execution(* com.jy.service.*.*(..))" />
<!-- 将事务通知 与 切入点组合 -->
<aop:advisor pointcut-ref="mysqlTransactionPointcut" advice-ref="mysqlTransactionAdvice" order="1"/>
</aop:config>
<!-- 开启注解事务
基于JDK动态代理 ,可以将@Transactional放置在接口和具体类上。
基于CGLIB类代理(proxy-target-class="true"),只能将@Transactional放置在具体类上。
-->
<tx:annotation-driven transaction-manager="mysqlTransactionManager" proxy-target-class="true" order="0"/>
<!--
备注:当同时配置声明式事务 和 注解式事务时,可通过order值进行排序,order值越小,在AOP的chain 中越靠前,越先执行。这样就属于事务嵌套。
-->
</beans>
JYBatis注解
package com.jy.repository.base;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
/**
* 标识MyBatis的DAO,方便{@link org.mybatis.spring.mapper.MapperScannerConfigurer}的扫描。
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Component
public @interface JYBatis {
String value() default "";
}
四、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>
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- <setting name="logImpl" value="LOG4J" /> -->
</settings>
<!-- mapper已经在spring-datasource.xml中的sqlSessionFactory配置,这里不再需要配置 -->
<!-- <mappers> -->
<!-- <mapper resource="com/a/b/c/dao/BusinessInfoDaoMapper.xml" /> -->
<!-- </mappers> -->
</configuration>
五、spring-shiro.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-4.0.xsd"
default-lazy-init="true">
<description>Shiro Configuration</description>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="ShiroRealm" />
<!-- <property name="sessionManager" ref="sessionManager"/> -->
<!-- 使用下面配置的缓存管理器 -->
<!-- <property name="cacheManager" ref="cacheManager" /> -->
</bean>
<!-- Realm实现:項目自定义的Realm -->
<bean id="ShiroRealm" class="com.jy.interceptor.shiro.ShiroRealm" ></bean>
<!-- Shiro Filter Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- 如果你没有登录,访问有登录验证的请求,都会跳转到/loginIndex页面 -->
<property name="loginUrl" value="/loginIndex" />
<!-- 登录成功跳转的页面 -->
<property name="successUrl" value="/backstage/index" />
<!-- 没有权限跳转的页面 -->
<property name="unauthorizedUrl" value="/loginIndex" />
<!-- anon:匿名拦截器,即不需要登录即可访问;一般用于静态资源过滤
authc:如果没有登录会跳到相应的登录页面登录
表示访问该地址用户【必须身份验证通过】(Subject. isAuthenticated()==true)
user:用户拦截器,用户已经身份验证/记住我登录的都可 -->
<property name="filterChainDefinitions">
<value>
/api/** = anon
/iclock/** = anon
/static/js/system/login/** = anon
/static/js/system/** = authc
/static/** = anon
/favicon.ico = anon
/verifyCode/** = anon
/system_login = anon
/exterInt/** = anon
/weixin/** = anon
/upload/** = anon
/** = authc
</value>
</property>
</bean>
<!-- 缓存管理器 使用Ehcache实现-->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:/spring/ehcache.xml"/>
</bean>
<!-- AOP式方法级权限检查 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>
六、ShiroRealm
package com.jy.interceptor.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* 用户身份验证,授权 Realm 组件
*
**/
public class ShiroRealm extends AuthorizingRealm {
// @Resource
// private UserService userService;
//
// @Resource
// private RoleService roleService;
//
// @Resource
// private PermissionService permissionService;
/**
* 权限检查(添加角色、权限)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
String username = String.valueOf(principals.getPrimaryPrincipal());
// final User user = userService.selectByUsername(username);
// final List<Role> roleInfos = roleService.selectRolesByUserId(user.getId());
// for (Role role : roleInfos) {
// // 添加角色
// System.err.println(role);
// authorizationInfo.addRole(role.getRoleSign());
//
// final List<Permission> permissions = permissionService.selectPermissionsByRoleId(role.getId());
// for (Permission permission : permissions) {
// // 添加权限
// System.err.println(permission);
// authorizationInfo.addStringPermission(permission.getPermissionSign());
// }
// }
return authorizationInfo;
}
/**
* 登录验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = String.valueOf(token.getPrincipal());
String password = new String((char[]) token.getCredentials());
// 通过数据库进行验证
// ...
// 在 shiro 中,用户需要提供 principals (身份)和 credentials(证明)给 shiro,从而应用能验证用户身份
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName());
return authenticationInfo;
}
}