Spring Oauth2大多数情况下还是用不到的,主要使用的还是Spring+SpringMVC+Hibernate,有时候加上SpringSecurity,因此,本文及以后的文章的example中都不会包含oauth2的配置,需要的话把前文的applicationContext-security.xml和pom.xml加上就可以了,本文在“SSH+Spring Security搭建方法及example”一文的基础上做一些调整,主要内容是:配置Spring AOP并且用log4j来记录日志。

1. 微调了部分配置文件

前文的pom.xml、spring-dispatcher-servlet.xml、applicationContext.xml等配置文件都是一点一点加的,本文附的代码做了一些调整。

这几个文件不需要做什么实质性的修改,只是做了微调,换了换内容的位置,不多做描述。

2. Spring AOP

面向方面编程 (Aspect Oriented Programming,AOP) 将程序分解成各个方面或者叫关注点。有了AOP,像事务管理这些功能就可以横切多个对象的关注点。AOP的主要功能就是记录日志、事务管理或者数据校验,我的例子是为了记录日志。

Spring AOP的机制我两年前用SSH的时候就不是非常清楚,所以这里除了用法之外,多说几个关键概念:

  • Aspect:Aspect就是一个类,它的方法要插入到其他类执行过程中,这个类可以通过XML配置,也可以通过@Aspect注解与Spring的AspectJ整合,比如说我要在日志里为每一个DAO的查询方法记录执行时间,那么记录时间的这些切面方法所在的类就是Aspect;
  • Join Point:连接点,就是要插入方面代码的点,上面的例子中,每一个要被记录时间的dao方法就是一个Joinpoint;
  • Advice:通知,某一个JoinPoint可以有多个通知,比如方法执行前“before”,方法执行前后“around”等,主要就是before、after、after returning、after throwing、arount这5种;
  • Pointcut:是匹配Join Point的一个表达式,来决定Advice是否要触发。

下面就看具体的配置,当年是用XML来配置的,现在用aspectj提供的注解,要更方便和直观一些。

首先在pom.xml中引入aspectj的包(spring aop的包在前文中作为依赖已经引入了):

<properties>
……
<aspectj.version>1.8.2</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>

下面创建Aspect类,创建一个叫aspect的package(我的项目中是org.zhangfc.demo4ssh.aspect),并创建Aspect类:

@Component
@Aspect
public class LogAspect { }

@Aspect是一个aspectj提供的注解,spring-aop可以根据这个注解以及PointCut等注解来解析aop配置,这儿需要注意的是@Component注解,我一开始怎么也配不出来,后来发现Spring容器里面根本没有生成logAspect这个bean,因为@Aspect这个注解并不是Spring自己的,IoC模块并不认识这个注解,所以没有创建管理这个bean。加上@Component这个注解就是为了让Spring来管理它。

下面加一个最简单的通知:

@Before("execution(* org.zhangfc.demo4ssh.service..*.*(..))")
public void loggingServiceAdvice() {
System.out.println("Executing Service...");
}

这个通知是说,在service包及service子包下的任何类的具有任意参数和返回值的任何方法,在执行之前(@Before)都要执行这个方法。

因为要让Spring来管理这个bean,自然要配置一下让Spring去自动扫描Aspect所在的package,打开applicationContext.xml,加入:

<context:component-scan base-package="org.zhangfc.demo4ssh.aspect"/>

因为我现在配置aop主要是为了记录日志,所以aop的配置放在hibernate的配置文件里,打开infrastructure.xml,在最后加入一句让aop自动代理aspectj的配置:

<aop:aspectj-autoproxy />

然后运行程序,在执行Service方法的时候,就会打印出Executing Service...的语句。这只是一个简单的demo,下面来配置我们真正需要的,对dao访问的日志,首先来把程序中抛异常的情况都记下来,在LogAspect类中添加下面的方法:

@AfterThrowing(value="within(org.zhangfc.demo4ssh..*)", throwing = "ex")
public void loggingExceptions(JoinPoint joinPoint, Exception ex) {
System.err.println("Exception thrown in Method = "
+ joinPoint.toString() + " " + ex.getClass().getSimpleName() + " = " + ex.getMessage());
}

