Springmvc学习总结【二】

来源:互联网 发布:维多利亚2新手国家知乎 编辑:程序博客网 时间:2024/05/22 13:28

这里写图片描述“`
1、Controller接口及其实现类
Controller是控制器/处理器接口,只有一个方法handleRequest,用于进行请求的功能处理(功能处理方法),处理完请求后返回ModelAndView对象。
如果想直接在处理器/控制器使用response向客户端写回数据,可以通过返回null来告诉DispatcherServlet我们已经写出响应了,不需要它进行视图解析。
Spring默认提供了一些Controller接口的实现类以方便我们使用,在Eclipse中选择Controller接口然后右键openType Hierarchy即可查看该类的实现类,每个类都有自己特殊的功能。

提供了【可选】的会话的串行化访问功能,即同一会话,线程同步
ModelandView.setViewNAme(“视图名”)
ModelAndView.addObject(“属性名”,属性值);

自定义适配器
springMVCSinmpleControllerHAndlerAdapter是主要的适配器,也是spring默认的适配器

首先判断handler是否实现了Controller接口,如果实现,调用Controller接口中的handleRequest方法。

处理器拦截器/控制器拦截器
SpringMVC的处理器拦截器类似于Filter用于对处理器进行预处理后处理。
常见应用场景
日志记录 权限检查 性能监控 通用行为
拦截器接口
public interface HandlerInterceptor{
//方法执行前拦截
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;
//执行后 渲染前处理
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;
//渲染后
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;
}

preHandle方法
预处理的回调方法,实现处理器的预处理,第三个参数为的处理器(本次请求要访问的Controller)
返回值true表示继续流程(如果有下一个拦截器或处理器)
false表示流程中断(如登陆失败),不会继续调用其它拦截器或处理器,此时通过response返回响应。
postHandle方法
后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView对模型数据进行处理,modelandView也可能为null。

AfterCompletion方法
整个处理完毕回调方法,即在视图渲染完毕时间回调。

拦截器适配器 HandleInterceptorAdapter适配器
可以选择实现三个方法

拦截器是单例模式,线程不安全,不管多少个用户请求都只有一个拦截器实现,可以使用ThreadLocal,与线程绑定一个线程一个ThreadLocal。

基于注释的SpringMVC
1、用于注解的配置
使用基于注解的配置可以省略很多操作。
配置

在spring中
处理器类可用 @Controller
业务逻辑可用 @Service
数据持久可用 @Repository

基于注解的Controller
使用注解后,不需要再实现特定的接口,任意一个javaBean都可以当作处理器对象,对象中任意一个方法都可以当作处理器方法。
在类上加上 @Controller 注解 表明是控制器类
方法上加上 @RequestMapping(“/url”) 注解
表示路径为url时 调用下面的方法

基于注解的Controller的返回值
1、返回ModelAndView和之前一样。
2、返回String 表示跳转的逻辑视图名字,模型可以通过参数传过来。
3、声明返回类型为void
可以通过参数获取request和response,分别使用服务器内部跳转和重定向跳转,自己来决定跳转位置。

spring 2.5中引入注解对控制器/处理器支持
@Controller 用于标识是处理器类
@RequestMapping 请求到处理器功能方法的映射规则。
@RequestParam 请求参数到处理器功能处理方法的方法参数上的绑定。
@ModelAttribute请求参数到命令对象的绑定。
@SessionAttribute用于声明session级别的属性,放置在处理器上,通常列出模型 属性对应的名称,则这些属性会会透明 的保存在session中。
@InitBinder 自定义数据绑定注册支持,用于将请求参数转换为命令对象的对应类型。

Spring3引入了更多注解 Restful风格的支持
@CookieValue
cookie数据到处理器功能处理方法的方法参数上的绑定。
@RequestHeader
请求头数据到处理器功能处理方法参数上的绑定。
@RequestBody
请求的body体的绑定
@ResponseBody
处理器功能处理方法的返回值作为响应体
@ResponseStatus
定义处理器功能处理方法/异常处理器返回的状态码和原因
@ExceptionHandler
注解式声明异常处理器;
@PathVariable
请求URI 中的模板变量部分到处理器功能处理方法的方法参数上的绑定,从而支持RESTful架构风格的URI;

7、Spring3中引入的mvc命名空间
mvc这个命名空间是在spring3中引入的,其作用是用来支持mvc的配置
需要中声明出这个命名空间及其对应的schemaLocation的值

自动注册基于注解风格的映射器和适配器
在spring2.5中是DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter

在spring3中是RequestMappingHandlerMapping和RequestMappingHandlerAdapter.同时还支持各种数据的转换器.


配置自定义的处理器拦截器






收到响应请求后直接选择相应的视图,


逻辑静态资源路径到物理静态资源路径的对应.例如:



当在web.xml中DispatcherServlet使用/ 映射的时候,会静态资源也映射了,如果配置了这个mvc标签,那么再访问静态资源的时候就转交给默认的Servlet来响应静态文件,否则报404 找不到静态资源错误。

8\、@Controller和@RequestMapping注解
1、声明处理器
@Controller
public class HelloWorldController {

}

2)映射处理器中的【功能处理方法】
@Controller
public class HelloWorldController {
@RequestMapping(“/home”)
public ModelAndView home(){
ModelAndView mv = new ModelAndView(“index”);
return mv;
}
}

表明该方法映射的url路径为/home

3)@RequestMapping也可以写在处理器类上
@RequestMapping(“/test”)
@Controller
public class HomeController {
@RequestMapping(“/home”)
public ModelAndView home(){
ModelAndView mv = new ModelAndView(“index”);
return mv;
}
}
表明该方法映射的url路径为/test/home

9.请求映射

假设浏览器发送了一个请求如下:

POST /login HTTP1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,en;q=0.8,zh;q=0.5,en-US;q=0.3
Connection: keep-alive
Cookie: JSESSIONID=DBC6367DEB1C024A836F3EA35FCFD5A2
Host: 127.0.0.1:8989
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0

username=tom&password=123

http协议的请求格式如下:

请求方法 URL 协议版本号
请求头信息
请求头信息
请求头信息
..
回车换行

请求正文

从格式中我们可以看到【请求方法、URL、请求头信息、请求正文】这四部分一般是可变的,因此我们可以把请求中的这些信息在处理器的【功能处理方法】中进行的映射,因此请求的映射分为如下几种:
URL路径映射
使用URL映射到处理器的功能处理方法;
请求方法映射限定
例如限定功能处理方法只处理GET请求;
请求参数映射限定
例如限定只处理包含username参数的请求;
请求头映射限定
例如限定只处理”Accept=application/json”的请求。

10.URL路径映射
1)普通URL路径映射
@RequestMapping(value=”/test”)
@RequestMapping(“/hello”)
注解中只出现一个参数且参数名为value的话,可以将参数名去掉
@RequestMapping(value={“/test”, “/user/hello”})
多个URL路径可以映射到同一个处理器的功能处理方法。

2)URI模板模式映射
@RequestMapping(value=”/users/{userId}”)
{XXX}占位符, 请求的URL可以是”/users/123456”或”/users/abcd”,之后可以通过@PathVariable可以提取URI模板模式中的{XXX}中的值
@RequestMapping(value=”/users/{userId}/create”)
这样也是可以的,请求的URL可以是”/users/123/create”
@RequestMapping(value=”/users/{userId}/topics/{topicId}”)
这样也是可以的,请求的URL可以是”/users/123/topics/123”

3)Ant风格的URL路径映射
@RequestMapping(value=”/users/**”)
可以匹配”/users/abc/abc”,但”/users/123”将会被【URI模板模式映射中的”/users/{userId}”模式优先映射到】
@RequestMapping(value=”/product/?”)
可匹配”/product/1”或”/product/a”,但不匹配”/product”或”/product/aa”;
?代表有且只有一个字符
@RequestMapping(value=”/product*”)
可匹配”/productabc”或”/product”,但不匹配”/productabc/abc”;
*代表0~n个字符
@RequestMapping(value=”/product/*”)
可匹配”/product/abc”,但不匹配”/productabc”;
@RequestMapping(value=”/products/**/{productId}”)
可匹配”/products/abc/abc/123”或”/products/123”,也就是Ant风格和URI模板变量风格可混用;
**代表所有的子路径

4)正则表达式风格的URL路径映射
从Spring3.0 开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式},之后通过@PathVariable可以提取{XXX:正则表达式匹配的值}中的XXX这个变量的值。

@RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}")    可以匹配"/products/123-1",但不能匹配"/products/abc-1",这样可以设计更加严格的规则。@RequestMapping(value="/user/{userId:^\\d{4}-[a-z]{2}$}")    可以匹配"/user/1234-ab"注意:\d表示数字,但是\在java的字符串中是特殊字符,所以需要再加一个\进行转义即可(参照之前js的学习文档,和java的正则几乎一致,js正则中的一个/变为java中的俩个/即可)    括号:        [abc]   查找方括号之间的任何字符。        [^abc]  查找任何不在方括号之间的字符。        [0-9]   查找任何从 0 至 9 的数字。        [a-z]   查找任何从小写 a 到小写 z 的字符。        [A-Z]   查找任何从大写 A 到大写 Z 的字符。        [A-z]   查找任何从大写 A 到小写 z 的字符。        (red|blue|green)    查找任何指定的选项。    元字符:        .   查找单个任意字符,除了换行和行结束符.如果要表示.这个字符,需要转义        \w  查找单词字符。     字母 数字 _        \W  查找非单词字符。非 字母 数字 _        \d  查找数字。        \D  查找非数字字符。        \s  查找空白字符。        \S  查找非空白字符。        \b  匹配单词边界。        \B  匹配非单词边界。        \0  查找 NUL 字符。        \n  查找换行符。        \f  查找换页符。        \r  查找回车符。        \t  查找制表符。        \v  查找垂直制表符。    量词:        n+      匹配任何包含至少一个 n 的字符串。        n*      匹配任何包含零个或多个 n 的字符串。        n?      匹配任何包含零个或一个 n 的字符串。        n{X}    匹配包含 X 个 n 的序列的字符串。        n{X,Y}  匹配包含 X 到 Y 个 n 的序列的字符串。        n{X,}   匹配包含至少 X 个 n 的序列的字符串。        n$         匹配任何结尾为 n 的字符串。        ^n      匹配任何开头为 n 的字符串。        ?=n     匹配任何其后紧接指定字符串 n 的字符串。        ?!n     匹配任何其后没有紧接指定字符串 n 的字符串。正则表达式风格的URL路径映射是一种特殊的URI模板模式映射URI模板模式映射不能指定模板变量的数据类型,如是数字还是字符串;正则表达式风格的URL路径映射,可以指定模板变量的数据类型,可以将规则写的相当复杂。

2.请求方法映射限定
一般获取数据为GET请求方法,提交表单一般为POST请求方法。但之前URL路径映射方式对任意请求方法都是接受的,因此我们需要某种方式来告诉相应的功能处理方法只处理如GET方式的请求或POST方式的请求。

@RequestMapping(value=”/user/{userId:\d+}”,method=RequestMethod.GET)
可以匹配”/user/100”,并且请求方式只能是GET

@RequestMapping(value=”/hello”, method={RequestMethod.POST,RequestMethod.GET})
可以匹配”/hello”,并且请求方式只能是POST或者GET

注意:
1、一般浏览器只支持GET、POST请求方法,如想浏览器支持PUT、DELETE 等请求方法只能模拟。(jquery中的ajax函数可以发送这些方式的请求)
2、除了GET、POST,还有HEAD、OPTIONS、PUT、DELETE、TRACE(观察servlet源码也可获知)
3、DispatcherServlet默认开启对GET、POST、PUT、DELETE、HEAD 的支持;
4、如果需要支持OPTIONS、TRACE,请添加DispatcherServlet 在web.xml 的初始化参数:dispatchOptionsRequest 和
dispatchTraceRequest 为true。(查看源码,在DispatcherServlet的父类中可以找到这个俩个属性)

3.请求参数映射限定
1)请求数据中有指定参数名
@RequestMapping(“/test”)
@Controller
public class HomeController {
@RequestMapping(params=”create”,method=RequestMethod.GET)
public ModelAndView test1(){

    return null;}@RequestMapping(params="create",method=RequestMethod.POST)public ModelAndView test2(){    return null;}

}

可以匹配的路径为:/test?create
如果是get 方式的请求则访问test1方法
如果是post方式的请求则访问test2方法

2)请求数据中没有指定参数名
@RequestMapping(params=”!create”, method=RequestMethod.GET)

3)请求数据中指定参数名=值
@RequestMapping(params=”username=tom”)

4)请求数据中指定参数名!=值
username参数名可以不出现,但是如果出现了,那么参数值一定不能等于tom
@RequestMapping(params=”username!=tom”)

5)组合使用是”且”的关系
@RequestMapping(params={“create”,”username=tom”})

4.请求头数据映射限定
1)请求头数据中有指定参数名
@RequestMapping(value=”/header/test1”, headers=”Accept”)
表示请求的URL必须为”/header/test1”且请求头中必须有Accept参数才能匹配。

@RequestMapping(value=”/header/test1”, headers=”my_test”)
表示请求的URL必须为”/header/test1”且请求头中必须有my_test参数才能匹配

2)请求头数据中没有指定参数名
@RequestMapping(value=”/header/test2”, headers=”!abc”)
表示请求的URL必须为”/header/test2”且请求头中必须没有abc参数才能匹配

3)请求头数据中指定参数名=值
@RequestMapping(value=”/header/test3”, headers=”Content-Type=application/json”)
表示请求的URL必须为”/header/test3”且请求头中必须有”Content-Type=application/json”参数即可匹配。

4)请求头数据中指定参数名!=值
@RequestMapping(value=”/header/test4”, headers=”Accept!=text/html”)
表示请求的URL必须为”/header/test4”且请求头中必须有Accept参数,但是值不等于text/html即可
例如:
@RequestMapping(value=”/test1”,headers=”Content-Type!=application/json”)
表示请求头信息中要么不出现Content-Type属性,如果出现了那么它的值一定不能等于application/json

5)组合使用是”且”的关系
@RequestMapping(value=”/header/test5”, headers={“Accept!=text/html”, “abc=123”}):
表示请求的URL必须为”/header/test5”且请求头中必须有”Accept”参数但值不等于”text/html”且请求中必须有参数”abc=123”即可匹配。

6)consumes属性和produces属性
consumes 指定处理请求的提交内容类型(消费)
@RequestMapping(value=”/test”,consumes=”application/json”)
方法仅处理请求中,Content-Type为”application/json”的情况

produces 指定返回的内容类型(生产)
@RequestMapping(value= “/test”, produces=”application/json”)
表示该功能处理方法将产生json格式的数据,此时根据请求头中的Accept进行匹配,如请求头”Accept=application/json”时即可匹配;

例如:
@RequestMapping(value=”test6”,consumes=”application/json”)
public String test6(){
System.out.println(“test6…”);
return “test”;
}

@RequestMapping(value=”test7”,produces=”application/json”)
public String test7(){
System.out.println(“test7…”);
return “test”;
}

测试类中的main函数代码:
此处我们使用Spring提供的Http客户端API创建了请求并设置了请求的Content-Type和编码并在响应体中写回了json数据
public static void main(String[] args) {

try {    String url = "http://127.0.0.1:8989/XXX/XXX";    //创建HttpRequest    ClientHttpRequest request =    new SimpleClientHttpRequestFactory().    createRequest(new URI(url), HttpMethod.POST);    //设置请求头的内容类型头和内容编码    //request.getHeaders().set("Content-Type", "application/json;charset=UTF-8");    request.getHeaders().set("Accept", "application/json");    //写出请求内容体    String jsonData = "{\"username\":\"zhang\", \"password\":\"123\"}";    request.getBody().write(jsonData.getBytes("UTF-8"));    //发送请求并得到响应    ClientHttpResponse response = request.execute();    System.out.println(response.getStatusCode());    System.out.println(response.getHeaders());} catch (Exception e) {    e.printStackTrace();} 

}

注意:在上面代码中,如果想获得响应正文中的数据,可以编写一下代码:
//得到响应体的编码方式
Charset charset = response.getHeaders().getContentType().getCharSet();
//得到响应体的内容
InputStream is = response.getBody();
byte bytes[] = new byte[(int)response.getHeaders().getContentLength()];
is.read(bytes);
String data = new String(bytes, charset);
System.out.println(“charset=”+charset);
System.out.println(“data : ” + data);

5.数据绑定

1)功能处理方法支持的”参数类型”
注意下面这些参数都可以在功能处理方法中直接声明并且没有指定顺序,spring会自动注入的
第一种
ServletRequest/HttpServletRequest 和 ServletResponse/HttpServletResponse
SpringWebMVC框架会自动帮助我们把相应的Servlet请求/响应作为参数传递过来。

第二种
InputStream/OutputStream 和 Reader/Writer
分别对应的是request.getInputStream();
response.getOutputStream();
request.getReader();
response.getWriter()。
InputStream/OutputStream 和 Reader/Writer两组不能同时使用,只能使用其中的一组。

注意://代码如下,访问的时候会报500错误,因为使用输出流,就不能再发回视图了,因为使用输出流那么就是使用了response,使用了response就是要自己处理返回给浏览器的内容,那么也就不能再让Controller返回视图了@RequestMapping("/test")public String test(InputStream in,OutputStream out){    System.out.println(in);    System.out.println(out);    return "test";}

第三种
WebRequest/NativeWebRequest
WebRequest是SpringMVC提供的统一请求访问接口,不仅仅可以访问请求相关数据(如参数区数据、请求头数据,但访问不到Cookie区数据),还可以访问会话和上下文中的数据;NativeWebRequest继承了WebRequest,并提供访问本地ServletAPI的方法。
例如:
public String webRequest(WebRequest webRequest, NativeWebRequest nativeWebRequest) {
System.out.println(webRequest.getParameter(“test”));
webRequest.setAttribute(“name”, “tom”,WebRequest.SCOPE_REQUEST);
System.out.println(webRequest.getAttribute(“name”, WebRequest.SCOPE_REQUEST));
HttpServletRequest request =
nativeWebRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response =
nativeWebRequest.getNativeResponse(HttpServletResponse.class);
return “success”;
}

webRequest.getParameter() 访问请求参数区的数据webRequest.getHeader()    访问请求头数据webRequest.setAttribute/getAttribute:到指定的作用范围内取/放属性数据,Servlet定义的三个作用范围分别使用如下常量代表:    SCOPE_REQUEST :代表请求作用范围;    SCOPE_SESSION :代表会话作用范围;    SCOPE_GLOBAL_SESSION :代表全局会话作用范围,即ServletContext上下文作用范围。 得到本地的Servlet API。nativeWebRequest.getNativeRequestnativeWebRequest.getNativeResponse

第四种
HttpSession
public String session(HttpSession session) {
System.out.println(session);
return “success”;
}
注意:session访问不是线程安全的,如果需要线程安全,需要自己手动的设置AnnotationMethodHandlerAdapter或RequestMappingHandlerAdapter的synchronizeOnSession属性为true,即可线程安全的访问session。
在spring2.5中是AnnotationMethodHandlerAdapter
在spring3中是RequestMappingHandlerAdapter.

第五种
命令/表单对象(也可以是自定义对象 例如User)
SpringMVC能够自动将请求参数绑定到功能处理方法的命令/表单对象上。

这里说的命令/表单对象并不需要实现任何接口,仅是一个拥有若干属性的POJO类对象例如:@RequestMapping(value = "/create" public String toCreateUser(HttpServletRequest request,User user) {      return null;  } 如果提交的表单(包含username和password文本域),将自动将请求参数绑定到命令对象user中去。

第六种
Model、Map、ModelMap
SpringMVC提供Model、Map或ModelMap让我们能去封装/处理模型数据。
例如:
@RequestMapping(value=”/model”)
public String test(Model m1, Map

原创粉丝点击