准备阶段:
<context:compnent-scan>中默认扫描的注解类型是@Component,在其基础上细化的@Repository, @Service 和 @Controller 也同样扫到;
<context:component-scan base-package="org.zachary.spring3.anno.web" />
handlerMapping:
handler:根据url通过通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法以响应请求;
定义了(比其他HandlerMapping 优先级高的)DefaultAnnotationHandlerMapping,请求来的url可以和被注解了@@RequesMapping 的值进行匹配
没有定义但是定义了其他的HandlerMapping,请求过来的 url 和注解了的@RequestMapping 里的值正好能匹配上,@Controller一样可被捕获到
——————————————————————————————————————————————————————————————
HandlerAdaptor :
如果没有注册任何 HandlerAdaptor 到容器中,那么 DispatcherServlet 将启用后备的几个默认使用的 HandlerAdaptor 实现:
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
org.springframework.web.servlet.mvc.AnnotationMethodHandlerAdaptor
如果注册了某个HandlerAdaptor,框架只会启用注册的那个,所以别忘了把其他的 HandlerAdaptor 也注册进来,除非你确保你真的只需要那一个你注册进容器的 HandlerAdaptor
————————————————————————————————————————————————————
@Controller
类级别上的注解。我们定义的类可以只是一个 javabean,不需要实现任何接口。标注了@Controller,借助 <context:component-scan>,框架就能自动识别到这就是一个 Controller,springboot是不需要的,我没有配置包扫描机制吧,所以没有额外的配置,上传一副结构图:
补:springboot不需要设置包扫描,只要保证入口类在类的上层包就行
————————————————————————————————————————————————————————————————
@RequestMapping
可加在类级别上(不是必需的),也可在方法上。如果出现在类级别上,那请求的 url 为 类级别上的 @RequestMapping + 方法级别上的 @RequestMapping,否则直接取方法级上的 @RequestMapping。
属性:value、params、method、headers
/**
* @RequestMapping 还有一个参数化 headers,它和 params 非常相似,也有两种表达式,只不过它是对
* 请求头做限制罢了。大家可以通过 telnet 或 http-client 来发类似的请求以检验。以 telnet 为例:
*
* telnet localhost 8080
* POST /contextPath/my HTTP/1.1
* Host: localhost
* hello: world # 这个就是自定义请求头,和标准的请求头的写法别无二致
* 【回车】
* 【回车】
*/
@RequestMapping(headers="hello=world", method={RequestMethod.POST})
public String cplusplus() {...}
返回值:
ModelAndView:视图和模型信息
String,代表逻辑视图名,模型数据需要以其它形式提供(如modelmap类型的参数)
返回null、框架从请求路径中提取视图信息;想返回空白页,writer.write("")
ModelMap:模型数据信息没有视图信息,根据请求路径提取视图信息
void:从请求路径中提取视图信息,模型数据以其他形式提供
补:从请求路径提取视图信息:截取请求路径中的最后一个 / 后面的内容,并去掉后缀名,剩下来的内容就是视图名。
————————————————————————————————————————————————————————————--——
@RequestParam(将请求参数绑定到方法参数)
请求参数与方法中参与名要对应,没有传递给方法则出现异常,类型不知框架借助PropertyEditor 类型转换失败,ExceptionResolver 会接手处理
@RequestParam(value = "per_page", required = false,defaultValue = "10"
@InitBinder:绑定复杂对象,类型转换、字符串对象转换==》自定义数据绑定规则
对一个 Controller 对应的 WebBinder 做定制
在整个应用中共享绑定规则,可以为 AnnotationMethodHandlerAdapter 指定一个自定义的 org.springframework.web.bind.support.WebBindingInitializer 实例,这样可以避免在每个 Controller 中都重复定义几乎相同逻辑的 @InitBinder 的初始化方法
@PathVariable(将 url template 里的参数绑定到方法参数)
是url 模板,需要和 @RequestMapping 配合起来使用,这是 Spring 3.0 之后引入的;
@PathVariable 和 @RequestParam 的区别在于:
* @PathVariable 的 url:/my/user/zhangsan/18
* @RequestParam 的 url:/my/user?nickname=zhangsan&age=18
————————————————————————————————————————------------------------------
@RequestBody(将请求正文绑定到方法参数)
/**
* 来看一个 http 请求:
* (请求行) POST /my HTTP/1.1
* (请求头) Host: localhost
* (请求头) Content-Type: text/plain
* (请求头) Content-Length: 5
*
* (请求体) hello
*
* 这里的 hello,就是请求体,也称 request message。若有请求体,则必须提供请求体的类型和长度,这些信
* 息是写在请求头里的,即 Content-Type 和 Content-Length
*/
@ResponseBody(将处理完请求后返回的对象绑定到响应正文)
HttpMessageConverter 用于将处理完请求后返回的对象序列化成字符串,该注解将告知框架对象作为响应正文返回,HttpMessageConverter 在这里起了作用,根据请求头的 Accept 头决定对象要转成什么样的String(Accept 头可以使用逗号分隔定义多个类型,用以告知服务器我只接受哪些类型的响应)
遍历Accept头中每种媒体类型,在定义的多个HttpMessageConverters中依次匹配;
匹配上使用该HttpMessageConverter(匹配到HttpMessageConverter定义的supportedMediaTypes中的第一个类型)完成序列化并响应头的Content-Type;
均匹配不上,收到406Not Acceptable响应;
————————————————————————————————————————————————————————————————
@ModelAttribute 为视图渲染提供更多的模型数据
@SessionAttributes :数据存放于session或从session中取数据
————————————————————————————————————————————————————————————————
配置:
<mvc:annotation-driven /> 会做以下几件事:
向 spring 容器中注册 DefaultAnnotationHandlerMapping。向 spring 容器中注册 AnnotationMethodHandlerAdapter。
配置一些 messageconverter。
解决了 @Controller 注解的使用前提配置,即 HandlerMapping 能够知道谁来处理请求。
<context:component-scan/>
启用了对类包进行扫描以实施注解驱动 Bean 定义的功能
启用了注解驱动自动注入的功能(即还隐式地在内部注册了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor)
因此当使用 <context:component-scan /> 后,除非需要使用PersistenceAnnotationBeanPostProcessor 和 RequiredAnnotationBeanPostProcessor 两个 Processor 的功能(例如 JPA 等),否则就可以将 <context:annotation-config /> 移除了。
<context:annotation-config /> :
向 spring 容器中注册 AutowiredAnnotationBeanPostProcessor。
向 spring 容器中注册 CommonAnnotationBeanPostProcessor。
向 spring 容器中注册 PersistenceAnnotationBeanPostProcessor。
向 spring 容器中注册 RequiredAnnotationBeanPostProcessor。
使用 <context:annotationconfig />之前,必须在 <beans> 元素中声明 context 命名空间 <context:component-scan />。<context:component-scan /> 对包进行扫描,实现注解驱动 Bean 定义。即,将 @Controller 标识的类的 bean 注册到容器中。
扩展:
@Configuration可理解为用spring的时候xml里面的<beans>标签
@Bean可理解为用spring的时候xml里面的<bean>标签