Shepard's Blog

Nothing is true everything is permitted


  • 首页

  • 标签

  • 分类

  • 归档

  • 公益404

  • 搜索

Windows系统下的部分解决办法

发表于 2016-01-13 | 分类于 其他 |

Windows 7 修改登录界面

WIN7登陆界面怎么修改

按快捷键Win+R或者打开开始菜单,点击运行,然后输入cmd开启命令行工具。接着在命令行工具输入regedit开启注册表编辑器。按以下路径点开:

1
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background

然后在注册表编辑器右边的面板中找到键OEMBackground,没有可以新建一个。
将值改成1,保存。
打开C:\Windows\System32\oobe\info\backgrounds文件夹,没有对应的文件夹就新建。
然后准备一张与当前分辨率一致的图片,命名为backgroundDefault.jpg,图片大小最好保持在250KB以下。
按Win+L查看效果。

阅读全文 »

Office组件小技巧

发表于 2016-01-13 | 分类于 其他 |

word 2010 自定义页码起始页

Word 2010 中自定义页码起始页

从第二页开始编号

  1. 双击页码以打开页眉和页脚工具->设计选项卡
  2. 选中设计->选项->首页不同复选框
  3. 若要从1开始编号,单击页眉和页脚->页码->设置页码格式->起始编号,输入1。
  4. 若要返回至文档正文,单击页眉和页脚工具->设计->关闭页眉和页脚。

在其他页面上开始编号

  1. 单击要开始编号的页面的开头; 按Home键可确保光标位于页面开头。
  2. 单击页面布局->页面设置->分隔符,在分节符下,单击下一页。
  3. 双击页码以打开页眉和页脚工具->设计选项卡
  4. 单击页眉和页脚工具->导航->链接到前一节以禁用它。
  5. 若要从1开始编号,单击页眉和页脚->页码->设置页码格式->起始编号,输入1。
  6. 若要返回至文档正文,单击页眉和页脚工具->设计->关闭页眉和页脚。

word 2010 取消拼写检查

word2010 取消拼写检查

审阅->拼写和语法->全部忽略
或者
文件->选项->校对->在word中更正拼写和语法时,取消选中键入时拼写检查。


去掉word里面的超链接

怎么去掉WORD文档里的所有超链接?

快捷键方法:Ctrl+A全选之后再按Ctrl+Shift+F9


outlook2003取消记住密码

在控制面板->用户账户->凭据管理器->管理Windows凭据中,删除相关的存储凭据即可。或者按win+r弹出运行对话框,接着输入control keymgr.dll可以直达凭据管理器

Laravel部分知识点收集

发表于 2016-01-12 | 分类于 PHP |

Laravel开启内置服务

Running PHP’s Built-in Web Server

Laravel内置了一个Web服务器,当需要调试或者查看效果时,可以直接使用命令开启服务:

1
php artisan serve

默认端口为8000,也可以指定端口:

1
php artisan serve --port=8888


Laravel更改时区

Timezones in Laravel 4

在Laravel项目的congfig文件夹下有个配置文件为app.php,找到配置项timezone,默认为UTC,改成PRC即为北京时间


Laravel中间件

HTTP 中间件
Laravel 权限控制整理–中间件

生成中间件

使用下列命令创建一个新的中间件:

1
php artisan make:middleware LoginMiddleware

在项目文件夹下的app/Http/Middleware中可以看到新建的中间件,在这个中间件中,指定如果登陆了的用户才能通过验证,反之则跳转到登陆页面,如果进入了不该进入的页面,则跳转到主页面:

阅读全文 »

PHP配置相关知识点收集

发表于 2016-01-12 | 分类于 PHP |

Windows下安装Composer

windows下安装php依赖关系管理工具composer
windows下安装composer方法
解决Win7下运行php Composer出现SSL报错的问题
How to install Symfony 2.7

Composer是PHP的一个依赖管理工具。
要安装Composer首先需要开启php_openssl.dll扩展;开启的方法则是在php.ini配置文件中将extension = php_openssl.dll这一行前面的分号去掉。
命令行cd到放置Composer文件夹下,使用下列命令:

1
php -r "readfile('https://getcomposer.org/installer');" | php

或者可以直接下载Composer文件
这里已经完成了Composer的下载工作,可以使用命令php composer.phar -V来查看Composer的版本。当然这也稍显麻烦,因此可以在composer.phar文件同级目录下新建一名为composer.bat的文件,然后输入下列命令:

1
echo @php "%~dp0composer.phar" %*>composer.bat

保存之后即可使用composer -V来查看当前composer的版本了。
如果想要全局使用,可以将它添加到系统变量PATH中。
接下来就可以使用composer create-project命令来新建项目,如:

1
2
composer create-project larave/laravel project_name
composer create-project symfony/framework-standard-edition project_name

注意:如果运行composer出现了SSL错误,有一种可能是没有安装CA证书导致的。首先需要下载证书,然后再修改php.ini文件即可

1
openssl.cafile= X:/存放证书的路径/cacert.pem


Windows下配置Nginx与PHP的开发环境

转载:配置Windows下Nginx + PHP 开发环境
Windows下配置nginx+php(wnmp)
windows安装nginx跑php 再加上Laravel

PHP部分配置

修改php.ini-development文件:

  • 将extension_dir前面的分号去掉,并将值改为php文件夹内ext文件夹的路径,如extension_dir = "C:/mine/php/ext"
  • 将enable_dl前面的分号去掉,并将值改为On,如enable_dl = On
  • 将cgi.force_redirect前面的分号去掉,并将值改为0,如cgi.force_redirect = 0
  • 将fastcgi.impersonate前面的分号去掉
  • 将cgi.rfc2616_headers前面的分号去掉,并将值改为1,如cgi.rfc2616_headers = 1
  • 将date.timezone前面的分号去掉,并将值改成Asia/Shanghai,如date.timezone = Asia/Shanghai
  • 将extension=php_mysql.dll,extension=php_mysqli.dll,extension=php_pdo_mysql.dll前面的分号去掉,以支持MySQL数据库(可选)
  • 将extension=php_curl.dll前面的分号去掉,以开启curl扩展(可选)
  • 将extension=php_openssl.dll前面的分号去掉,以下载composer(可选)