@AfterThrowing是在匹配的方法抛出异常的情况下执行,我这个配置就是指明在我的项目包下面任意package的任意类中,抛出异常之后都会让loggingExceptions来记录,现在我在某个Dao方法中写了一行会抛异常的代码:

Integer.parseInt("asd");

运行过程中就会打印如下的内容:

Exception thrown in Method = execution(List org.zhangfc.demo4ssh.service.UserService.getAllUsers()) NumberFormatException = For input string: "asd"

最后配置dao的访问记录,我要在每一个dao方法执行前后各创建一个切面,那么就要用到@Around通知了,首先来创建一个Pointcut:

@Pointcut("execution(* org.zhangfc.demo4ssh.repo..*.*(..))")
public void daoPointCut() {
}

这个Pointcut匹配了repo package及子package下的任意类的任意方法,之后就可以根据这个Pointcut来创建Around通知:

@Around("daoPointCut()")
public Object loggingAround(ProceedingJoinPoint joinpoint) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("method starts...."
+ joinpoint.getSignature().getDeclaringTypeName() + "_"
+ joinpoint.getSignature().getName() + " with "
+ arrayToString(joinpoint.getArgs()));
Object result = joinpoint.proceed();
long diff = System.currentTimeMillis() - start;
System.out.println("method ends...."
+ joinpoint.getSignature().getDeclaringTypeName() + "_"
+ joinpoint.getSignature().getName() + " with " + diff + "ms");
return result;
} private String arrayToString(Object[] traces) {
StringBuilder trace = new StringBuilder();
for (Object s : traces) {
trace.append(s == null ? "" : s.toString() + "\t");
}
if (trace.length() == 0) {
trace.append("no parameter");
}
return trace.toString();
}

运行输出如下:

method starts....org.zhangfc.demo4ssh.repo.UserDao_findAll with no parameter
method ends....org.zhangfc.demo4ssh.repo.UserDao_findAll with 537ms

3. Log4j

AOP就说到这儿,下面来配置log4j,首先导入log4j的jar包:

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

log4j默认的配置文件需要放在classpath下,而且不能是子目录下,配置文件多了这就非常不方便,如果觉得放在classpath下没有问题,那么把配置文件放过去就可以直接运行了,我现在要改这个配置文件的目录,正好,spring的一个类可以帮我们处理这个事情,不过要在web.xml里面配置一下:

<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:/META-INF/properties/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>

这个配置要放在spring listener的前面,指定配置文件位置并且每60秒重新读取配置文件,这样如果变更了配置也不需要重启应用。配置文件的配置方法我就不详述了,这里贴出来我的配置,我把配置往Console和文件里各输出了一份:

log4j.rootLogger=INFO,CONSOLE,ROLLING_FILE
#INFO,CONSOLE,ROLLING_FILE
#ERROR,ROLLING_FILE ###################
# Console Appender
###################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=INFO
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern= [%p] %d %c - %m%n ########################
# Rolling File
########################
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=INFO
log4j.appender.ROLLING_FILE.File=${webapp.root}/WEB-INF/webapp.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.ROLLING_FILE.MaxFileSize=5000KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=2
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[%p] %d %c - %m%n

输出的格式demo如下:

[INFO] 2014-11-22 11:30:07,944 LogAspect - method ends....org.zhangfc.demo4ssh.repo.UserDao_findAll with 385ms

日志文件按配置放在了项目的WEB-INF下面。

源码下载

