基于Maven的SSM总体架构设计(五)

3.4.9 引入log4j,完善日志输出体系

        为了跟踪程序的运行状况,方便调试。日志是必不可少的。Log4j是目前最流行的日志框架,几乎所有的其他框架都用到了log4j,具体使用步骤如下:
1、在src/main/resources下增加log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	<!-- ========================== 自定义输出格式说明================================ -->
	<!-- %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL -->
	<!-- #%r 输出自应用启动到输出该log信息耗费的毫秒数 -->
	<!-- #%c 输出所属的类目,通常就是所在类的全名 -->
	<!-- #%t 输出产生该日志事件的线程名 -->
	<!-- #%n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n” -->
	<!-- #%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 
		22:10:28,921 -->
	<!-- #%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10) -->
	<!-- ========================================================================== -->

	<!-- ========================== 输出方式说明================================ -->
	<!-- Log4j提供的appender有以下几种: -->
	<!-- org.apache.log4j.ConsoleAppender(控制台), -->
	<!-- org.apache.log4j.FileAppender(文件), -->
	<!-- org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件), -->
	<!-- org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件), -->
	<!-- org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) -->
	<!-- ========================================================================== -->
	
	<!-- 输出到日志文件 每天一个日志 -->
	<appender name="filelog_daily" class="org.apache.log4j.DailyRollingFileAppender">
		<param name="File" value="${pass}logs/mesnac_logs_daily.log" />
		<param name="DatePattern" value="'daily.'yyyy-MM-dd'.log'" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern"
				value="[%d{yyyy-MM-dd HH:mm:ss\} %-5p] [%t] (%c:%L) - %m%n" />
		</layout>
	</appender>

	<!-- 输出到控制台中 -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss\} %-5p] (%c:%L) - %m%n" />
			<!-- <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p: %m%n" /> -->
			<!-- "%-5p: [%t] [%c{3}.%M(%L)] | %m%n" -->
		</layout>
		<!-- 限制日志输出级别 -->
		<filter class="org.apache.log4j.varia.LevelRangeFilter">
			<param name="LevelMax" value="ERROR" />
			<param name="LevelMin" value="TRACE" />
		</filter>
	</appender>

	<!-- 发邮件(只有ERROR时才会发送) -->
	<appender name="mail" class="org.apache.log4j.net.SMTPAppender">
		<param name="threshold" value="ERROR" />
		<!-- 缓存文件大小,日志达到512k时发送Email -->
		<param name="BufferSize" value="512" />
		<param name="From" value="[email protected]" />
		<param name="SMTPHost" value="smtp.126.com" />
		<param name="Subject" value="Archimedes-log4jMessage" />
		<param name="To" value="[email protected]" />
		<param name="SMTPUsername" value="zhenglibingaccp" />
		<param name="SMTPPassword" value="qibing791014" />
		<layout  class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss.SSS} [%p]-[%c] %m%n" />
		</layout>
	</appender>

	<!-- 通过<category></category>的定义可以将各个包中的类日志输出到不同的日志文件中-->
	<!-- 
	<category name="com.mesnac" additivity="false">
		<level value="INFO" />
		<appender-ref ref="filelog_daily" />
		<appender-ref ref="console" />
		<appender-ref ref="mail" />
	</category>
	-->
	 
	<root>
		<level value="DEBUG" />
		<!-- <appender-ref ref="filelog_appender" /> -->
		<!-- <appender-ref ref="filelog_daily" /> -->
		<appender-ref ref="console" />
	</root>
</log4j:configuration>  

2、修改web.xml,增加对log4j的支持

<context-param>
	<param-name>log4jConfigLocation</param-name>
	<param-value>classpath:log4j.xml</param-value>
</context-param>
<context-param>
	<param-name>log4jRefreshInterval</param-name>
	<param-value>60000</param-value>
</context-param>

3、编写日志服务类com.mesnac.util.LogService

package com.mesnac.util;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

/**
 * 功能说明:日志记录服务类
 * 修改说明:
 * @author zhenglibing
 * @date 2017-4-25 下午4:01:24
 * @version V0.1
 */
public final class LogService {
	private static LogService instance;
	private static Logger logger = null;
	private static Map<Class, Logger> loggerList = new HashMap<Class, Logger>();	//用于缓存logger对象
	
	/**
	 * 定义私有构造方法实现单例
	 */
	private LogService() {
	}
	