修改完毕后另存为php.ini文件至php根目录下。


Nginx部分配置

修改nginx的配置文件nginx.conf,以支持PHP:

1
2
3
4
5
6
7
location ~ \.php$ {
root C:/workspace/php/laraveltest2/public;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

添加一个新的路径:

1
2
3
4
5
location / {
root C:/workspace/php/laravelyh/public;
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?$query_string;
}


运行

在命令行输入命令

1
C:/mine/php/php-cgi.exe -b 127.0.0.1:9000 -c C:/mine/php/php.ini

然后再另开一个命令行窗口,定位到nginx目录下,启动nginx服务

1
start nginx

接着在浏览器输入http://localhost查看效果

php基本知识整理

发表于 2016-01-11 | 分类于 PHP |

发送HTTP请求

通过http post发送json数据
PHP扩展CURL的用法详解
PHP中使用cURL实现Get和Post请求的方法
php发送http请求
PHP curl CURLOPT_RETURNTRANSFER参数的作用使用实例
PHP中CURL方法curl_setopt()函数的参数

PHP中发送HTTP请求可以使用curl或者file_get_contents()方法,curl使用前需要在php.ini中将extension=php_curl.dll前面的分号去掉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php

$url = 'http://localhost:5000/hello';
$data = json_encode(array('name'=>'tom'));

printf("test1=>");
function sendData1($url, $data) {
//初始化curl
$ch = curl_init();
//请求的url
curl_setopt($ch, CURLOPT_URL, $url);
//结果是否直接输出,1为保存到变量不输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//设置请求头
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($data)
));
//设置请求方式为post
curl_setopt($ch, CURLOPT_POST, 1);
//设置post的数据
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
//运行curl,得到返回结果
$result = curl_exec($ch);
//关闭curl连接
curl_close($ch);

return $result;
}
//json_decode的第二个参数为true时,返回的对象为array而不是object,默认为false
var_dump(json_decode(sendData1($url, $data), true));