【JavaEE】SSH+Spring Security基础上配置AOP+log4j的更多相关文章

  1. 【JavaEE】SSH+Spring Security整合及example

    到前文为止,SSH的基本框架都已经搭建出来了,现在,在这基础上再加上权限控制,也就是Spring Security框架,和前文的顺序一样,先看看需要加哪些库. 1. pom.xml Spring Se ...

  2. Java Web系列:Spring Security 基础

    Spring Security虽然比JAAS进步很大,但还是先天不足,达不到ASP.NET中的认证和授权的方便快捷.这里演示登录.注销.记住我的常规功能,认证上自定义提供程序避免对数据库的依赖,授权上 ...

  3. Spring Security Oauth2 的配置

    使用oauth2保护你的应用,可以分为简易的分为三个步骤 配置资源服务器 配置认证服务器 配置spring security 前两点是oauth2的主体内容,但前面我已经描述过了,spring sec ...

  4. 白话Spring(基础篇)---AOP(execution表达式)

    作为AOP的最后一节内容,我们来简单总结一下切面表达式上见的书写方法.下面的那内容有参考其他博文,在此先对开源博客的各位大神表示感谢! -------------------------------- ...

  5. Spring 框架基础(04):AOP切面编程概念,几种实现方式演示

    本文源码:GitHub·点这里 || GitEE·点这里 一.AOP基础简介 1.切面编程简介 AOP全称:Aspect Oriented Programming,面向切面编程.通过预编译方式和运行期 ...

  6. 白话Spring(基础篇)---AOP(execution表达式)(转)

    [一知半解,就是给自己挖坑] 作为AOP的最后一节内容,我们来简单总结一下切面表达式上见的书写方法.下面的那内容有参考其他博文,在此先对开源博客的各位大神表示感谢! ----------------- ...

  7. CAS Spring Security 3 整合配置(转)

    一般来说, Web 应用的安全性包括用户认证( Authentication )和用户授权( Authorization )两个部分.用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否 ...

  8. Spring Security基于Java配置

    Maven依赖 <dependencies> <!-- ... other dependency elements ... --> <dependency> < ...

  9. spring boot rest 接口集成 spring security(2) - JWT配置

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

随机推荐

  1. CentOS 6.5 Python 2.6.6+Flask 用wsgi方式部署在Apache 2.2.15下

    1,安装wsgi Apache模块 easy_install mod_wsgi 2,添加/etc/httpd/conf.d/wsgi.conf LoadModule wsgi_module modul ...

  2. php读取csv文件,在linux上出现中文读取不到的情况 解决方法

    今,php读取csv文件,在linux上出现中文读取不到的情况,google,后找到解决办法<?phpsetlocale(LC_ALL, 'zh_CN');$row = 1;$handle = ...

  3. Win7“当前用户没有安装Microsoft Office"

    故障:在win7 win10系统已安装office2007~但打开word excel应用程序时提示"当前用户没有安装Microsoft Office". 原因:office200 ...

  4. 使用SharePoint Designer定制开发员工工作日志系统实例!

    昨天已介绍了一篇<使用SharePoint Designer定制开发专家库系统实例!>,今天继续来介绍使用SharePoint Designer定制开发员工工作日志系统实例,主要功能包括填 ...

  5. Xenia and Divisors

    Xenia and Divisors time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  6. [持续更新]UnsatisfiedLinkError常见问题及解决方案

    想必很多开发者和我们一样,遇到过许多UnsatisfiedLinkError的困难,着实令人头疼,现在总结一下,希望能帮助更多的人. 常见错误 lib库不同目录下的SO文件参差不齐. lib库目录下的 ...

  7. Mina、Netty、Twisted一起学(四):定制自己的协议

    在前面的博文中,介绍一些消息分割的方案,以及MINA.Netty.Twisted针对这些方案提供的相关API.例如MINA的TextLineCodecFactory.PrefixedStringCod ...

  8. Mina、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息

    在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息.理想状况是一方每发送一条消息,另一方就立即接收到一条,也就是一次write对应一次rea ...

  9. 【原创】C#搭建足球赛事资料库与预测平台(5) 赔率数据表设计1

            本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html 开源C#彩票数据资料库系列文章总目录:http://www.cn ...

  10. Understanding CMS GC Logs--转载

    原文地址:https://blogs.oracle.com/poonam/entry/understanding_cms_gc_logs Understanding CMS GC Logs By Po ...