	/**
	 * 功能说明:获取服务实例的静态方法
	 * 修改说明:
	 * @author zhenglibing
	 * @date 2017-4-25 下午4:02:09
	 * @param obj 传入调用此方法的对象
	 * @return
	 */
	public synchronized static LogService getInstance(Object obj) {
		if (instance == null) {
			instance = new LogService();
		}
		LogService.logger = loggerList.get(obj.getClass());
		if (LogService.logger == null) {
			LogService.logger = Logger.getLogger(obj.getClass());
			loggerList.put(obj.getClass(), LogService.logger);
		}
		return instance;
	}
	
	/**
	 * 功能说明:获取服务实例的静态方法
	 * 修改说明:
	 * @author zhenglibing
	 * @date 2017-4-25 下午4:03:10
	 * @param clazz 传入调用此方法的类型
	 * @return
	 */
	public synchronized static LogService getInstance(Class clazz) {
		if (instance == null) {
			instance = new LogService();
		}
		LogService.logger = loggerList.get(clazz);
		if (LogService.logger == null) {
			LogService.logger = Logger.getLogger(clazz);
			loggerList.put(clazz, LogService.logger);
		}
		return instance;
	}
	
	/**
	 * 功能说明:获取服务实例的静态方法
	 * 修改说明:
	 * @author zhenglibing
	 * @date 2017-4-25 下午4:05:13
	 * @return
	 */
	public synchronized static LogService getInstance() {
		if (instance == null) {
			instance = new LogService();
		}
		LogService.logger = loggerList.get(LogService.class);
		if (LogService.logger == null) {
			LogService.logger = Logger.getLogger(LogService.class);
			loggerList.put(LogService.class, LogService.logger);
		}
		return instance;
	}
	
	public void trace(Object message) {
		LogService.logger.trace(message);
	}
	
	public void trace(Object message, Throwable t) {
		LogService.logger.trace(message, t);
	}
	
	public void debug(Object message) {
		LogService.logger.debug(message);
	}
	
	public void debug(Object message, Throwable t) {
		LogService.logger.debug(message, t);
	}
	
	public void info(Object message) {
		LogService.logger.info(message);
	}
	
	public void info(Object message, Throwable t) {
		LogService.logger.info(message, t);
	}
	
	public void warn(Object message) {
		LogService.logger.warn(message);
	}
	
	public void warn(Object message, Throwable t) {
		LogService.logger.warn(message, t);
	}
	
	public void error(Object message) {
		LogService.logger.error(message);
	}

	public void error(Object message, Throwable t) {
		LogService.logger.error(message, t);
	}
}

4、编写日志服务测试类,运行测试

public class LogServiceTestCase {
	@Test
	public void testDebug() {
		LogService.getInstance(this).debug("This is Debug log");
	}
	@Test
	public void testInfo() {
		LogService.getInstance(this).info("This is Info log");
	}
	@Test
	public void testWarn() {
		LogService.getInstance(this).warn("This is warn log");
	}
	@Test
	public void testError() {
		LogService.getInstance(this).error("This is error log");
	}
}

5、在dao、service、action中使用LogService

3.4.10 引入Shiro,实现身份验证与授权访问

直接说使用步骤吧:
1、在pom.xml中增加shiro依赖库

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-all</artifactId>
    <version>1.2.1</version>
</dependency>

2、在src/main/java下增加Realm相关代码
shiro代码
3、在src/main/resources下增加ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
	updateCheck="false">

	<defaultCache maxElementsInMemory="10000" eternal="false"
		overflowToDisk="false" timeToIdleSeconds="500" timeToLiveSeconds="1000"
		diskPersistent="false" diskExpiryThreadIntervalSeconds="120" />
		
	<cache name="shiroAuthorizationCache" maxElementsInMemory="10000"
		eternal="false" overflowToDisk="false" diskPersistent="false"
		timeToIdleSeconds="120" timeToLiveSeconds="120"
		diskExpiryThreadIntervalSeconds="120" />
</ehcache>