print_r("test2=>");
function sendData2($url, $data) {
$options = [
'http'=>[
'method'=>'POST',
//设定类型为json类型
'header'=>'Content-Type: application/json',
'content'=>$data,
//超时时间
'timeout'=>15*60
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
var_dump(json_decode(sendData2($url, $data)));
?>

通过命令行运行命令php filename.php即可
响应的服务端为Python的Flask实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/')
def index():
return 'Hello World!'

@app.route('/hello', methods=['POST'])
def hello():
name = request.json['name'] if request.json['name'] else ''
return jsonify({'message': 'Hello '+name})

if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True)


去除Object中的部分属性

Is it possible to delete an object’s property in PHP?

使用unset()方法即可去除指定Ojbect中的指定属性

1
2
3
4
5
6
7
$a = new stdClass();

$a->new_property = 'foo';
var_export($a); // -> stdClass::__set_state(array('new_property' => 'foo'))

unset($a->new_property);
var_export($a); // -> stdClass::__set_state(array())


闭包

匿名函数
Closure 类
PHP的闭包
PHP中的闭包详解
条件组合查询问题
Eloquent ORM关于拆分查询chunk

闭包即为匿名函数。创建一个没有名称的函数,使用use关键字来连接闭包与外界的变量,使子函数可以使用父函数的局部变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$num = 1;
function test1($num) {
$result = 1;
$a = function() use ($num, &$result){
$result += $num;
print("result in a: ".$result."\n");
};
$a();
print($result);
print("\n");
//不加&则不会影响父函数的局部变量
$b = function() use ($num, $result) {
$result -= $num;
print("result in b: ".$result."\n");
};
$b();
print($result);
}

test1($num);

Flask页面相关知识

发表于 2016-01-11 | 分类于 Python |

更改jinja2模板的默认修饰符

different delimiters in jinja2 + flask

在Flask中的jinja2模板中输出值的修饰符号与AngularJs中的修饰符一样,为了解决冲突,可以自定义默认模板的修饰符:

1
2
3
4
5
6
7
8
9
10
11
12
13
class CustomFlask(Flask):
jinja_options = Flask.jinja_options.copy()
jinja_options.update(dict(
block_start_string='<%',
block_end_string='%>',
variable_start_string='%%', #替换{{
variable_end_string='%%', #替换}}
comment_start_string='<#',
comment_end_string='#>',
))

//默认写法app = Flask(__name__)这里使用了上面自定义的类
app = CustomFlask(__name__)

这样输出值的修饰符就变成了%%,避开了与AngularJS的输出修饰符冲突。


输出静态文件

python flask - serving static files

1
2
3
4
5
from flask import url_for, redirect

@app.route('/')
def home():
return redirect(url_for('static', filename='index.html'))

使用Cocoapods来进行项目依赖管理

发表于 2015-10-26 | 分类于 iOS |

安装

在安装之前,先做一些准备工作。首先需要替换掉Ruby的默认源:

1
2
gem sources -a https://ruby.taobao.org/
gem sources --remove https://rubygems.org/

更新: 现在淘宝的ruby镜像不再维护了,现在应该替换成gem sources -a https://gems.ruby-china.org/

然后可以输入命令gem sources -l验证是否替换成功。
若是gem版本低,可以使用update命令更新:

1
sudo gem update -n /usr/local/bin --system

接下来则是安装Cocoapods:

1
sudo gem install -n /usr/local/bin cocoapods

使用

可以使用search命令搜寻需要的第三方库:

1
pod search 第三方库名称

在已经建立好的Xcode项目中加入Podfile文件,或者在终端中cd到项目路径中,然后运行touch命令建立该文件

1
touch Podfile

然后编辑Podfile文件

1
2
3
4
platform :ios, '9.0' #支持的系统版本
target 'MyApp' do
pod 'AFNetworking', '~> 3.0'
end

编辑完保存之后在终端运行命令

1
pod install

如果是第一次运行pod install命令的话,默认会执行pod setup来更新源。这一步会从github上边下载,如果连接经常断掉的话,可以按以下步骤解决:

  1. 首先通过浏览器下载压缩包,默认解压后的路径是~/Download/Spec-master。
  2. 然后在终端中运行git clone https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master命令,等其开始运行。
  3. 再开一个终端,运行cp -r ~/.cocoapods/repos/master/.git ~/Download/Spec-master/,成功后将上边的下载动作终止。
  4. 运行命令mv ~/Download/Spec-master ~/.cocoapods/repos/master转移目录。
  5. cd到Pod项目目录中执行pod install --no-repo-update命令。

待其构建好项目之后打开MyApp.xcworkspace文件即可。

如果出现了引入的依赖无法找到的问题(Could not build module ‘…’),可以尝试以下步骤解决:

  1. 关闭Xcode。
  2. 运行命令rm -rf ~/Library/Developer/Xcode/DerivedData删除项目临时文件。
  3. 删除项目根目录下的*.xcworkspace、Podfile.lock文件,还有Pods文件夹。
  4. 重新运行Pod install命令,待其完成之后再通过*.xcworkspace打开项目。

可以参考stackoverflow上的答案。


卸载Cocoapods

首先使用命令查找pod的安装路径

1
which pod

然后删除这它:

1
sudo rm -rf /usr/local/bin/pod

这里的路径则是通过which命令找出来的。然后通过gem list命令来查找gem中的Cocoapods包

1
gem list

接下来将所有与Cocoapods有关的包移除掉

1
sudo gem uninstall cocoapods

如果有多个版本同时存在,终端会提示需要删除哪一个版本,按对应的数字即可。
这样Cocoapods就算是成功卸载了。


参考
CocoaPods详解之—-使用篇
用CocoaPods做iOS程序的依赖管理
CocoaPods 安装 使用
CocoaPods报错:The dependency AFNetworking is not used in any concrete target
如何从电脑中卸载cocoapods

Spring AOP相关知识点收集

发表于 2015-05-16 | 分类于 Java , Spring |

Spring 之AOP AspectJ切入点语法详解)
使用Spring进行面向切面编程
aop:aspectj-autoproxy的内部机制
使用Spring的注解方式实现AOP
Spring AOP 完成日志记录

语法

Spring AOP支持的AspectJ切入点指示符

切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下:

  • execution:用于匹配方法执行的连接点;
  • within:用于匹配指定类型内的方法执行;
  • this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
  • target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
  • args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
  • @within:用于匹配所以持有指定注解类型内的方法;
  • @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
  • @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
  • @annotation:用于匹配当前执行方法持有指定注解的方法;
  • bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;
  • reference pointcut:表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。

类型匹配语法

*:匹配任何数量字符;
..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
+:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。

1
2
3
4
5
6
7
8
java.lang.String    //匹配String类型;  
java.*.String //匹配java包下的任何“一级子包”下的String类型;
//如匹配java.lang.String,但不匹配java.lang.ss.String
java..* //匹配java包及任何子包下的任何类型;
//如匹配java.lang.String、java.lang.annotation.Annotation
java.lang.*ing //匹配任何java.lang包下的以ing结尾的类型;
java.lang.Number+ //匹配java.lang包下的任何Number的自类型;
//如匹配java.lang.Integer,也匹配java.math.BigInteger

匹配类型:使用如下方式匹配

1
注解? 类的全限定名字

  • 注解:可选,类型上持有的注解,如@Deprecated;
  • 类的全限定名:必填,可以是任何类全限定名。

匹配方法执行:使用如下方式匹配

1
注解? 修饰符? 返回值类型 类型声明?方法名(参数列表) 异常列表?

  • 注解:可选,方法上持有的注解,如@Deprecated;
  • 修饰符:可选,如public、protected;
  • 返回值类型:必填,可以是任何类型模式;“*”表示所有类型;
  • 类型声明:可选,可以是任何类型模式;
  • 方法名:必填,可以使用“*”进行模式匹配;
  • 参数列表:“()”表示方法没有任何参数;“(..)”表示匹配接受任意个参数的方法,“(..,java.lang.String)”表示匹配接受java.lang.String类型的参数结束,且其前边可以接受有任意个参数的方法;“(java.lang.String,..)” 表示匹配接受java.lang.String类型的参数开始,且其后边可以接受任意个参数的方法;“(*,java.lang.String)” 表示匹配接受java.lang.String类型的参数结束,且其前边接受有一个任意类型参数的方法;
  • 异常列表:可选,以“throws 异常全限定名列表”声明,异常全限定名列表如有多个以“,”分割,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException。

组合切入点表达式

AspectJ使用 且(&&)、或(||)、非(!)来组合切入点表达式。
在Schema风格下,由于在XML中使用“&&”需要使用转义字符&amp;&amp;来代替之,所以很不方便,因此Spring ASP 提供了and、or、not来代替&&、||、!。


切入点使用示例

execution

使用“execution(方法表达式)”匹配方法执行-

模式 描述
public * *(..) 任何公共方法的执行
* cn.javass..*.*(..) cn.javass包及所有子包下任何类的任何方法
* (!cn.javass..IPointcutService+).*(..) 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法
`@java.lang.Deprecated (..)` 任何持有@java.lang.Deprecated注解的方法
within

使用“within(类型表达式)”匹配指定类型内的方法执行;

模式 描述
within(cn.javass..*) cn.javass包及子包下的任何方法执行
within(cn.javass..IPointcutService+) cn.javass包或所有子包下IPointcutService类型及子类型的任何方法
within(@cn.javass..Secure *) 持有cn.javass..Secure注解的任何类型的任何方法.必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
this

使用“this(类型全限定名)”匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口方法也可以匹配;注意this中使用的表达式必须是类型全限定名,不支持通配符

模式 描述
this(cn.spring.service.IPointcutService) 当前AOP对象实现了 IPointcutService接口的任何方法
this(cn.spring.service.IIntroductionService) 当前AOP对象实现了 IIntroductionService接口的任何方法也可能是引入接口
target

使用“target(类型全限定名)”匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是类型全限定名,不支持通配符

模式 描述
target(cn.spring.service.IPointcutService) 当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法
target(cn.spring.service.IIntroductionService) 当前AOP对象实现了 IIntroductionService接口的任何方法也可能是引入接口
args

使用“args(参数类型列表)”匹配当前执行的方法传入的参数为指定类型的执行方法;注意是匹配传入的参数类型,不是匹配方法签名的参数类型;参数类型列表中的参数必须是类型全限定名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用

模式 描述
args (java.io.Serializable,..) 任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的
@within

使用“@within(注解类型)”匹配所以持有指定注解类型内的方法;注解类型也必须是全限定类型名

模式 描述
@within cn.spring.Secure) 任何目标对象对应的类型持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
@target

