前言


AOP在大多数的情况下的应用场景是:日志和验证。至于AOP的理论知识我就不做赘述。而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示。

一、AOP入门


修改“pom.xml”文件

<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>com.github.carter659</groupId>
<artifactId>spring07</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent> <name>spring07</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

pom.xml

修改入口类文件“App.java”:

package com.github.carter659.spring07;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class App { public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}

App.java

控制器MainController:

package com.github.carter659.spring07;

import java.util.HashMap;
import java.util.Map; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody; @Controller
public class MainController { @GetMapping("/")
public String index() {
return "index";
} @PostMapping("/save")
public @ResponseBody Map<String, Object> save() {
Map<String, Object> map = new HashMap<>();
map.put("msg", "ok");
return map;
}
}

我们拦截控制器中的返回Map的方法。

新建切面类文件“AopAspect.java”:

package com.github.carter659.spring07;

import java.util.HashMap;
import java.util.Map; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component; @Component
@Aspect
public class AopAspect { @Around("execution (java.util.Map com.github.carter659.spring07.MainController.*( .. ) ) ")
public Object invoke(ProceedingJoinPoint point) {
Map<String, Object> map = null;
try {
Object[] args = point.getArgs();
Object val = point.proceed(args);
map = (Map<String, Object>) val;
} catch (Throwable e) {
e.printStackTrace();
map = new HashMap<>();
map.put("msg", e.toString());
}
map.put("aop", "拦截了一个请求");
return map;
}
}

如果能拦截到MainController中的方法,则会在Map中put一对键值。

templates模板:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>玩转spring boot——结合AOP</title>
<script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
<script type="text/javascript">
/*<![CDATA[*/
var app = angular.module('app', []);
app.controller('MainController', function($rootScope, $scope, $http) {
//保存
$scope.save = function() {
$http({
url : '/save',
method : 'POST'
}).success(function(r) {
$scope.result = JSON.stringify(r)
});
} }); /*]]>*/
</script>
</head>
<body ng-app="app" ng-controller="MainController">
<h1>玩转spring boot——结合AOP</h1>
<h4>
<a href="http://www.cnblogs.com/GoodHelper/">from 刘冬的博客</a>
</h4>
<input type="button" value="调用" ng-click="save()" />
<br />
<h3>调用结果:</h3>
<p>{{result}}</p> <br />
<a href="http://www.cnblogs.com/GoodHelper/">点击访问原版博客</a>
</body>
</html>

index.html

运行效果:

点击调用按钮后:

二、表单验证


  由于有了一节的AOP拦截,那么表单验证就完全可以实现了。但是,spring boot给我们提供了原生的表单验证实例。一些简单的验证,我建议实现spring boot自带的验证,因为它足够简单好用,而复杂的验证可以用AOP来实现。

参考:参考:https://spring.io/guides/gs/validating-form-input/

控制器:

package com.github.carter659.spring07;

import java.util.HashMap;
import java.util.Map; import javax.validation.Valid; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody; /**
* 博客出处:http://www.cnblogs.com/GoodHelper/
*
* @author 刘冬
*
*/
@Controller
public class MainController { @GetMapping("/")
public String index() {
return "index";
} @PostMapping("/save")
public @ResponseBody Map<String, Object> save() {
Map<String, Object> map = new HashMap<>();
map.put("msg", "ok");
return map;
} @PostMapping("/saveOrder")
public @ResponseBody Map<String, Object> saveOrder(@RequestBody @Valid Order order) {
Map<String, Object> map = new HashMap<>();
map.put("msg", "ok");
map.put("order", order);
return map;
}
}

MainController.java

在要验证的方法的参数中增加@Valid注解。

修改Order类:

package com.github.carter659.spring07;

import java.util.Date;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; /**
* 博客出处:http://www.cnblogs.com/GoodHelper/
*
* @author 刘冬
*
*/
public class Order { public String id; @NotNull
@Size(min = 10, max = 20)
public String no; @NotNull
public Date date; @Min(100)
@NotNull
public Integer quantity; /**
* 省略 get set
*/
}

增加这javax.validation.constraints包下的验证注解。

修改index.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>玩转spring boot——结合AOP与表单验证</title>
<script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
<script type="text/javascript">
/*<![CDATA[*/
var app = angular.module('app', []);
app.controller('MainController', function($rootScope, $scope, $http) { $scope.data = {
no : 'no.1234567890',
date : '2017-01-01',
quantity : 100
}; $scope.errors = {
no : '',
date : '',
quantity : ''
}; //保存
$scope.save = function() {
$http({
url : '/save',
method : 'POST'
}).success(function(r) {
$scope.result = JSON.stringify(r)
});
}
$scope.saveOrder = function() {
$http({
url : '/saveOrder',
method : 'POST',
data : $scope.data
}).success(function(r) {
$scope.result = JSON.stringify(r)
}).error(function(e) {
$scope.result = JSON.stringify(e)
$scope.errors.no = '';
$scope.errors.date = '';
$scope.errors.quantity = '';
for ( var i in e.errors) {
var error = e.errors[i];
var field = $scope.errors[error.field];
if (field == undefined)
continue;
$scope.errors[error.field] = error.defaultMessage;
}
})
}
}); /*]]>*/
</script>
</head>
<body ng-app="app" ng-controller="MainController">
<h1>玩转spring boot——结合AOP与表单验证</h1>
<h4>
<a href="http://www.cnblogs.com/GoodHelper/">from 刘冬的博客</a>
</h4>
<input type="button" value="调用" ng-click="save()" />
<br />
<br />
<input type="button" value="保存订单" ng-click="saveOrder()" />
<br /> 订单信息:
<br />
<table cellspacing="1" style="background-color: #a0c6e5">
<tr>
<td>编号:</td>
<td><input ng-model="data.no" /></td>
<td><font color="red" ng-show="errors.no">{{errors.no}}</font></td>
</tr>
<tr>
<td>日期:</td>
<td><input ng-model="data.date" /></td>
<td><font color="red" ng-show="errors.date">{{errors.date}}</font></td>
</tr>
<tr>
<td>数量:</td>
<td><input ng-model="data.quantity" /></td>
<td><font color="red" ng-show="errors.quantity">{{errors.quantity}}</font></td>
</tr>
</table>
<br />
<h3>调用结果:</h3>
<p>{{result}}</p> <br />
<a href="http://www.cnblogs.com/GoodHelper/">点击访问原版博客</a>
</body>
</html>

