記錄自己的SSM框架配置
阿新 • • 發佈:2018-12-27
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>