使用“@target(注解类型)”匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是全限定类型名

模式 描述
@target(cn.spring.Secure) 任何目标对象持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
@args

使用“@args(注解列表)”匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是全限定类型名

模式 描述
@args (cn.spring.Secure) 任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.spring.Secure;动态切入点,类似于arg指示符;
@annotation

使用“@annotation(注解类型)”匹配当前执行方法持有指定注解的方法;注解类型也必须是全限定类型名

模式 描述
@annotation(cn.spring.Secure ) 当前执行方法上持有注解 cn.spring.Secure将被匹配
bean

使用“bean(Bean id或名字通配符)”匹配特定名称的Bean对象的执行方法;Spring ASP扩展的,在AspectJ中无相应概念

模式 描述
bean(*Service) 匹配所有以Service命名(id或name)结尾的Bean

通知参数

  • 使用JoinPoint获取:Spring AOP提供使用org.aspectj.lang.JoinPoint类型获取连接点数据,任何通知方法的第一个参数都可以是JoinPoint(环绕通知是ProceedingJoinPoint,JoinPoint子类),当然第一个参数位置也可以是JoinPoint.StaticPart类型,这个只返回连接点的静态部分。

1) JoinPoint:提供访问当前被通知方法的目标对象、代理对象、方法参数等数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package org.aspectj.lang;  
import org.aspectj.lang.reflect.SourceLocation;
public interface JoinPoint {
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
Object getThis(); //返回AOP代理对象
Object getTarget(); //返回目标对象
Object[] getArgs(); //返回被通知方法参数列表
Signature getSignature(); //返回当前连接点签名
SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
String getKind(); //连接点类型
StaticPart getStaticPart(); //返回连接点静态部分
}

2)ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法

1
2
3
4
public interface ProceedingJoinPoint extends JoinPoint {  
public Object proceed() throws Throwable;
public Object proceed(Object[] args) throws Throwable;
}

3) JoinPoint.StaticPart:提供访问连接点的静态部分,如被通知方法签名、连接点类型等

1
2
3
4
5
6
7
8
public interface StaticPart {  
Signature getSignature(); //返回当前连接点签名
String getKind(); //连接点类型
int getId(); //唯一标识
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
}


实例

build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apply plugin: 'java'
apply plugin: 'eclipse'

repositories {
maven {
url "http://repo.spring.io/libs-release"
url "http://maven.oschina.net/content/groups/public/"
}
mavenCentral()
}

dependencies {
compile(
[group: 'org.springframework', name: 'spring-aop', version: '4.1.5.RELEASE'],
[group: 'org.springframework', name: 'spring-aspects', version: '4.1.5.RELEASE'],
[group: 'org.springframework', name: 'spring-context-support', version: '4.1.5.RELEASE']
)
}

service类

1
2
3
4
5
6
7
8
9
10
public interface IHelloWorldService {
public String sayHello(String s1,String s2);
}

public class HelloWorldService implements IHelloWorldService {
@Override
public String sayHello(String s1,String s2){
return s1+" "+s2;
}
}

aspect类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Aspect
public class MyAspect {
//切入点 args获取方法参数
@Pointcut(value="execution(* sayHello(..)) && args(s1,s2)")
public void helloService(String s1,String s2){}
//前置通知
@Before(value="helloService(s1,s2)")
public void beforeMethod(String s1,String s2){
System.out.println("before:"+s1+" "+s2);
}
//环绕通知
@Around("helloService(s1,s2)")
public Object aroundMethod(ProceedingJoinPoint pjp,String s1,String s2) throws Throwable{
System.out.println("around before: "+s1);
Object obj = pjp.proceed();
System.out.println("around after: "+s2);
return obj;
}
//后置通知,returning为返回值
@AfterReturning(value="helloService(s1,s2)",returning="rtv")
public void afterMethod(JoinPoint jp,Object rtv,String s1,String s2){
//通过getArgs获取方法所有参数
Object[] obj = jp.getArgs();
for(Object o:obj){
System.out.println(o.toString());
}
//获取类名及执行方法名
System.out.println(jp.getSignature().getDeclaringTypeName()
+"."+jp.getSignature().getName()
+" return: "+rtv);
}
//@AfterThrowing当方法抛出异常后执行
//@After类似于finally中的方法,不管方法有无异常抛出都会通知
}

configuration类

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
@EnableAspectJAutoProxy //开启aspect织入支持
public class AppConfig {
@Bean
public IHelloWorldService iHelloWorldService(){
return new HelloWorldService();
}
@Bean
public MyAspect myAspect(){
return new MyAspect();
}
}

