概述
注释配置相对于 XML 配置具备不少的优点:
它能够充分利用 Java 的反射机制获取类结构信息,这些信息能够有效减小配置的工做。如使用 JPA 注释配置 ORM 映射时,咱们就不须要指定 PO 的属性名、类型等信息,若是关系表字段和 PO 属性名、类型都一致,您甚至无需编写任务属性映射信息——由于这些信息均可以经过 Java 反射机制获取。
注释和 Java 代码位于一个文件中,而 XML 配置采用独立的配置文件,大多数配置信息在程序开发完成后都不会调整,若是配置信息和 Java 代码放在一块儿,有助于加强程序的内聚性。而采用独立的 XML 配置文件,程序员在编写一个功能时,每每须要在程序文件和配置文件中不停切换,这种思惟上的不连贯会下降开发效率。javascript
springmvc和struts是一个层次的概念,均属java web mvc框架,只是ssh中第2个s的技术。html
ssh通常意义上是指 struts,spring framework以及hibernate。这三个框架做用是不同的。
hibernate主要是用于持久层,struts主要是用于mvc,而spring主要用于aop和ioc。前端
spring mvc经常使用的注解: @Controller 、 @RequestMapping 、 @PathVariable 、 @ModelAttribute 、 @ResponseBody 、 @RequestParam 、 @SessionAttributes 、@CookieValue 、@RequestHeader 九个
@Controller
@Controller 负责注册一个bean 到spring 上下文中,bean 的ID 默认为
类名称开头字母小写,你也能够本身指定,以下
方法一:
@Controller
public class TestController {}
方法二:
@Controller("tmpController")
public class TestController {}java
@RequestMapping
1.@RequestMapping用来定义访问的URL,你能够为整个类定义一个@RequestMapping,或者为每一个方法指定一个。
把@RequestMapping放在类级别上,这可令它与方法级别上的@RequestMapping注解协同工做,取得缩小选择范围的效果。
例如:
@RequestMapping("/test")
public class TestController {}
则该类下的全部访问路径都在/test之下。程序员
2.将@RequestMapping用于整个类不是必须的,若是没有配置,全部的方法的访问路径配置将是彻底独立的,没有任何关联。web
3.完整的参数项为:@RequestMapping(value="",method ={"",""},headers={},params={"",""}),各参数说明以下:
value :String[] 设置访问地址
method: RequestMethod[]设置访问方式,字符数组,查看RequestMethod类,包括GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE,经常使用RequestMethod.GET,RequestMethod.POST。
headers:String[] headers通常结合method = RequestMethod.POST使用
params: String[] 访问参数设置,字符数组 例如:userId=idajax
4.value的配置还能够采用模版变量的形式 ,例如:@RequestMapping
(value="/owners/{ownerId}", method=RequestMethod.GET),这点将在介
绍@PathVariable中详细说明。spring
5.@RequestMapping params的补充说明,你能够经过设置参数条件来限制
访问地址,例如params="myParam=myValue"表达式,访问地址中参数只有
包含了该规定的值"myParam=myValue"才能匹配得上,相似"myParam"之类
的表达式也是支持的,表示当前请求的地址必须有该参数(参数的值能够是
任意),"!myParam"之类的表达式代表当前请求的地址不能包含具体指定的
参数"myParam"。后端
6.有一点须要注意的,若是为类定义了访问地址为*.do,*.html之类的,则
在方法级的@RequestMapping,不能再定义value值,不然会报错,例如
Java代码
@RequestMapping("/bbs.do")
public class BbsController {
@RequestMapping(params = "method=getList")
public String getList() {
return "list";
}
@RequestMapping(value= "/spList")
public String getSpecialList() {
return "splist";
}
}
如上例:/bbs.do?method=getList 能够访问到方法getList() ;而访
问/bbs.do/spList则会报错.数组
@PathVariable
1.@PathVariable用于方法中的参数,表示方法参数绑定到地址URL的模板
变量。
例如:
Java代码
@RequestMapping(value="/owners/{ownerId}",
method=RequestMethod.GET)
public String findOwner(@PathVariable String ownerId, Model
model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
return "displayOwner";
}
2.@PathVariable用于地址栏使用{xxx}模版变量时使用。
若是@RequestMapping没有定义相似"/{ownerId}" ,这种变量,则使用在
方法中@PathVariable会报错。
@ModelAttribute
1.应用于方法参数,参数能够在页面直接获取,至关于request.setAttribute(,)
2.应用于方法,将任何一个拥有返回值的方法标注上 @ModelAttribute,使其返回值将会进入到模型对象的属性列表中.
3.应用于方法参数时@ModelAttribute("xx"),须关联到Object的数据类型,基本数据类型 如:int,String不起做用。
例如:
Java代码
@ModelAttribute("items")//<——①向模型对象中添加一个名为items的属性
public List populateItems() {
List lists = new ArrayList();
lists.add("item1");
lists.add("item2");
return lists;
}
@RequestMapping(params = "method=listAllBoard")
public String listAllBoard(@ModelAttribute("currUser")User user,ModelMap model) {
bbtForumService.getAllBoard();
//<——②在此访问模型中的items属性
System.out.println("model.items:" + ((List)
model.get("items")).size());
return "listBoard";
}
在 ① 处,经过使用 @ModelAttribute 注解,populateItem() 方法将在任何请求处理方法执行前调用,Spring MVC 会将该方法返回值以“items”为名放入到隐含的模型对象属性列表中。
因此在 ② 处,咱们就能够经过 ModelMap 入参访问到 items 属性,当执行 listAllBoard() 请求处理方法时,② 处将在控制台打印出“model.items:2”的信息。固然咱们也能够在请求的视图中访问到模型对象中的 items 属性。
@ResponseBody
这个注解能够直接放在方法上,表示返回类型将会直接做为HTTP响应字节流输出(不被放置在Model,也不被拦截为视图页面名称)。能够用于ajax。
@RequestParam
@RequestParam是一个可选参数,例如:@RequestParam("id") 注解,因此它将和URL所带参数 id进行绑定,若是入参是基本数据类型(如 int、long、float 等),URL 请求参数中
必定要有对应的参数,不然将抛出org.springframework.web.util.NestedServletException 异常,提示没法将 null 转换为基本数据类型.
@RequestParam包含3个配置 @RequestParam(required = ,value="",
defaultValue = "")
required :参数是否必须,boolean类型,可选项,默认为true
value: 传递的参数名称,String类型,可选项,若是有值,对应到设置方法的参数
defaultValue:String类型,参数没有传递时为参数指定默认的值。
如:
package com.happyBKs.springmvc.handlers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("class")
@Controller
public class RPTestHandler {
String page="successrm";
@RequestMapping("student")
public String handle(@RequestParam(value="username") String un, @RequestParam(value="age",required=false, defaultValue="0") int age)
{
System.out.println("a student's request has come. username: "+un+", age: "+age);
return page;
}
}
1、基本使用,获取提交的参数
后端代码:
Java代码
前端代码:
Html代码
前端界面:
执行结果:
test1
123
能够看到spring会自动根据参数名字封装进入,咱们能够直接拿这个参数名来用
2、各类异常状况处理
一、能够对传入参数指定参数名
Java代码
错误信息:
HTTP Status 400 - Required String parameter 'aa' is not present
二、能够经过required=false或者true来要求@RequestParam配置的前端参数是否必定要传
Java代码
三、若是用@ RequestParam 注解的参数是int基本类型,可是required=false,这时若是不传参数值会报错,由于不传值,会赋值为null给int,这个不能够
Java代码
解决方法:
“Consider declaring it as object wrapper for the corresponding primitive type.”建议使用包装类型代替基本类型,如使用“Integer”代替“int”
@SessionAttributes
session管理,Spring 容许咱们有选择地指定 ModelMap 中的哪些属性须要转存到session 中,以便下一个请求属对应的 ModelMap 的属性列表中还能访问到这些属性。这一功能是经过类定义处标注 @SessionAttributes 注解来实现的。@SessionAttributes 只能声明在类上,而不能声明在方法上。
在 默认状况下,ModelMap 中的属性做用域是 request 级别是,也就是说,当本次请求结束后,ModelMap 中的属性将销毁。若是但愿在 多个请求中共享 ModelMap 中的属性,必须将其属性转存到 session 中,这样ModelMap 的属性才能够被跨请求访问。 Spring 容许咱们有选择地指定 ModelMap 中的哪些属性须要转存到 session 中,以便下一个请求属对应的ModelMap 的属性 列表中还能访问到这些属性。这一功能是经过类定义处标注 @SessionAttributes 注解来实现的。
代码:
使模型对象的特定属性具备 Session 范围的做用域
Java代码
咱们在 ② 处添加了一个 ModelMap 属性,其属性名为 currUser,而 ① 处经过 @SessionAttributes 注解将ModelMap 中名为 currUser 的属性放置到 Session 中, 因此咱们不但能够在 listBoardTopic() 请求所对应的 JSP视图页面中通 过 request.getAttribute(“currUser”) 和 session.getAttribute(“currUser”) 获 取 user 对象,还能够在下一个请求所对应的 JSP 视图页面中通 过 session.getAttribute(“currUser”) 或 ModelMap#get(“currUser”) 访问到这个属性。
这里咱们仅将一个 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”})。
2、@ModelAttribute
咱们能够在 须要访问 Session 属性的 controller 上加上 @SessionAttributes,而后在 action 须要的 User 参数上加上 @ModelAttribute,并保证二者的属性名称一致。SpringMVC 就会自动将 @SessionAttributes 定义的属性注入到 ModelMap 对象,在 setup action 的参数列表时,去
ModelMap 中取到这样的对象,再添加到参数列表。只要咱们不去调用 SessionStatus 的 setComplete() 方法,这个对象就会一直保留在 Session 中,从而实现 Session 信息的共享。
Java代码
1)Spring MVC 在调用处理方法以前,在请求线程中自动的建立一个隐含的模型对象。
2)调用全部方法级的 标注了 @ModelAttribute 的方法,并将方法返回值添加到隐含的模型对象中。
3)若是方法所在的控制器 (标记 @Controller的类)没有标记 @SessionAttributes("sessionXXX") 注释,则该处理步骤可跳过。
查看Session 中是否存在 sessionXXX 属性,若是有,将其添加到隐含的模型对象中。若是隐含的模型对象中已经存在了sessionXXX属性,则其值将会被覆盖。
如下的步骤是针对 标记@ModelAttribute("xxx") 方法入参 的
4)若是隐含的模型对象已经存在xxx属性,则将其赋值给入参,并将用户的请求消息 赋值给入参的相应属性 (PS:支持级联属性),并返回,如下的处理步骤再也不进行。
5)若是 方法所在的控制器、标记了 @SessionAttributes("xxx") 注释,则继续进行该处理步骤,不然直接进入步骤6。
查找 Session,若是没有找到 xxx 属性,则抛出异常 HttpSessionRequiredException 。
若是找到则将其赋值给入参,并将用户的请求消息 赋值给入参的相应属性 (PS:支持级联属性),并返回,如下的处理步骤再也不进行。
6)建立入参实例,并将其赋值给入参,并将用户的请求消息 赋值给入参的相应属性 (PS:支持级联属性)。至此,处理完毕。
最后
@CookieValue 获取cookie信息
@RequestHeader 获取请求的头部信息
Spring的注解:
@Service用于标注业务层组件
@Controller用于标注控制层组件(如struts中的action)
@Repository用于标注数据访问组件,即DAO组件
@Component泛指组件,当组件很差归类的时候,咱们可使用这个注解进行标注。
[java] view plain copy
component-scan标签默认状况下自动扫描指定路径下的包(含全部子包),将带有@Component、@Repository、 @Service、@Controller标签的类自动注册到spring容器。对标记了 Spring's @Required、@Autowired、JSR250's @PostConstruct、@PreDestroy、@Resource、JAX-WS's @WebServiceRef、EJB3's @EJB、JPA's @PersistenceContext、@PersistenceUnit等注解的类进行对应的操做使注解生效(包含了annotation- config标签的做用)。
@Autowired
注释,它能够对类成员变量、方法及构造函数进行标注,完成自动装配的工做 。
Spring 经过一个 BeanPostProcessor
对 @Autowired
进行解析,因此要让@Autowired
起做用必须事先在 Spring 容器中声明AutowiredAnnotationBeanPostProcessor
Bean。
@Resource
@Resource 的做用至关于 @Autowired,只不过 @Autowired 按 byType 自动注入,面@Resource 默认按 byName 自动注入罢了。@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将@Resource 注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。因此若是使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。若是既不指定 name 也不指定 type 属性,这时将经过反射机制使用 byName 自动注入策略。
Resource 注释类位于 Spring 发布包的 lib/j2ee/common-annotations.jar 类包中,所以在使用以前必须将其加入到项目的类库中。来看一个使用@Resource的例子:
JSR-250 为初始化以后/销毁以前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁以前调用。
虽然咱们能够经过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能,可是 Bean 仍是在 XML 文件中经过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,经过@Autowired 或 @Resource 为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。可否也经过注释定义 Bean,从 XML 配置文件中彻底移除 Bean 定义的配置呢?那是确定的,咱们经过 Spring 2.5 提供的@Component 注释就能够达到这个目标了。
为何 @Repository 只能标注在 DAO 类上呢?这是由于该注解的做用不仅是将类识别为 Bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。 Spring 自己提供了一个丰富的而且是与具体的数据访问技术无关的数据访问异常结构,用于封装不一样的持久层框架抛出的异常,使得异常独立于底层的框架。
Spring 2.5 在 @Repository 的基础上增长了功能相似的额外三个注解:@Component、@Service、@Constroller,它们分别用于软件系统的不一样层次:
@Component 是一个泛化的概念,仅仅表示一个组件 (Bean) ,能够做用在任何层次。
@Service 一般做用在业务层,可是目前该功能与 @Component 相同。
@Constroller 一般做用在控制层,可是目前该功能与 @Component 相同。
经过在类上使用 @Repository、@Component、@Service 和 @Constroller 注解,Spring 会自动建立相应的 BeanDefinition 对象,并注册到 ApplicationContext 中。这些类就成了 Spring 受管组件。这三个注解除了做用于不一样软件层次的类,其使用方式与 @Repository 是彻底相同的。
@Component 有一个可选的入参,用于指定 Bean 的名称,在 Boss 中,咱们就将 Bean 名称定义为“boss”。通常状况下,Bean 都是 singleton 的,须要注入 Bean 的地方仅须要经过 byType 策略就能够自动注入了,因此大可没必要指定 Bean 的名称。
在使用 @Component 注释后,Spring 容器必须启用类扫描机制以启用注释驱动 Bean 定义和注释驱动 Bean 自动注入的策略。
@Scope
spring中bean的scope属性,有以下5种类型:
singleton 表示在spring容器中的单例,经过spring容器得到该bean时老是返回惟一的实例
prototype表示每次得到bean都会生成一个新的对象
request表示在一次http请求内有效(只适用于web应用)
session表示在一个用户会话内有效(只适用于web应用)
globalSession表示在全局会话内有效(只适用于web应用)
在多数状况,咱们只会使用singleton和prototype两种scope,若是在spring配置文件内未指定scope属性,默认为singleton。 scope是prototype的状况下,同一个bean定义会返回不一样的对象。
是否有了这些 IOC 注释,咱们就能够彻底摒除原来 XML 配置的方式呢?NO。有如下几点缘由:
注释配置不必定在先天上优于 XML 配置。若是 Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整,那么注释配置优于 XML 配置;反之若是这种依赖关系会在部署时发生调整,XML 配置显然又优于注释配置,由于注释是对 Java 源代码的调整,您须要从新改写源代码并从新编译才能够实施调整。
若是 Bean 不是本身编写的类(如 JdbcTemplate、SessionFactoryBean 等),注释配置将没法实施,此时 XML 配置是惟一可用的方式。
注释配置每每是类级别的,而 XML 配置则能够表现得更加灵活。好比相比于 @Transaction 事务注释,使用 aop/tx 命名空间的事务配置更加灵活和简单。
因此在实现应用中,咱们每每须要同时使用注释配置和 XML 配置,对于类级别且不会发生变更的配置能够优先考虑注释配置;而对于那些第三方类以及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 建立和 Bean 注入以前将这两种配置方式的元信息融合在一块儿。