4、在src/main/resources下增加spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans 	xmlns="http://www.springframework.org/schema/beans" 
		xmlns:cache="http://www.springframework.org/schema/cache"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xmlns:context="http://www.springframework.org/schema/context"
		xmlns:task="http://www.springframework.org/schema/task" 
		xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context-3.0.xsd
						http://www.springframework.org/schema/task 
						http://www.springframework.org/schema/task/spring-task-3.1.xsd 
						http://www.springframework.org/schema/mvc 
						http://www.springframework.org/schema/mvc/spring-mvc.xsd 
						http://www.springframework.org/schema/cache
                        http://www.springframework.org/schema/cache/spring-cache-3.2.xsd   ">
	
	<!-- 启用缓存注解功能(请将其配置在Spring主配置文件中)  --> 
    <cache:annotation-driven cache-manager="cacheManager"/>  
	<!-- ehcache 的配置 -->
	<!-- Spring提供的基于的Ehcache实现的缓存管理器 -->  
    <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
        <property name="configLocation" value="classpath:ehcache.xml"/>  
    </bean>  
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">  
        <property name="cacheManager" ref="cacheManagerFactory"/>  
    </bean>  
	
	<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->  
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
	<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> 
    	<property name="cacheManager" ref="cacheManagerFactory"/> 
    </bean>
    
    <!-- 配置ModularRealmAuthenticator,可以实现多Realm认证 -->
    <!-- <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> -->
    <bean id="authenticator" class="com.wongoing.sys.shiro.ShiroMulityModularRealmAuthenticator">
    	<!-- 配置认证策略,只要有一个Realm认证成功即可,并且返回所有认证成功信息 -->
    	<property name="authenticationStrategy">
    		<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
    	</property>
    </bean>
    
	<!-- 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的MesnacShiroRealm.java -->  
	<bean id="shiroUserRealm" class="com.wongoing.sys.shiro.ShiroUserRealm">
		<property name="cacheManager" ref="shiroCacheManager"/> 
	    <property name="authenticationCacheName" value="shiroAuthorizationCache"></property>
	    <!--配置密码匹配器-->
	    <property name="credentialsMatcher">
	    	<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
	    		<!-- 加密算法可以为MD5、SHA-1、SHA-256、SHA-512,此处使用的SHA-1 -->
	    		<property name="hashAlgorithmName" value="SHA-1" />
	    		<!-- 加密次数 -->
	    		<property name="hashIterations" value="1024" />
	    	</bean>
	    </property>
	</bean>
	
	<!-- Shiro默认会使用Servlet容器的Session,可通过sessionMode属性来指定使用Shiro原生Session -->  
	<!-- 即<property name="sessionMode" value="native"/>,详细说明见官方文档 -->  
	<!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 -->  
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<!-- 以下为单realm配置 -->  
	    <!--<property name="realm" ref="shiroRealm"/>-->
	    <property name="authenticator" ref="authenticator"/>
	    <!--可以配置多个Realm,其实会把realms属性赋值给ModularRealmAuthenticator的realms属性 -->
	    <property name="realms">
	    	<list>
	    		<ref bean="shiroUserRealm" />
	    	</list>
	    </property>  
	</bean>
	  
	<!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->  
	<!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 -->  
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
	    <!-- Shiro的核心安全接口,这个属性是必须的 -->  
	    <property name="securityManager" ref="securityManager"/>  
	    <!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->  
	    <property name="loginUrl" value="/start.jsp"/>  
	    <!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码为main.jsp了) -->  
	    <property name="successUrl" value="/index.jsp"/> 
	    <!-- 用户访问未对其授权的资源时,所显示的连接 -->  
	    <!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp,然后用[玄玉]登录后访问/admin/listUser.jsp就看见浏览器会显示unauthor.jsp -->  
	    <property name="unauthorizedUrl" value="/"/>  
	    <property name="filterChainDefinitions">  
	        <value>  
	             /favicon.ico = anon
	             /Kaptcha.jpg = anon
		       	 /release/** = anon
		       	 /resources/** = anon  
		       	 /resources/frontPage/** = anon 
		       	 /extend/** = anon
		       	 /druid/** = anon
		       	 /start.jsp = anon
		       	 /error.jsp = anon
		       	 /fail.jsp = anon
		       	 /upload/** = anon
		       	 /img/** = anon
		       	 /jsp/system/login.jsp = anon
		       	 /sys/sysUserAction/login =  anon
		       	 /ws/** = anon
		       	 /front/** = anon
		       	 /front2/** = anon
	             /** = authc 
	        </value>  
	    </property>
	</bean>
</beans>

5、修改web.xml增加对shiro的支持

<!-- 配置Spring配置文件的位置 -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:spring.xml,classpath:spring-shiro.xml</param-value>
</context-param>
<!-- 配置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>

6、通过Subject来进行认证和授权
图3-13
7、菜单权限-MesnacShiroRealm
图3-14
8、菜单权限-index.jsp
图3-15
9、操作权限-MesnacShrioRealm
图3-16
10、操作权限-xxx.jsp
图3-17

<%@ taglib uri=“http://shiro.apache.org/tags” prefix=“shiro” %>
<shrio:hasPermission name=“”></shiro:hasPermission>
<shiro:guest>我的账户</shiro:guest>
<shiro:user><shiro:principal /></shiro:user>

(未完待续…)
完整资料下载

猜你喜欢

转载自blog.csdn.net/zlbdmm/article/details/83185086