test

1
2
3
4
5
6
7
8
public class Test1 {
private static AnnotationConfigApplicationContext ctx;
public static void main(String[] args) {
ctx = new AnnotationConfigApplicationContext(AppConfig.class);
IHelloWorldService service = ctx.getBean(IHelloWorldService.class);
service.sayHello("a", "b");
}
}

输出

1
2
3
4
5
6
around before: a
before:a b
around after: b
a
b
com.spring.service.IHelloWorldService.sayHello return: a b

spring注解相关知识点

发表于 2015-05-15 | 分类于 Java , Spring |

spring 基本注解

Spring Annotation 详解
autowire异常的三个情况
Spring注释@Qualifier

@Component: 是一个泛化的概念,仅仅表示一个组件 (Bean) ,可以作用在任何层次。
@Service: 常作用在业务层
@Constroller: 通常作用在控制层
@Repository: 只能标注在 DAO 类上
@Scope: 指定 Bean 的作用域

1
2
3
@Scope("prototype")     
@Repository
public class Demo { … }

@PostConstruct: 标注初始化之后执行的回调方法
@PreDestroy: 标注销毁之前执行的回调方法
@Required: 进行对Bean的依赖检查,判断给定Bean的相应Setter方法是否都在实例化的时候被调用了标签提供了 dependency-check 属性用于进行依赖检查。该属性的取值包括以下几种:

  • none: 默认不执行依赖检查
  • simple: 对原始基本类型和集合类型进行检查。
  • objects: 对复杂类型进行检查(除了 simple 所检查类型之外的其他类型)。
  • all: 对所有类型进行检查。

自动装配

@Autowired: 自动装配.Spring 在装配 Bean 的时候,根据指定的自动装配规则,将某个 Bean 所需要引用类型的 Bean 注入进来。 元素提供了一个指定自动装配类型的 autowire 属性,该属性有如下选项:

  • no: 显式指定不使用自动装配。
  • byName: 如果存在一个和当前属性名字一致的Bean,则使用该Bean 进行注入。如果名称匹配但是类型不匹配,则抛出异常。如果没有匹配的类型,则什么也不做。
  • byType: 如果存在一个和当前属性类型一致的 Bean ( 相同类型或者子类型 ),则使用该 Bean 进行注入。byType 能够识别工厂方法,即能够识别 factory-method 的返回类型。如果存在多个类型一致的 Bean,则抛出异常。如果没有匹配的类型,则什么也不做。
  • constructor: 与 byType 类似,只不过它是针对构造函数注入而言的。如果当前没有与构造函数的参数类型匹配的 Bean,则抛出异常。使用该种装配模式时,优先匹配参数最多的构造函数。
  • autodetect: 根据Bean的自省机制决定采用byType还是constructor进行自动装配。如果 Bean 提供了默认的构造函数,则采用byType;否则采用constructor进行自动装配。

在按类型匹配的时候(可能是byType、constructor、autodetect),同一个类型可能存在多个Bean如果被注入的属性是数组、集合或者Map,这可能没有问题,但是如果只是简单的引用类型,则会抛出异常。解决方法有如下几种:

  • 取消该 Bean 的自动装配特性,使用显式的注入。我们可能不希望某个 Bean 被当作其他 Bean 执行自动封装时的候选对象,我们可以给该 增加 autowire-candidate="false"。(autowire-candidate属性和autowire属性相互独立,互不相干) 另外,我们可以设置default-autowire-candidates属性,可以在该属性中指定可以用于自动装配候选 Bean 的匹配模式,比如 default-autowire-candidates="*serv,*dao",这表示所有名字以serv或者dao结尾的 Bean 被列为候选,其他则忽略,相当于其他 Bean 都指定为 autowire-candidate="false",此时可以显式为 指定 autowire-candidate="true"。在 上指定的设置要覆盖 上指定的设置。
  • 如果在多个类型相同的 Bean 中有首选的 Bean,那么可以将该 的primary属性设置为 “true” ,这样自动装配时便优先使用该 Bean 进行装配。此时不能将autowire-candidate 设为 false

使用@Autowired注解进行装配,只能是根据类型进行匹配。@Autowired 注解可以用于 Setter 方法、构造函数、字段,甚至普通方法,前提是方法必须有至少一个参数。@Autowired 可以用于数组和使用泛型的集合类型。然后 Spring 会将容器中所有类型符合的 Bean 注入进来。@Autowired 标注作用于 Map 类型时,如果 Map 的 key 为 String 类型,则 Spring 会将容器中所有类型符合 Map 的 value 对应的类型的 Bean 增加进来,用 Bean 的 id 或 name 作为 Map 的 key。

当标注了@Autowired后,自动注入不能满足,则会抛出异常。我们可以给@Autowired标注增加一个required=false属性,以改变这个行为。另外,每一个类中只能有一个构造函数的`@Autowired.required()属性为true。否则就出问题了。如果用@Autowired`同时标注了多个构造函数,那么,Spring 将采用贪心算法匹配构造函数 ( 构造函数最长 )。

@Qualifier: 当容器中存在多个Bean的类型与需要注入的相同时,注入将不能执行,我们可以给@Autowired增加一个候选值,做法是在@Autowired后面增加一个@Qualifier标注,提供一个String类型的值作为候选的Bean的名字。

1
2
3
@Autowired(required=false)
@Qualifier("ppp")
public void setPerson(person p){}

可以作用于方法的参数 ( 对于方法只有一个参数的情况,我们可以将 @Qualifer 标注放置在方法声明上面,但是推荐放置在参数前面 )

1
2
@Autowired(required=false)     
public void sayHello(@Qualifier("ppp")Person p,String name){}

