SpringBoot初体验(续)
1.如果你还不知道SpringBoot的厉害之处,或者你不知道SpringBoot的初级用法,请移步我的上一篇文章,传送门
2.SpringBoot中的表单验证
所谓验证,无非就是检验,对比,正如javax.validation.constraints包中的各种注解,从名字上我们可以看出来:
我就用这个包中的Min做例子:
我给我们的数据持久化层Dril类的age属性加上注解@Min
a.Dril.java
//数据持久化 @Entity public class Dril { @Id @GeneratedValue private Integer id; private String name; @Min(value=18,message="未成年!") private Integer age; public Dril() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
b.DrilController.java
@RequestMapping(value="addDril.do",method=RequestMethod.POST) public Dril getDrilName(@Valid Dril dril,BindingResult bindingResult){ if (bindingResult.hasErrors()) { logger.info(bindingResult.getFieldError().getDefaultMessage()); return null; } return drilService2.addDril(dril);
c.运行结果
当我们插入age小于18的数据的时候出现
console输出:
如果我们输入的对象年龄大于18的话出现
其他方法自行测试。
2.AOP统一处理请求日志
a.简单介绍AOP
面向对象将对象垂直划分,并且每个都有自己的方法,AOP将面向对象的庞大体系进行水平分割,并将影响到多个类的公共行为做成可重用的模块。正如AOP的核心思想,将通用逻辑从业务逻辑分离出来。
b.AOP的运用场景
权限控制,缓存控制,事务控制,审计日志,性能监控,分布式追踪,异常处理
b.使用Aspectj注解
@Aspect:用于声明当前类是一个切面
@Pointcut:用于描述在哪些类、哪些方法上执行切面的代码
Advice:描述想要在这些方法执行的什么时机进行拦截
在介绍5种Advice之前,我先说说切面表达式
c.切面表达式
1.designators(指示器)
描述通过什么样的方式去匹配哪些类、哪些方法。如匹配方法 execution(),匹配注解 @target() @args() @within() @annotation(),匹配包/类型 @within(),匹配对象 this() bean()target(),匹配参数 args()。
2.wildcards(通配符)
* .. +
使用通配符进行描述,如* 匹配任意数量的字符 ,+ 匹配指定类及其子类, .. 一般用于匹配任意参数的子包或参数
3.operators(运算符)
&& || !
使用运算符进行多条件的判断,如&& 与操作符, || 或操作符 ,! 非操作符
d.5种advice1.匹配包类
// 匹配 ProductServiceAop 类里面的所有方法 @Pointcut("within(com.myimooc.springaopguide.service.ProductServiceAop)") public void matchType(){ } // 匹配 com.myimooc.springaopguide.service 包及子包下所有类的方法 @Pointcut("within(com.myimooc.springaopguide.service..*)") public void matchPackage(){ }
2.匹配对象
// 匹配AOP对象的目标对象为指定类型的方法,即DemoDao的aop代理对象的方法 @Pointcut("this(com.myimooc.springaopguide.dao.DemoDao)") public void testDemo() { } // 匹配实现IDao接口的目标对象(而不是aop代理后的对象)的方法,这里即DemoDao的方法 @Pointcut("target(com.myimooc.springaopguide.dao.IDao)") public void targetDemo() { } // 匹配所有以Service结尾的bean里面的方法 @Pointcut("bean(*Service)") public void beanDemo() { }
3.匹配参数
// 匹配任何以find开头而且只有一个Long参数的方法 @Pointcut("execution(* *..find*(Long))") public void argsDemo1(){} // 匹配任何只有一个Long参数的方法 @Pointcut("args(Long)") public void argsDemo2(){} // 匹配任何以find开头而且第一个参数为Long型的方法 @Pointcut("execution(* *..find*(Long,..))") public void argsDemo3(){} // 匹配第一个参数为Long型的方法 @Pointcut("args(Long,..))") public void argsDemo4(){}
4.匹配注解
// 匹配方法标注有AdminOnly的注解的方法 @Pointcut("@annotation(com.myimooc.springaopguide.security.AdminOnly)") public void annoDemo(){ } // 匹配标注有Beta的类底下的方法,要求的annotation的RetentionPolicy级别为CLASS @Pointcut("@within(com.google.common.annotations.Beta)") public void annoWithDemo(){ } // 匹配标注有Repository的类底下的方法,要求的RetentionPolicy级别为RUNTIME @Pointcut("@target(org.springframework.stereotype.Repository)") public void annoTargetDemo(){ } // 匹配传入的参数类标注有Repository注解的方法 @Pointcut("@args(org.springframework.stereotype.Repository)") public void annoArgsDemo(){ }
5.匹配方法
execution()格式
execution( modifier-pattern? // 修饰符匹配 ret-type-pattern // 返回值匹配 declaring-type-pattern? // 描述值包名 name-pattern(param-pattern) // 方法名匹配(参数匹配) throws-pattern?// 抛出异常匹配 )
实例:
/** * 切点 * 使用public修饰符匹配,任意返回值,在com.huhu.controller包下以Controller结尾的类名下的getDrils()方法 */ @Pointcut("execution(public * com.huhu.controller..*Controller.getDrils(..))") public void Log() { }
e.AOP所需要的注解
@Before,前置通知
@After(finally)后置通知,方法执行完之后
@AfterReturning,返回通知,成功执行之后
@AfterThrowing,异常通知,抛出异常之后
@Around,环绕通知
f.请开始我们的表演
代码接着上篇的代码,我们给在controller运行前输出访问的URL,METHOD,IP,类方法以及参数
HttpAspect.java
@Aspect @Component public class HttpAspect { Logger logger=LoggerFactory.getLogger(HttpAspect.class); /** * 切点 * 使用public修饰符匹配,任意返回值,在com.huhu.controller包下以Controller结尾的类名下的getDrils()方法 */ @Pointcut("execution(public * com.huhu.controller..*Controller.getDrils(..))") public void Log() { } /** * 用于匹配方法执行的连接点 * @param joinpoint(为org.aspectj.lang.JoinPoint的对象) */ @Before("Log()") public void before(JoinPoint joinpoint) { logger.info("AOP的before()方法"); ServletRequestAttributes attributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //url logger.info("url={}",request.getRequestURL()); //method logger.info("method={}",request.getMethod()); //ip logger.info("ip={}",request.getRemoteAddr()); //类方法 logger.info("class_method= {}",joinpoint.getSignature().getDeclaringTypeName()+"."+joinpoint.getSignature().getName()); //参数 logger.info("args={}",joinpoint.getArgs()); } @After("Log()") public void after() { logger.info("AOP的after()方法"); } }
为了知道是运行controller前输出的,我们给controller加上
@RequestMapping(value="getDrils",method=RequestMethod.GET) public List<Dril> getDrils(){ logger.info("getDrils"); List<Dril> drils =drilService.findAll(); return drils; }
运行结果:
结果向我们展示了使用AOP的结果,所以AOP显然能做权限控制,缓存控制,事务控制,审计日志,性能监控,分布式追踪,异常处理这些事了。
参考资料:
慕课网--Spring Boot进阶之Web进阶