@Configuration:用于修饰一个Java配置类
@Bean:用于修饰一个方法,将该方法的返回值定义成容器中的一个Bean
@Value:用于修饰一个Field,用于为配置一个值。
如:
@Configuration
public class AppConfig
{
//定义需要依赖注入的属性值
@value("孙悟空") StringpersonName;
//配置一个Bean:chinese
@Bean(name="Chinese")
public Person person(){
Chinese p=new Chinese();
p.setAxe(stoneAxe());
p.setName(personName);
return p;
}
//配置Bean:stoneAxe
@Bean:(name="stoneAxe")
public Axe stoneAxe(){
return new StoneAxe();
}
//配置Bean:steelAxe
@Bean(name="steelAxe")
public Axe steelAxe(){
return new SteelAxe();
}
}
//创建Spring容器
ApplicationContext ctx=newAnnotationConfigApplicationContext(AppConfig.class);
@Import:修饰一个Java配置类,用于向当前Java配置类中导入其他Java配置类
@Scope:用于修饰一个方法,指定该方法对应的Bean的生命域
@Lazy:用于修饰一个方法,指定该方法对应的Bean的是否需要延迟初始化
@DependOn:用于修饰一个方法,指定在初始化该方法对应的Bean之前初始化指定Bean
@ImportResource("classpath:/bean.xml"):导入XML配置
Controller体系中
BaseCommandController及其子类AbstractCommandController、AbstractFormController、
AbstractWizardFormController、SimpleFormController、CancellableFormController等都已经被标示为@Deprecated,建议不再使用。
下面通过对SpringMVC注解的详细介绍来看一下上述优点。
首先需要在应用的dispatcher-servlet.xml启动注解机制
<context:annotation-config />
<!-- 设置注解驱动 -->
<mvc:annotation-driven />
<!-- 设置扫描的包 -->
<context:component-scan base-package="com.demo.web.controller"/>
<beanclass="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<beanclass="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
注:虽然我们的Controller不需要再继承任何类,但出于规范,我们仍然命名为***Controller.java,并统一放在
com.demo.web.controller包中。
简单示例
package com.demo.controller;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
@Controller
class IndexController {
@RequestMapping("/index")
String index() {
return "index";
}
}
注:
在一个POJO(简单的Java对象)上面使用 @Controller 就可以标注该POJO是一个Controller,就这么简单
@Controller注解定义在org.springframework.steretype包中。
使用方式:@Controller 或者@Controller("indexController")。 org.springframework.steretype包中还包含@Componenet @Service @Respository
三个注解。@Component是通用标注,@Controller标注web控制器,@Service标注Servicec层的服务,@Respository标注DAO层的数据访问。
2、使用@RequestMapping注解处理请求映射
SpringMVC中注解基本都包含在 org.springframework.web.bind.annotation 包中。先看一下@RequestMapping 注解的源码。
@Target( { ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
/**
* 指定映射的URL.可以在类层次和方法层次使用。方式如下:
* @RequestMapping("/add_")或 @RequestMapping(value = "/add")
* 支持Ant风格的URL映射,如 @RequestMapping("/myPath/*.htm")
* 在类层次指定了映射后,可以在方法层次再指定相对路径
*/
String[] value()default {};
/**
* 指定HttpRequest的方法, 如:GET, POST, HEAD, OPTIONS, PUT,DELETE, TRACE.
* 使用举例:@RequestMapping(value = "/add_activity", method = RequestMethod.GET)
*/
RequestMethod[]method() default {};
/**
* 指定HttpRequest中包含的参数,使用方式如下:
* @RequestMapping(value = "/something",params="myParam") 请求包含myParam参数
* @RequestMapping(value = "/something",params="myParam=myValue")请求包含myParam参数,并且该参数值
为myValue
* @RequestMapping(value = "/something",params="!myParam") 请求不包含myParam参数
*/
String[] params()default {};
/**
* 指定HttpRequest中包含的头部信息,使用方式如下:
* @RequestMapping(value = "/something", headers="content-type")请求包含该头部
* @RequestMapping(value = "/something", headers="content-type=text/*")请求包含特定值的头部
* @RequestMapping(value = "/something", headers="!content-type")请求不包含该头部
*/
String[] headers()default {};
}
注:如果在类层次指定了映射,则方法层次上都将继承类层次的映射
3、获取HttpRequest中得参数
@RequestMapping("active")
public @ResponseBody boolean active(Long accountId) {
return accountService.activeAccount(accountId);
}
@RequestMapping("active")
public @ResponseBody boolean active(Accountaccount) {
return accountService.activeAccount(accountId);
}
@RequestMapping("inactive")
public @ResponseBody booleaninactive(@RequestParam("accountId") Long accountId,
@RequestHeader("User-Agent") String userAgent,
@CookieValue("loginId") String loginId) {
return accountService.inactiveAccount(accountId);
}
@RequestMapping(value ="list/{pageNo}", method = RequestMethod.GET)
public String list(@PathVariable intpageNo) {
return "/account/list";
}
@RequestMapping(value = "add",method = RequestMethod.GET)
public String add(@RequestBody String body){
return "/account/add";
}
active方法的入参 accountId,如果请求中有名为 accountId的参数,则会进行默认绑定,不仅基本类型,javabean的属性也可以默认进行绑定;
如果需要明确绑定,使用@RequestParam。一般建议进行明确指定。
3.1 @RequestParam绑定httpRequest中参数
如:@RequestParam("accountId")
完整形式为 @RequestParam(value="accountId",required=true,defaultValue=null)
3.2 @RequestHeader绑定httpRequest头部信息
如:@RequestHeader("User-Agent")
完整形式为@RequestHeader(value="User-Agebt",required=true, defaultValue=null)
3.3 @PathVariable是用来对指定请求的URL路径里面的变量
如:@RequestMapping(value= "form/{id}/apply", method = {RequestMethod.PUT,RequestMethod.POST})
{id}在这个请求的URL里就是个变量,可以使用@PathVariable来获取
@PathVariable和@RequestParam的区别就在于:@RequestParam用来获得静态的URL请求入参
3.4 @CookieValue 绑定一个Cookie值
如:@CookieValue("loginId")
完整形式为@CookieValue(value="loginId",required=true,defaultValue=null)
3.5 @RequestBody将httpRequest的body绑定到方法参数上
3.6 @ModelAttribute有两种使用方式:
1)在方法级别,指定方法的返回值绑定到model中;
2方法参数级别,指定model中的值绑定到方法的入参上
示例如下:
@ModelAttribute("countryList")
public List<String> getCountries() {
return new ArrayList<String>();
}
@RequestMapping(value = "search", method = RequestMethod.POST)
public String searchAccount(@ModelAttribute("accountId") Long accountId) {
return "/search";
}
4、使用@ResponseBody 生成response
适用于webservice的数据交换,或ajax异步请求,text、json或者xml格式的数据交换。
例如访问:http://localhost:8080/accounts/info.htm
@RequestMapping(value = "info")
public @ResponseBody Account getAccount() {
Account a = new Account();
a.setId(123L);
a.setName("zhangsan");
return a;
}
返回数据如下:
{"name":"zhangsan","id":123}
从上面例子可以看出,使用@ResponseBody后,返回的javabean默认被序列化成json格式的数据并被写入到response body中。
@Request 和 @ReponseBody 使用了HttpMessageConverter机制。下面是HttpMessageConverter的继承体系。
常用的有如下几个:
StringHttpMessageConverter ---字符串
MappingJacksonHttpMessageConverter ----json
ByteArrayHttpMessageConverter ----字节数组
MarshallingHttpMessageConverter -----xml
5、使用模板技术生成response
适用于一般页面请求。可以使用velocityfreemarker等模板技术,在dispatcher-servlet.xml中需要设置viewResolver。
@RequestMapping("/index")
public String index(ModelMap modelMap) {
modelMap.put("name", "liucs");
return "index";
}
@RequestMapping("/index")
public String index2(Model model) {
model.addAttribute("name","liucs");
return "index";
}
@RequestMapping("/index")
public ModelAndView index3() throws Exception {
ModelAndView mav = newModelAndView("index");
mav.addObject("name","liucs");
return mav;
}
如上面代码index1和index2所示,不使用@ResponseBody注解。 返回一个String类型,这个String是ViewName, 如果是重定向,return"redirect:/index.htm".
入参可以包含ModelMap或者Model,其实这两者是一个东西,作用一样。也可以采用index3式的传统写法,返回一个ModelAndView对象。
6、数据验证
@InitBinder标注:
@InitBinder
public void myInitBinder(WebDataBinder binder){
binder.setDisallowedFields(new String[]{"id"});
}
通过在方法中声明一个BindingResult参数来启动绑定和验证
@RequestMapping("update")
public void update(@ModelAttribute("account") Account account,BindingResult bindResult) {
if(bindResult.hasErrors()){
//……
}
}
需要注意以下限制:
1、BindingResult参数必须跟在一个JavaBean参数后面
2、错误会被自动的绑定到model中,便于渲染模板时使用
3、不支持@RequestBody等类型的参数形式
7、异常处理
@ExceptionHandler