如果没有明确指定Bean的qualifier名字,那么默认名字就是 Bean 的名字
如果@Autowired注入的是BeanFactory、ApplicationContext、ResourceLoader 等系统类型,那么则不需要@Qualifier,此时即使提供了@Qualifier注解,也将会被忽略;而对于自定义类型的自动装配,如果使用了@Qualifier注解并且没有名字与之匹配的 Bean,则自动装配匹配失败。


@Resource: 如果希望根据name执行自动装配,那么应该使用JSR-250提供的@Resource注解,而不应该使用@Autowired与@Qualifier的组合。@Resource使用byName的方式执行自动封装。@Resource标注可以作用于带一个参数的Setter方法、字段,以及带一个参数的普通方法上。@Resource注解有一个name属性,用于指定 Bean 在配置文件中对应的名字。如果没有指定 name 属性,那么默认值就是字段或者属性的名字。@Resource 和 @Qualifier 的配合虽然仍然成立,但是 @Qualifier 对于 @Resource 而言,几乎与 name 属性等效。

如果 @Resource 没有指定 name 属性,那么使用byName匹配失败后,会退而使用byType继续匹配,如果再失败,则抛出异常。在没有为@Resource注解显式指定name属性的前提下,如果将其标注在BeanFactory 类型、ApplicationContext类型、ResourceLoader类型、ApplicationEventPublisher类型、MessageSource类型上,那么 Spring 会自动注入这些实现类的实例,不需要额外的操作。此时 name 属性不需要指定 ( 或者指定为””),否则注入失败;如果使用了 @Qualifier,则该注解将被忽略。而对于用户自定义类型的注入,@Qualifier 和 name 等价,并且不被忽略


JAVA配置Bean声明

@Configuration: 用于指定配置信息的类上加上@Configuration注解,以明确指出该类是 Bean 配置的信息源。Spring 对标注 Configuration 的类有如下要求

  • 配置类不能是 final 的
  • 配置类不能是本地化的,亦即不能将配置类定义在其他类的方法内部
  • 配置类必须有一个无参构造函数

@Bean: AnnotationConfigApplicationContext将配置类中标注了@Bean的方法的返回值识别为Spring Bean,并注册到容器中,受IoC容器管理。@Bean的作用等价于XML 配置中的标签。

1
2
3
4
5
6
7
@Configuration     
public class BookStoreDaoConfig{
@Bean
public UserDao userDao(){ return new UserDaoImpl();}
@Bean
public BookDao bookDao(){return new BookDaoImpl();}
}

与以上配置等价的 XML 配置如下

1
2
<bean id="userDao" class="bookstore.dao.UserDaoImpl"/>      
<bean id="bookDao" class="bookstore.dao.BookDaoImpl"/>

@Bean具有以下四个属性:

  • name: 指定一个或者多个 Bean 的名字。这等价于 XML 配置中 的 name 属性。
  • initMethod: 容器在初始化完Bean之后,会调用该属性指定的方法。这等价于XML配置中的init-method属性。
  • destroyMethod: 该属性与initMethod功能相似,在容器销毁 Bean 之前,会调用该属性指定的方法。这等价于XML配置中的destroy-method属性。
  • autowire: 指定 Bean 属性的自动装配策略,取值是Autowire类型的三个静态属性。Autowire.BY_NAME,Autowire.BY_TYPE,Autowire.NO。与 XML 配置中的autowire属性的取值相比,这里少了constructor,这是因为constructor在这里已经没有意义了。

AnnotationConfigApplicationContext提供了三个构造函数用于初始化容器。

  • AnnotationConfigApplicationContext():该构造函数初始化一个空容器,容器不包含任何 Bean 信息,需要在稍后通过调用其register()方法注册配置类,并调用refresh()方法刷新容器。
  • AnnotationConfigApplicationContext(Class... annotatedClasses):这是最常用的构造函数,通过将涉及到的配置类传递给该构造函数,以实现将相应配置类中的 Bean 自动注册到容器中。
  • AnnotationConfigApplicationContext(String... basePackages):该构造函数会自动扫描以给定的包及其子包下的所有类,并自动识别所有的 Spring Bean,将其注册到容器中。它不但识别标注@Configuration的配置类并正确解析,而且同样能识别使用@Repository、@Service、@Controller、@Component标注的类。

除了使用上面第三种类型的构造函数让容器自动扫描 Bean 的配置信息以外,AnnotationConfigApplicationContext 还提供了scan()方法,其功能与上面也类似,该方法主要用在容器初始化之后动态增加 Bean 至容器中。调用了该方法以后,通常需要立即手动调用refresh()刷新容器,以让变更立即生效。

@Import:引入其他@Configuration类

1
2
3
@Configuration   
@Import({BookStoreServiceConfig.class,BookStoreDaoConfig.class})
public class BookStoreConfig{ … }

混合使用 XML 与注解进行 Bean 的配置
以XML为主的配置

1
2
3
4
5
6
7
@Configuration   
public class MyConfig{
@Bean
public UserDao userDao(){
return new UserDaoImpl();
}
}

在XML配置bean

1
2
3
4
5
<beans … >   
……
<context:annotation-config />
<bean class=”demo.config.MyConfig”/>
</beans>

由于启用了针对注解的 Bean 后处理器,因此在 ApplicationContext 解析到 MyConfig 类时,会发现该类标注了@Configuration注解,随后便会处理该类中标注@Bean的方法,将这些方法的返回值注册为容器总的 Bean。

对于以上的方式,如果存在多个标注了@Configuration的类,则需要在 XML 文件中逐一列出。另一种方式是使用前面提到的自动扫描功能,配置如下:

1
<context:component-scan base-package=”bookstore.config” />

如果在Configuration中可以使用@ComponentScan进行扫描
对于以注解为中心的配置方式,只需使用@ImportResource注解引入存在的 XML 即可

1
2
3
4
5
@Configuration   
@ImportResource(“classpath:/bookstore/config/spring-beans.xml”)
public class MyConfig{
……
}

