前言


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. .Net Core MVC 网站开发(Ninesky) 2.2、栏目管理功能-System区域添加

    在asp或asp.net中为了方便网站的结构清晰,通常把具有类似功能的页面放到一个文件夹中,用户管理功能都放在Admin文件夹下,用户功能都放在Member文件夹下,在MVC中,通常使用区域(Area ...

  2. JavaScript自定义媒体播放器

    使用<audio>和<video>元素的play()和pause()方法,可以手工控制媒体文件的播放.组合使用属性.事件和这两个方法,很容易创建一个自定义的媒体播放器,如下面的 ...

  3. Unity3D框架插件uFrame实践记录(二)

    5.创建属性和命令 本小节主要内容包括: 在Element节点上创建属性数据 在Element节点上创建命令数据 5.1.在Element节点上创建属性数据 在这里,我们首先为Login节点中的属性( ...

  4. 项目持续集成环境(jenkins + SVN + maven + tomcat)

    整体流程 每次SVN上代码有变动,触发自动构建动作,并部署到服务器的tomcat上,具体流程: 1.SVN上提交代码修改 2.maven执行Goals 3.将web工程打成war包 4.关闭服务器的t ...

  5. MongoDB备份(mongodump)和恢复(mongorestore)

    MongoDB提供了备份和恢复的功能,分别是MongoDB下载目录下的mongodump.exe和mongorestore.exe文件 1.备份数据使用下面的命令: >mongodump -h ...

  6. liunx 磁盘管理命令记录

    Linux磁盘管理好坏管理直接关系到整个系统的性能问题. Linux磁盘管理常用三个命令为df.du和fdisk. df:列出文件系统的整体磁盘使用量 du:检查磁盘空间使用量 fdisk:用于磁盘分 ...

  7. Web应用之LAMP源码环境部署

    一.LAMP环境的介绍 1.LAMP环境的重要性 思索许久,最终还是决定写一篇详细的LAMP的源码编译安装的实验文档,一来是为了给自己一个交代,把技术进行系统的归纳,将技术以极致的形式呈现出来,做为一 ...

  8. Merge Sorted Array

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:Yo ...

  9. 个人也能申请微信小程序获得APPID和手机测试效果

    微信小程序昨晚火爆公测,我也第一时间注册了小程序账号开启公测之旅. 注册过程可以看文档:https://my.oschina.net/imhoodoo/blog/780901 进入后台之后我们其实主要 ...

  10. Debian下安装mono

    从mono的官网上查,debian的步骤写得太乱了.其实总结起来,就是这么几步: apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --rec ...