Spring mvc的注解功能
1、@Controller——表示控制器
举例:
@Controller
public class SoftCreateController extendsSimpleBaseController {}
或者:
@Controller("softCreateController")
说明:
@Controller负责注册一个bean到spring上下文中,bean的ID默认为类名称开头字母小写。当一个类加上@Controller之后就表明已经注册到spring上下文了,不用再去spring的配置文件中显式的使用的形式进行注册了。
注意:
和Struts1一样,Spring的Controller是Singleton的。这就意味着会被多个请求线程共享。因此,我们将控制器设计成无状态类。
在spring 3.0中,通过@controller标注即可将class定义为一个controller类。有以上可知,为使spring能找到定义为controller的bean,需要在spring配置文件servlet-context.xml中增加如下定义:
<context:component-scan base-package="相应controller所在的包"/>
注:实际上,使用@component(下面有介绍),也可以起到@Controller同样的作用。
2、@Service——表示业务处理层【一般在ServiceImpl】
举例:
@ Service
public class SoftCreateServiceImpl implements ISoftCreateService{}
或者:
@Service("softCreateServiceImpl")
说明:
@Service负责注册一个bean到spring上下文中,bean的ID默认为类名称开头字母小写。
3、@Repository——表示持久层【一般在daoImpl】
与@Controller、@Service类似,都是向spring上下文中注册bean;
4、@Component——当你的类不清楚在哪一层时使用该注解【不推荐使用】
@Component是所有受Spring管理组件的通用形式,Spring还提供了更加细化的注解形式: @Repository、@Service、@Controller,它们分别对应数据存储层Bean,业务层Bean,和展示层Bean。
@Component是一种泛指,标记类是组件,spring扫描注解配置时,会标记这些类要生成bean。
目前版本(2.5)中,这些注解与@Component的语义是一样的,完全通用,在Spring以后的版本中可能会给它们追加更多的语义。所以,我们推荐使用@Repository、@Service、@Controller来替代@Component。
5、@Resource
例如:
@Resource
private DataSource dataSource; // inject the bean named 'dataSource'
或者:
@Resource(name="dataSource")
@Resource(type=DataSource.class)
说明:
@Resource默认按bean的name进行查找,如果没有找到会按type进行查找,此时与@Autowired类似;在没有为 @Resource注解显式指定 name属性的前提下,如果将其标注在BeanFactory类型、ApplicationContext类型、ResourceLoader类型、ApplicationEventPublisher类型、MessageSource类型上,那么 Spring 会自动注入这些实现类的实例,不需要额外的操作。此时name属性不需要指定(或者指定为”“),否则注入失败;
6、@Autowried
举例:
@Autowired
private ISoftPMService softPMService;
或者:
@Autowired(required=false)
private ISoftPMService softPMService = newSoftPMServiceImpl();
说明:
@Autowired根据bean类型从spring上线文中进行查找,注册类型必须唯一,否则报异常。与@Resource的区别在于,@Resource允许通过bean名称或bean类型两种方式进行查找@Autowired(required=false)表示,如果spring上下文中没有找到该类型的bean时,才会使用new SoftPMServiceImpl();
@Autowired还有一个作用就是,如果将其标注在 BeanFactory类型、ApplicationContext类型、ResourceLoader类型、ApplicationEventPublisher类型、MessageSource类型上,那么 Spring会自动注入这些实现类的实例,不需要额外的操作。
注意:
javax.annotation.Resource注解实现的效果和@Autowired+@Qualifier的效果是一样的。 另外,同时使用Autowired注解和Qualifier注解时也要注意一点:
如果采用@Autowired来注解,则无需指定name属性,若是实现该接口有多个类,则需要通过@Qualifier来做区分:
CarService1、CarService2是实现ICarService的两个实现类,类中@Service的注解分别是:
@Service("carService1")
public class CarService implements ICarService {}
@Service("carService2")
public class CarService2 implements ICarService {}
那么在测试方法,使用接口ICarService时,当使用@Autowired来标注时,需要使用注解@Qualifier来做区分具体使用到的实现类:
@Autowired
@Qualifier("carService2")
private ICarService carService;
既:使用@Autowired时,如果找到多个同一类型的bean,则会抛异常,此时可以使用 @Qualifier(“beanName”),明确指定bean的名称进行注入,此时与 @Resource指定name属性作用相同。
7、@RequestMapping
可以声明到类或者方法上,用于注解该类和方法的访问路径(控制器可以处理哪些URL请求);
8、@RequestParam
用于将指定的请求参数赋值给方法中的形参,如果请求参数名称和形参保持一致,则此种写法就没有必要了;该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;
9、@PathVariable
将通过@RequestMapping传过来的值绑定到方法的参数上
10、@RequestBody
作用:
1) 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上;
2) 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。
使用时机:
1) GET、POST方式提交时, 根据request header Content-Type的值来判断:
a、 application/x-www-form-urlencoded, 可选(即非必须,因为这种情况的数据@RequestParam, @ModelAttribute也可以处理,当然@RequestBody也能处理);
b、 multipart/form-data, 不能处理(即使用@RequestBody不能处理这种格式的数据);
c、 其他格式, 必须(其他格式包括application/json, application/xml等。这些格式的数据,必须使用@RequestBody来处理);
2) PUT方式提交时, 根据request header Content-Type的值来判断:
a、 application/x-www-form-urlencoded, 必须;
b、 multipart/form-data, 不能处理;
c、 其他格式, 必须;
说明:request的body部分的数据编码格式由header部分的Content-Type指定;
11、@ResponseBody
作用:
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
代码示例:
package com.hollycrm.hollyuniproxy.admin.mvc;
@Controller
public class EcsServiceController {
private static final Log logger = LogFactory.getLog(EcsServiceController.class);
@Resource(name= "ecsClient")
ThirdServiceClient ecsClient ;
@Resource(name= "ecsConfig")
EcsConfig ecsConfig ;
}
@RequestMapping(value = "/ecs/remove/{key}" ,produces="text/html;charset=UTF-8" )
public @ResponseBody String removeConfig(@PathVariable String key){
ecsConfig.removeEcsService(key);
return "OK";
}
@RequestMapping(value = "/ecs" )
public @ResponseBody Map<String,Object> postForEcsResponse(@RequestParam String serviceName,
@RequestParam(required = false) Map<String,Object> inParam){
logger.debug("serviceName " + serviceName);
logger.debug("inParam " + inParam);
return ecsClient.postForResponse(serviceName, inParam);
}
@RequestMapping(value = "/qryDetail", produces="text/plain;charset=UTF-8")
public @ResponseBody String queryDetail(@RequestBody String json,HttpServletRequest req) {
logger.debug("---------------------杩涘叆/restservice/qryDetail--------------------------");
return "";
}
}
12、@RequestHeader
@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。
示例代码:
这是一个Request 的header部分:
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
@RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Keep-Alive") long keepAlive) {
}
上面的代码,把request header部分的 Accept-Encoding的值,绑定到参数encoding上了, Keep-Alive header的值绑定到参数keepAlive上。
13、@CookieValue
@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。
例如有如下Cookie值:
JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
参数绑定的代码:
@RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {
}
即把JSESSIONID的值绑定到参数cookie上。
14、@Scope
说明:
在使用XML定义Bean时,可以通过bean的scope 属性来定义一个Bean的作用范围,同样可以通过@Scope注解来完成。
@Scope中可以指定如下值:
singleton:定义bean的范围为每个spring容器一个实例(默认值)
prototype:定义bean可以被多次实例化(使用一次就创建一次)
request:定义bean的范围是http请求(springMVC中有效)
session:定义bean的范围是http会话(springMVC中有效)
global-session:定义bean的范围是全局http会话(portlet中有效)
15、@SessionAttributes
说明:
Spring允许我们有选择地指定 ModelMap中的哪些属性需要转存到 session中,以便下一个请求属对应的 ModelMap的属性列表中还能访问到这些属性。这一功能是通过类定义处标注 @SessionAttributes注解来实现的。@SessionAttributes只能声明在类上,而不能声明在方法上。
例如:
@SessionAttributes("currUser") //将ModelMap中名为currUser的属性放到session中,前台可以通过${sessionScope.currUser}来获取属性currUser的值
@SessionAttributes({"attr1","attr2"})
@SessionAttributes(types = User.class)
@SessionAttributes(types = {User.class,Dept.class})
@SessionAttributes(types ={User.class,Dept.class},value={"attr1","attr2"})
16、@ModelAttribute
这个注解可以跟@SessionAttributes配合在一起用。可以将ModelMap中属性的值通过该注解自动赋给指定变量。
示例代码如下:
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@RequestMapping("/user.do")
@SessionAttributes({"u","a"})
public class UserController {
@RequestMapping(params="method=reg4")
public String reg4(ModelMap map) {
System.out.println("HelloController.handleRequest()");
map.addAttribute("u","kobe");
return "index";
}
@RequestMapping(params="method=reg5")
//将属性u的值赋给形参uname
public String reg5(@ModelAttribute("u")String uname,ModelMap map) {
System.out.println("HelloController.handleRequest()");
System.out.println(uname);
return "index";
}
}
17、@Required
@Required
public setName(String name){}
说明:
@ required负责检查一个bean在初始化时其声明的 set方法是否被执行,当某个被标注了 @Required的 Setter方法没有被调用,则 Spring在解析的时候会抛出异常,以提醒开发者对相应属性进行设置。 @Required注解只能标注在 Setter方法之上。因为依赖注入的本质是检查 Setter方法是否被调用了,而不是真的去检查属性是否赋值了以及赋了什么样的值。如果将该注解标注在非 setXxxx()类型的方法则被忽略。
18、@InitBinder
说明:
在SpringMVC中,bean中定义了Date,double等类型,如果没有做任何处理的话,日期以及double都无法绑定。解决的办法就是使用spring mvc提供的@InitBinder标签;
如果希望某个属性编辑器仅作用于特定的 Controller,可以在 Controller中定义一个标注 @InitBinder注解的方法,可以在该方法中向 Controller注册若干个属性编辑器,那么spring mvc在绑定表单之前,都会先注册这些编辑器,当然你如果不嫌麻烦,你也可以单独的写在你的每一个controller中。剩下的控制器都继承该类。spring自己提供了大量的实现类,诸如CustomDateEditor ,CustomBooleanEditor,CustomNumberEditor等许多,基本上够用。
示例:
@InitBinder
public void initBinder(WebDataBinder binder){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class,new CustomDateEditor(dateFormat,false));
}
注意:
SimpleDateFormat和DateFormat的setLenient()方法用于设置Calendar是否宽松解析字符串,如果为false,则严格解析;默认为true,宽松解析。