容器的初始化过程和纯粹的以配置为中心的方式一致

1
2
AnnotationConfigApplicationContext ctx =   
new AnnotationConfigApplicationContext(MyConfig.class);


Spring 使用注解方式进行事物管理

Spring 使用注解方式进行事物管理

@Transactional: 当标于类前时, 标示类中所有方法都进行事物处理

事物传播行为介绍:
@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER)
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

事物超时设置:
@Transactional(timeout=30)//默认是30秒

事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE)
串行化

MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED

脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说,
后续读取可以读到另一事务已提交的更新数据. 相反, “可重复读”在同一事务中多次
读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读 : 一个事务读到另一个事务已提交的insert数据


Spring MVC部分注解

Spring4.0系列3-@RestController
Spring @SessionAttributes @ModelAttribute
6 详解@SessionAttributes
spring学习之@ModelAttribute运用详解
Spring MVC之@RequestMapping 详解
@RequestParam @RequestBody @PathVariable 等参数绑定注解详解
@RequestBody, @ResponseBody 注解详解
SpringMVC @RequestBody接收Json对象字符串
spring3.1.1 使用@ResponseBody 返回中文时出现乱码
Spring 注解学习手札(八)补遗——@ExceptionHandler
Spring MVC 的请求参数获取的几种方法
Spring @PropertySource example

@RestController

@RestController: 继承于@Controller,开发REST服务的时候不需要使用@Controller而专门的@RestController.当实现一个RESTful web services的时候,response将一直通过response body发送。为了简化开发,Spring 4.0提供了一个专门版本的controller

1
2
3
4
5
6
@Target(value=TYPE)  
@Retention(value=RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController

使用了@RestController注解之后,方法就可以不需要再指定@ResponseBody了


@ModelAttribute

@ModelAttribute: 该注解有两个用法,一个是用于方法上,一个是用于参数上;
用于方法上时: 通常用来在处理@RequestMapping之前,为请求绑定需要从后台查询的model;
用于参数上时: 用来通过名称对应,把相应名称的值绑定到注解的参数bean上;要绑定的值来源于:
A) @SessionAttributes 启用的attribute 对象上;
B) @ModelAttribute 用于方法上时指定的model对象;
C) 上述两种情况都没有时,new一个需要绑定的bean对象,然后把request中按名称对应的方式把值绑定到bean中

@ModelAttribute注释void返回值的方法

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloWorldController {  

@ModelAttribute
public void populateModel(@RequestParam String abc, Model model) {
model.addAttribute("attributeName", abc);
}

@RequestMapping(value = "/helloWorld")
public String helloWorld() {
return "helloWorld";
}
}

这个例子,在获得请求/helloWorld 后,populateModel方法在helloWorld方法之前先被调用,它把请求参数(/helloWorld?abc=text)加入到一个名为attributeName的model属性中,在它执行后helloWorld被调用,返回视图名helloWorld和model已由@ModelAttribute方法生产好了。

@ModelAttribute注释返回具体类的方法

1
2
3
4
@ModelAttribute  
public Account addAccount(@RequestParam String number) {
return accountManager.findAccount(number);
}

这种情况,model属性的名称没有指定,它由返回类型隐含表示,如这个方法返回Account类型,那么这个model属性的名称是account。

@ModelAttribute(value="")注释返回具体类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller  
public class HelloWorldController {

@ModelAttribute("attributeName")
public String addAccount(@RequestParam String abc) {
return abc;
}

@RequestMapping(value = "/helloWorld")
public String helloWorld() {
return "helloWorld";
}
}

这个例子中使用@ModelAttribute注释的value属性,来指定model属性的名称。model属性对象就是方法的返回值。它无须要特定的参数

@ModelAttribute和@RequestMapping同时注释一个方法

1
2
3
4
5
6
7
8
@Controller  
public class HelloWorldController {
@RequestMapping(value = "/helloWorld.do")
@ModelAttribute("attributeName")
public String helloWorld() {
return "hi";
}
}

这时这个方法的返回值并不是表示一个视图名称,而是model属性的值,视图名称由RequestToViewNameTranslator根据请求”/helloWorld.do”转换为逻辑视图helloWorld。
Model属性名称有@ModelAttribute(value=””)指定,相当于在request中封装了key=attributeName,value=hi

@ModelAttribute注释一个方法的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Controller  
public class HelloWorldController {

@ModelAttribute("user")
public User addAccount() {
return new User("jz","123");
}

@RequestMapping(value = "/helloWorld")
public String helloWorld(@ModelAttribute("user") User user) {
user.setUserName("jizhou");
return "helloWorld";
}
}

在这个例子里,@ModelAttribute("user") User user注释方法参数,参数user的值来源于addAccount()方法中的model属性。
此时如果方法体没有标注@SessionAttributes("user"),那么scope为request,如果标注了,那么scope为session


@SessionAttributes

@SessionAttributes:该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象.

通过Model绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Controller
@RequestMapping(value = "login")
@SessionAttributes("mysession")
//定义把Model中的mysession属性的值绑定到Session中
public class LoginController {
@RequestMapping(method = RequestMethod.POST)
public String login(@ModelAttribute User user, ModelMap model) {
String viewName = "";
boolean check = true;
if (check) {
model.addAttribute("mysession", "123");
viewName = "redirect:/home";
} else {
viewName = "redirect:/";
}
return viewName;
}
}

这样我们不但可以在请求所对应的JSP视图页面中通过request.getAttribute()和session.getAttribute()获取mysession,还可以在下一个请求所对应的JSP视图页面中通过session.getAttribute()或ModelMap#get()访问到这个属性。
这里我们仅将一个ModelMap的属性放入Session中,其实@SessionAttributes允许指定多个属性。你可以通过字符串数组的方式指定多个属性,如 @SessionAttributes({“attr1”,”attr2”})。此外,@SessionAttributes还可以通过属性类型指定要session化的ModelMap属性,如@SessionAttributes(types=User.class),当然也可以指定多个类,如 @SessionAttributes(types = {User.class,Dept.class}),还可以联合使用属性名和属性类型指定:@SessionAttributes(types = {User.class,Dept.class},value={“attr1”,”attr2”})。