index.html

运行效果:

点击“保存订单”按钮:

如果提交的数据未通过验证,会返回400的http请求结果,并会回到AngularJs的http请求的error方法。

我们再对error方法的参数处理,就能实现客户端验证提示。

当表单填写正确后,我们提交请求:

  代码下载:https://github.com/carter659/spring-boot-07.git

如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。

有可能就是你的一点打赏会让我的博客写的更好:)

玩转spring boot系列目录

玩转spring boot——AOP与表单验证的更多相关文章

  1. spring mvc:练习:表单验证(javaConfig配置和注解)

    使用Spring表单标签, 表单验证使用 JSR303 的验证注解,hibernate-validators,提供了使用MessageSource和访问静态资源(如CSS,JavaScript,图片) ...

  2. Spring Boot (一) 校验表单重复提交

    一.前言 在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据. 存在如上问题可以交给前端解决,判断多长时间内不能再次点 ...

  3. 玩转spring boot——开篇

    很久没写博客了,而这一转眼就是7年.这段时间并不是我没学习东西,而是园友们的技术提高的非常快,这反而让我不知道该写些什么.我做程序已经有十几年之久了,可以说是彻彻底底的“程序老炮”,至于技术怎么样?我 ...

  4. Spring Boot 表单验证、AOP统一处理请求日志、单元测试

    一.使用@Valid表单验证 于实体类中添加@Min等注解 @Entity public class Girl { @Id @GeneratedValue private Integer id; pr ...

  5. Spring Boot学习——表单验证

    我觉得表单验证主要是用来防范小白搞乱网站和一些低级的黑客技术.Spring Boot可以使用注解 @Valid 进行表单验证.下面是一个例子. 例子说明:数据库增加一条Student记录,要求学生年龄 ...

  6. Spring Boot 2 + Thymeleaf:服务器端表单验证

    表单验证分为前端验证和服务器端验证.服务器端验证方面,Java提供了主要用于数据验证的JSR 303规范,而Hibernate Validator实现了JSR 303规范.项目依赖加入spring-b ...

  7. Spring Boot笔记八:表单验证

    所谓的表单验证,就是为了防止用户乱输入的,这个问题前端的HTML5就可以判断了,其实不需要后端来验证,这里还是讲一下后端验证 首先,我们的Person类,我们加上一些表单验证的注释,如下: packa ...

  8. spring boot学习(7) SpringBoot 之表单验证

    第一节:SpringBoot 之表单验证@Valid 是spring-data-jpa的功能:   下面是添加学生的信息例子,要求姓名不能为空,年龄大于18岁.   贴下代码吧: Student实体: ...

  9. 玩转spring boot——结合AngularJs和JDBC

    参考官方例子:http://spring.io/guides/gs/relational-data-access/ 一.项目准备 在建立mysql数据库后新建表“t_order” ; -- ----- ...

随机推荐

  1. 故障重现, JAVA进程内存不够时突然挂掉模拟

    背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...

  2. 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)

    分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...

  3. ASP.NET MVC 请求路径相关参数的获取

    Request.ApplicationPath / Request.CurrentExecutionFilePath /Home/Index Request.FilePath /Home/Index ...

  4. “.Net 社区虚拟大会”(dotnetConf) 2016 Day 3 Keynote: Scott Hanselman

    美国时间 6月7日--9日,为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开,美国时间6.9 是第三天, Scott Hanselman 做Keynote.今天主题围绕的是.NET ...

  5. DDD CQRS架构和传统架构的优缺点比较

    明天就是大年三十了,今天在家有空,想集中整理一下CQRS架构的特点以及相比传统架构的优缺点分析.先提前祝大家猴年新春快乐.万事如意.身体健康! 最近几年,在DDD的领域,我们经常会看到CQRS架构的概 ...

  6. ExtJS 4.2 组件介绍

    目录 1. 介绍 1.1 说明 1.2 组件分类 1.3 组件名称 1.4 组件结构 2. 组件的创建方式 2.1 Ext.create()创建 2.2 xtype创建 1. 介绍 1.1 说明 Ex ...

  7. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

  8. js报错: Uncaught RangeError: Invalid string length

    在ajax请求后得到的json数据,遍历的时候chrome控制台报这个错误:Uncaught RangeError: Invalid string length,在stackoverflow查找答案时 ...

  9. The Zen of Python

    Beautiful is better than ugly. 优美总比丑陋好Explicit is better than implicit. 直率总比含蓄好Simple is better than ...

  10. JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象

    一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...