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>
<groupId>org.welkin</groupId>
<artifactId>ssm</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>demo Maven Webapp</name>
<url>http://www.example.com</url>
<!-- 自动生成代码 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
</dependencies>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
<properties>
<!-- spring -->
<spring.version>4.3.9.RELEASE</spring.version>
<!-- mybatis -->
<mybatis.version>3.4.1</mybatis.version>
<!-- shiro -->
<shiro.version>1.3.2</shiro.version>
<!-- log -->
<slf4j.version>1.7.7</slf4j.version>
<log4j.version>1.2.17</log4j.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</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.3.0</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- jstl -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<!-- shiro -->
<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>
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<!-- commons -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<!-- log -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- generator -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
</project>
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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启Spring 自动扫描注解包 -->
<context:component-scan base-package="org.welkin.ssm"/>
<!-- 开启注解 -->
<mvc:annotation-driven/>
<!-- 释放静态资源 -->
<mvc:default-servlet-handler/>
<!-- swagger 配置 ,线上版本需要注释掉 -->
<bean class="org.welkin.ssm.util.swagger.SwaggerConfig"/>
<!-- swagger ui resources-->
<mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/"/>
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>
<!-- 配置SpringMVC的视图解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="1"/>
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
<property name="contentType" value="text/html; charset=utf-8"/>
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
</bean>
<!-- 根目录'/'对应页面 -->
<mvc:view-controller path="/" view-name="/index"/>
<!-- 配置多文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 默认编码 -->
<property name="defaultEncoding" value="UTF-8" />
<!-- 文件大小最大值 -->
<!-- 上传文件大小限制为31M,31*1024*1024单位是字节 -->
<property name="maxUploadSize" value="32505856" />
<!-- 内存中的最大值 -->
<property name="maxInMemorySize" value="4096" />
<!-- 启用目的:延迟文件解析,以便捕获文件大小异常 -->
<property name="resolveLazily" value="true" />
</bean>
<!-- i18n国际化 -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!-- 找不到key时用key作为返回值 -->
<property name="useCodeAsDefaultMessage" value="false"/>
<!-- 资源刷新时间 -->
<property name="cacheSeconds" value="60"/>
<!-- 资源文件列表 -->
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
</beans>
SwaggerConfig.java 文件配置
package org.welkin.ssm.util.swagger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author Hyoutei
* @version 1.0
* @date 2018/8/3 15:04
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().build();
}
}
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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 引入jdbc配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 -->
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 初始化并发连接数量 -->
<property name="initialSize" value="1"/>
<!-- 最小并发连接数量 -->
<property name="minIdle" value="1"/>
<!-- 最大并发连接数量 -->
<property name="maxActive" value="30"/>
<!-- 连接等待超时时间 毫秒 -->
<property name="maxWait" value="60000"/>
<!--使用非公平锁-->
<property name="useUnfairLock" value="true"/>
<!--申请连接检测 如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。-->
<property name="testWhileIdle" value="true"/>
<!-- 一个连接在池中最小生存时间 毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<!-- 间隔多久进行一次空闲连接关闭检测 毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 检测连接是否有效的sql 查询语句-->
<property name="validationQuery" value="select 1"/>
<!--申请连接时执行validationQuery检测连接是否有效 -->
<property name="testOnBorrow" value="false"/>
<!--归还连接时执行validationQuery检测连接是否有效 -->
<property name="testOnReturn" value="false"/>
<!-- 打开PSCache 指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true"/>
<property name="maxOpenPreparedStatements" value="20"/>
<!-- 解密 -->
<property name="filters" value="config"/>
<property name="connectionProperties" value="config.decrypt=true;config.decrypt.key=${jdbc.encrypt}"/>
</bean>
<!-- 配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 自动扫描mapping.xml文件,自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
<property name="mapperLocations" value="classpath:org/welkin/ssm/mapper/impl/*.xml"/>
</bean>
<!-- 自动扫描mybatis映射文件和接口的包 -->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.rock.tjhd.mapper"/>
</bean>
<!-- 配置基于注解的声明式事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 注解方式配置事物 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
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.xsd">
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 缓存管理器 使用Ehcache实现 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean>
<!-- 凭证匹配器 -->
<bean id="credentialsMatcher"
class="org.welkin.ssm.util.shiro.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager"/>
<!-- 加密算法 -->
<property name="hashAlgorithmName" value="md5"/>
<!-- 加密次数 -->
<property name="hashIterations" value="512"/>
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
<!-- realm实现 -->
<bean id="userRealm" class="org.welkin.ssm.util.shiro.UserRealm">
<!-- 凭证匹配器 -->
<property name="credentialsMatcher" ref="credentialsMatcher"/>
<property name="cachingEnabled" value="true"/>
<!-- 如需要自定义缓存时间放开以下.修改 ehcache.xml -->
<property name="authenticationCachingEnabled" value="true"/>
<property name="authenticationCacheName" value="authenticationCache"/>
<property name="authorizationCachingEnabled" value="true"/>
<property name="authorizationCacheName" value="authorizationCache"/>
</bean>
<!-- Shiro安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"/>
<property name="cacheManager" ref="cacheManager"/>
</bean>
<!-- 登出过滤器 -->
<bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="/login.jsp"/>
</bean>
<!-- Shiro主过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
<!-- <property name="loginUrl" value="/security/login"></property> -->
<!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码) -->
<!-- <property name="successUrl" value="/" ></property> -->
<!-- 用户访问未对其授权的资源时,所显示的连接 -->
<property name="unauthorizedUrl" value="/"/>
<!-- 访问权限配置,anon不需要权限可以访问,authc需要权限,如果没有登陆则跳回登陆界面 -->
<!-- 这些是对url进行匹配 -->
<property name="filterChainDefinitions">
<value>
<!-- 静态资源允许访问 -->
/resources/** = anon
<!-- 登录注册允许访问 -->
/login* = anon
/register* = anon
<!-- 登出 -->
/logout = logout
<!-- 其他资源需要认证 -->
/** = authc
<!-- perms[user:query]表示访问此连接需要权限为user:query的用户 -->
<!-- /user=perms[user:query] -->
<!-- roles[manager]表示访问此连接需要用户的角色为manager -->
<!-- /user/add=roles[manager] -->
</value>
</property>
</bean>
</beans>
RetryLimitHashedCredentialsMatcher.java 文件配置
package org.welkin.ssm.util.shiro;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Hyoutei
* @version 1.0
* @date 2018/8/3 15:12
*/
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
/**
* AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。
*/
private Cache<String, AtomicInteger> passwordRetryCache;
public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
//获取密码错误次数缓存对象
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
}
/**
* 控制密码输入错误次数
*
* @param token AuthenticationToken
* @param info AuthenticationInfo
* @return boolean
*/
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
String principal = (String) token.getPrincipal();
AtomicInteger atomicInteger = passwordRetryCache.get(principal);
if (atomicInteger == null) {
atomicInteger = new AtomicInteger(0);
passwordRetryCache.put(principal, atomicInteger);
}
// 如果重试次数超过5次则抛出异常
if (atomicInteger.incrementAndGet() > 5) {
throw new ExcessiveAttemptsException();
}
// 调用父类的验证
boolean doCredentialsMatch = super.doCredentialsMatch(token, info);
// 如果账号密码正确,清除重试次数
if (doCredentialsMatch) {
passwordRetryCache.remove(principal);
}
return doCredentialsMatch;
}
}
UserRealm.java 文件配置
package org.welkin.ssm.util.shiro;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.HashSet;
import java.util.UUID;
/**
* @author Hyoutei
* @version 1.0
* @date 2018/8/3 15:16
*/
public class UserRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
if (principals == null) {
throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
}
HashSet<String> roles = new HashSet<>();
HashSet<String> permissions = new HashSet<>();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
info.setStringPermissions(permissions);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
if (username == null || username.equals("")) {
throw new AccountException("Null usernames are not allowed by this realm.");
}
return new SimpleAuthenticationInfo(username, "password".toCharArray(), ByteSource.Util.bytes("salt"), getName());
}
public static void main(String[] args) {
Object password = "111111";
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
System.out.println("salt : " + uuid);
Object salt = ByteSource.Util.bytes(uuid);
Object result = new SimpleHash("MD5", password, salt, 512);
System.out.println("result : " + result);
}
}
ehcache.xml 文件配置
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shirocache">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
<!-- 登录记录缓存 锁定5分钟 -->
<cache name="passwordRetryCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro-activeSessionCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
<cache name="shiro_cache"
maxElementsInMemory="2000"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
maxElementsOnDisk="0"
overflowToDisk="true"
memoryStoreEvictionPolicy="FIFO"
statistics="true">
</cache>
</ehcache>
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"
version="3.0">
<display-name>ssm</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>ssm</param-value>
</context-param>
<!-- 指定Spring的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mybatis.xml,classpath:spring-shiro.xml</param-value>
</context-param>
<!--实例化Spring容器,应用启动时,该监听器被执行,它会读取Spring相关配置文件 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 解决乱码问题 -->
<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>
<!--配置SpringMVC核心控制器 -->
<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>
<url-pattern>/v2/api-docs</url-pattern>
<url-pattern>/swagger-resources</url-pattern>
<url-pattern>/swagger-resources/configuration/ui</url-pattern>
<url-pattern>/swagger-resources/configuration/security</url-pattern>
</servlet-mapping>
<!-- 日志记录 -->
<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>60000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>