通过@ModelAttribute绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Controller
@RequestMapping(value = "login")
//此处定义需要绑定到session中的model名称
@SessionAttributes("user")
public class LoginController {
@RequestMapping(method = RequestMethod.POST)
//@ModelAttribute将绑定到session中
public String login(@ModelAttribute("user") User user, ModelMap model){
String viewName = "";
boolean check = true;
if (check) {
viewName = "redirect:/home";
} else {
viewName = "redirect:/";
}
return viewName;
}
}

@SessionAttributes需要清除时,使用SessionStatus.setComplete();来清除。注意,它只清除SessionAttributes的session,不会清除HttpSession的数据。故如用户身份验证对象的session一般不同它来实现,还是用session.setAttribute等传统的方式实现。


@RequestMapping

@RequestMapping: RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。主要有如下属性:

  • value: 指定请求的实际地址,指定的地址可以是URI Template 模式,可以指定为普通的具体值,含有某变量的一类值及含正则表达式的一类值
  • method: 指定请求的method类型, GET、POST、PUT、DELETE等
  • consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
  • produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
  • params: 指定request中必须包含某些参数值是,才让该方法处理
  • headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Controller
@RequestMapping("/hello")
public class HelloController{
//默认
@RequestMapping("/one")
public void oneMethod(){}

//指定请求方法为POST类型
@RequestMapping(value="/two",method=RequestMetho.POST)
public void twoMethod(){}

//含有某变量
@RequestMapping(value="/{three}", method = RequestMethod.GET)
public void threeMethod(@PathVariable String three){}

//含正则表达式
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\d\.\d\.\d}.{extension:\.[a-z]}")
public void fourMethod(@PathVariable String version, @PathVariable String extension) {}

//consumes指定仅处理request Content-Type为“application/json”类型的请求
//produces指定返回的内容类型为text/plain,同时指定字符集,否则碰中文会乱码
@RequestMapping(value="/five",method=RequestMethod.POST, consumes="application/json",produces="text/plain;charset=utf-8")
@ReponseBody
public void fiveMethod(@RequestBody User user){}

//params指定仅处理请求中包含了名为“myParam”,值为“myValue”的请求
//headers指定仅处理request的header中包含了指定“Refer”请求头和对应值为“http://www.baidu.com/”的请求
@RequestMapping(value="/six",method=RequestMethod.GET, params="myParam=myValue", headers="Referer=http://www.baidu.com/")
public void sixMethod(){}
}

@PathVariable:当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过@Pathvariable注解绑定它传过来的值到方法的参数上

1
2
@RequestMapping(value="/{three}", method = RequestMethod.GET)
public void threeMethod(@PathVariable String three){}

上面代码把URI template 中变量three,绑定到方法的参数上。若方法参数名称和需要绑定的uri template中变量名称不一致,需要在@PathVariable("name")指定uri template中的名称


@RequestHeader: 可以把Request请求header部分的值绑定到方法的参数上
Request 的header部分

1
2
3
4
5
6
Host                    localhost:8080  
Accept text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language fr,en-gb;q=0.7,en;q=0.3
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 300

把request header部分的 Accept-Encoding的值,绑定到参数encoding上了, Keep-Alive header的值绑定到参数keepAlive上

1
2
3
@RequestMapping("/seven")  
public void sevenMethod(@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Keep-Alive") long keepAlive) { }


@CookieValue: 可以把Request header中关于cookie的值绑定到方法的参数上

1
2
@RequestMapping("/eight")  
public void eightMethod(@CookieValue("JSESSIONID") String cookie) { }


@RequestParam

@RequestParam
A) 常用来处理简单类型的绑定,通过Request.getParameter() 获取的String可直接转换为简单类型的情况( String–> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值;

B)用来处理Content-Type: 为application/x-www-form-urlencoded编码的内容,提交方式GET、POST;

C) 该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;

1
2
@RequestMapping("/nine", method=RequestMethod.POST)
public void nineMethod(@RequestMapping("name")String name, @RequestMapping(required=false)int age){}


@RequestBody

  1. 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
  2. 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

使用时机:

  1. GET、POST方式提时, 根据request header Content-Type的值来判断:
  • application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
  • multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
  • 其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
  1. PUT方式提交时, 根据request header Content-Type的值来判断:

    • application/x-www-form-urlencoded, 必须;
    • multipart/form-data, 不能处理;
    • 其他格式, 必须;

说明:request的body部分的数据编码格式由header部分的Content-Type指定;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$(function(){  
var saveDataAry=[];
var data1={"userName":"u1","address":"by"};
var data2={"userName":"u2","address":"yx"};
saveDataAry.push(data1);
saveDataAry.push(data2);
$.ajax({
type:"POST",
url:"user/saveUser",
dataType:"json",
contentType:"application/json",
data:JSON.stringify(saveData),
success:function(data){

}
});
});

1
2
3
4
5
@RequestMapping(value = "saveUser", method = {RequestMethod.POST }}) 
@ResponseBody
public void saveUser(@RequestBody List<User> users) {
userService.save(users);
}

@ResponseBody

该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

Spring xml配置

发表于 2015-05-15 | 分类于 Java , Spring |

Spring使用Annotation时需要注意的地方

Spring使用Annotation时需要注意的地方

使用Annotation注解形式时,在Spring的配置文件中需要加入新的xsd文件引用:

阅读全文 »
1234…6
Shepard

Shepard

59 日志
25 分类
67 标签
GitHub
© 2015 — 2020 Shepard
由 Hexo 强力驱动
|
主题 — NexT.Mist v5.1.4