浅谈SpringMvc HttpMessageConverter
1.HttpMessageConverter是SpringMvc框架中一个重要的组件,其主要职责是对@RequestBody的解析(该注解作用就是告诉mvc,这个参数由Http的请求头,经过HttpMessageConverter解析得到)
看一下该接口
该接口的canRead方法表示其支持的Class类型,MediaType是其支持的http的ContentType类型,假如一个Http请求是Application/json,Mvc框架会去寻找支持该MediaType的Converter,然后再判断@RequestBody注解对应的class类型是否支持,如果支持,那么就交由对应的MessageConverter去解析。
另一个问题就是,这个类是解析什么呢,实际上,HttpInputMessage是指HttpServletRequest的Body的流,可以看接口。
那么Mvc框架的部分核心我们就能猜到了,一个Http请求过来,包括Header和Body,对于其中的Body的流将会被DispatcherServlet包装成SpringMvc的HttpRequest,然后委托RequestChainExecutor,经过一系列处理,最终Body的流到了HttpMessageConverter(这里不是那么准确),重点需要理解的就是一个Http请求,头部会被HttpMessageConverter获取并解析,如果找不到对应的HttpMessageConverter,Spring框架会报异常。
一般情况下,我们常见的有StringHttpMessageConverter(text/plain+String),ByteArrayHttpMessageConverter(application/octet-stream+byte[]),FormHttpMessageConverter(好几个),FastJsonHttpMessageConverter(application/json+Object)等。
如果要自定义一个HttpMessageConverter,只要继承AbstractHttpMessageConverter就可以,其中运用了模板方法,具体的逻辑组织在AbstractHttpMessageConverter中已经实现,只需要实现以下方法和构造方法就可以使用了。
该部分就是,将HttpMessage(通过容器的HttpRequest获得相关属性),首先read请求时,直接转readInternal(子类实现),如果是write响应,则先判断返回的结果类型是不是流,是流就直接构建Message响应(返回流,如果直接读取就会被消费了,流只能读一次,对应的就是Controller(MethodHandler)的返回结果),如果是其他类型,则交由实现类将JavaObject变成流。
综上所述,HttpMessageConverter就是负责将Http请求的Body与JavaObject之间进行转换,那么在哪里可以配置呢?在WebMvcConfigurationSupport的configureMessageConverters中可以配置,默认情况boot会在存在对应classPath时自动注入mvc相关配置,而关于HttpMessageConverter在不重写configureMessageConverters时默认配置一堆,一旦自定义配置了,就只支持自己定义的几个了。
关于模板方法,在AbstractXmlHttpMessageConverter中也有使用到,同样的套路,父类定义方法模板(骨架),子类实现逻辑原语。
对于一个Http请求,Tomcat(一定猜测)首先监听端口,收到请求就委托一个Thread去初始化Servlet或者执行Servlet,并通过ThreadLocal来保存HttpServletContext和HttpRequest与HttpResponse,如果去测试的话,你会发现Tomcat基于装饰器模式用RequestFacade,ResponseFacade封装了Request和Response,请求到DispatcherServlet,SpringMvc则解析请求头(可以重复解析)和请求Body,通过请求头方法类型交给doDispatch进行解析,最终交给RequestChainExecutor去执行,通过请求头得到路径交给不同的MethodHandler(Controller接口与@Controller)去处理。根据MethodHandler对应方法的注解(@RequestBody,@ResponseBody,@PathVariable等)来交给HttpMessageConverter(Body的解析)、Converter(默认的非Body的解析)、HandlerMethodArgumentResolver(报文头解析及前置处理)、HandlerMethodReturnValueHandler(方法返回参数处理)等进行Http报文和JavaObject的转换。
我实在懒得写清除细节了,截图头疼,没必要深究源码(太细节了),先搞清楚Mvc的各个组件再说。
Mvc 数据流
Http(Header+Body)-HttpMessage(Body)-HttpMessageConverter-JavaObject
(Header)-Converter+Format SPI
Mvc Controller拓展
MethodHandler+MethodHandlerInterceptor+HandlerMethodArgumentResolver+
HandlerMethodReturnValueHandler+Aspect(有些拓展基于代理)
springmvc是怎样接受websocket请求的
浏览器客户端和服务器建立起websocket的链接,最初也是http请求握手,通过httpServletRequest发送http请求到服务器,其中头部就包含需要请求websocket链接的一系列信息,大概过程如下
1.客户端请求一个链接,头部中包含如下信息
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Upgrade: WebSocket
Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5
Origin:
[8-byte security key]
2.服务器根据头部中的Sec-WebSocket-Key2,Sec-WebSocket-Key1,Upgrade,[8-byte security key] 知道客户端需要一个websocket协议链接,于是返回一个消息,包含如下头部
HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin:
WebSocket-Location: ws://example.com/demo
[16-byte hash response]
3.客户端收到消息之后,建立起websocket链接,这时就可以进行实时通信了
我们可以定义一个处理器来实现WebSocketHandler处理请求
public class MyWebSocketHandler implements WebSocketHandler{
/**
* webscoket建立好链接之后的处理函数
* @param session 当前websocket的会话id,打开一个websocket通过都会生成唯一的一个会话,可以通过该id进行发送消息到浏览器客户端
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// TODO Auto-generated method stub
}
/**
* 客户端发送服务器的消息时,的处理函数,在这里收到消息之后可以分发消息
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage? message) throws Exception {
// TODO Auto-generated method stub
}
/**
* 消息传输过程中出现的异常处理函数
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
// TODO Auto-generated method stub
}
/**
* websocket链接关闭的回调
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
// TODO Auto-generated method stub
}
/**
* 是否支持处理拆分消息,返回true返回拆分消息
*/
@Override
public boolean supportsPartialMessages() {
// TODO Auto-generated method stub
return false;
}
}
websocket的链接建立是基于http握手协议,我们可以添加一个拦截器处理握手之前和握手之后过程
public class MyHandShakeInterceptor implements HandshakeInterceptor{
/**
* 握手之前,若返回false,则不建立链接
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
MapString, Object attributes) throws Exception {
// TODO Auto-generated method stub
return true;
}
/**
* 握手之后
*/
@Override
public void afterHandshake(ServerHttpRequest requestscjgcj.comServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
// TODO Auto-generated method stub
}
}
接下来,需要我们把处理器和拦截器注册到spring websocket中
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyWebSocketHandler(), "/portfolio")//添加一个处理器还有定义处理器的处理路径
.addInterceptors(new MyHandShakeInterceptor())
.withSockJS();
}
}
在这里我们用到.withSockJS(),SockJS是spring用来处理浏览器对websocket的兼容性,目前浏览器支持websocket还不是很好,特别是IE11以下.SockJS能关键浏览器能否支持websocket来提供三种方式用于websocket请求,三种方式分别是 WebSocket, HTTP Streaming以及 HTTP Long Polling
SockJS提供了浏览器客户端的js库,在浏览器我们请求websocket就这么用
var socket = new SockJS('/whats/portfolio');//项目名称 + 处理器拦截路径名就会打开的目的websocket链接口
/**
* 建立成功的回调函数
*/
socket.onopen = function() {
console.log('open');
};
/**
* 服务器有消息返回的回调函数
*/
socket.onmessage = function(e) {
console.log('message', e.data);
};
/**
* websocket链接关闭的回调函数
*/
socket.onclose = function() {
console.log('close');
};
然后客户端发送一个消息
document.getElementById("ws").onclick = function() {
socket.send("fff");
}
服务器MyWebSocketHandler中,通过handlemessage接收消息并进行分发
/**
* 客户端发送服务器的消息时,的处理函数,在这里收到消息之后可以分发消息
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage? message) throws Exception {
//获取消息
String body = (String) message.getPayload();
//一系列的处理之后...
//发送消息
session.sendMessage(message);
}
session可以用来标注客户端id,相对于我们的httpsession,这样,如果我们想做一个精准推送和全部推送,我们可以这么做
首先在自定义的处理其中,建一个队列来存储连进来的websocketsession
public class MyWebSocketHandler implements WebSocketHandler{
private ListWebSocketSession users = new ArrayListWebSocketSession(); //存放WebSocketSession的队列
/**
* webscoket建立好链接之后的处理函数
* @param session 当前websocket的会话id,打开一个websocket通过都会生成唯一的一个会话,可以通过该id进行发送消息到浏览器客户端
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
session.getAttributes().put("userid", "xxxx");//如果有用户登录,可以把用户的id绑定到session里面,便于后面做精准推送
users.add(session); //每个链接来的客户端都把WebSocketSession保存进来
}
//...
}
然后呢,我们在接收到消息的时候,就可以直接的根据需要精准推送到用户或者全部推送了
/**
* 客户端发送服务器的消息时,的处理函数,在这里收到消息之后可以分发消息
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage? message) throws Exception {
// TODO Auto-generated method stub
for (WebSocketSession webSocketSession : users) {
//Long id = (Long) session.getAttributes().get("userid");//可以通过获取userid进行匹配,从而进行精准推送
message = new TextMessage("ggg");
webSocketSession.sendMessage(message); //全部推送
}
}
spring websocket大概的请求过程就是这样子,这是基础的请求过程,细心的同学可能发现,如果我有很多种不同的业务请求,是不是要写很多个处理器??能不能只实现一个处理器,然后由这个处理器来进行分发处理,做到类似springmvc的DispatcherServlet那样子??下次研究看看
springmvc的注解都有哪些
spring mvc常用的注解:
@Controller
@Controller 负责注册一个bean 到spring 上下文中,bean 的ID 默认为
类名称开头字母小写,你也可以自己指定,如下
方法一:
@Controller
public class TestController {}
方法二:
@Controller("tmpController")
public class TestController {}
@RequestMapping
1.@RequestMapping用来定义访问的URL,你可以为整个类定义一个
@RequestMapping,或者为每个方法指定一个。
把@RequestMapping放在类级别上,这可令它与方法级别上的
@RequestMapping注解协同工作,取得缩小选择范围的效果。
例如:
@RequestMapping("/test")
public class TestController {}
则,该类下的所有访问路径都在/test之下。
2.将@RequestMapping用于整个类不是必须的,如果没有配置,所有的方法
的访问路径配置将是完全独立的,没有任何关联。
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=id
4.value的配置还可以采用模版变量的形式 ,例如:@RequestMapping
(value="/owners/{ownerId}", method=RequestMethod.GET),这点将在介
绍@PathVariable中详细说明。
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 ListString populateItems() {
ListString lists = new ArrayListString();
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:" + ((ListString)
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类型,参数没有传递时为参数默认指定的值
@SessionAttributes session管理
Spring 允许我们有选择地指定 ModelMap 中的哪些属性需要转存到
session 中,以便下一个请求属对应的 ModelMap 的属性列表中还能访问
到这些属性。这一功能是通过类定义处标注 @SessionAttributes 注解来
实现的。@SessionAttributes 只能声明在类上,而不能声明在方法上。
例如
@SessionAttributes("currUser") // 将ModelMap 中属性名为currUser 的属性
@SessionAttributes({"attr1","attr2"})
@SessionAttributes(types = User.class)
@SessionAttributes(types = {User.class,Dept.class})
@SessionAttributes(types = {User.class,Dept.class},value={"attr1","attr2"})
@CookieValue 获取cookie信息
@RequestHeader 获取请求的头部信息
springmvc 请求头和请求体 有什么用
1. Content-Type
MediaType,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。
[html] view plain copy
类型格式:type/subtype(;parameter)? type
主类型,任意的字符串,如text,如果是*号代表所有;
subtype 子类型,任意的字符串,如html,如果是*号代表所有;
parameter 可选,一些参数,如Accept请求头的q参数, Content-Type的 charset参数。
例如: Content-Type: text/html;charset:utf-8;
常见的媒体格式类型如下:
text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
以application开头的媒体格式类型:
application/xhtml+xml :XHTML格式
application/xml : XML数据格式
application/atom+xml :Atom XML聚合格式
application/json : JSON数据格式
application/pdf :pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded : form encType=””中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
以上就是我们在日常的开发中,经常会用到的若干content-type的内容格式。
2. Spring MVC中关于关于Content-Type类型信息的使用
首先我们来看看RequestMapping中的Class定义:
[html] view plain copy
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String[] value() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
value: 指定请求的实际地址, 比如 /action/info之类。
method: 指定请求的method类型, GET、POST、PUT、DELETE等
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
params: 指定request中必须包含某些参数值是,才让该方法处理
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求
其中,consumes, produces使用content-typ信息进行过滤信息;headers中可以使用content-type进行过滤和判断。
3. 使用示例
3.1 headers
[html] view plain copy
@RequestMapping(value = "/test", method = RequestMethod.GET, headers="Referer=")
public void testHeaders(@PathVariable String ownerId, @PathVariable String petId) {
// implementation omitted
}
这里的Headers里面可以匹配所有Header里面可以出现的信息,不局限在Referer信息。
示例2
[html] view plain copy
@RequestMapping(value = "/response/ContentType", headers = "Accept=application/json")
public void response2(HttpServletResponse response) throws IOException {
//表示响应的内容区数据的媒体类型为json格式,且编码为utf-8(客户端应该以utf-8解码)
response.setContentType("application/json;charset=utf-8");
//写出响应体内容
String jsonData = "{\"username\":\"zhang\", \"password\":\"123\"}";
response.getWriter().write(jsonData);
}
服务器根据请求头“Accept=application/json”生产json数据。
当你有如下Accept头,将遵守如下规则进行应用:
①Accept:text/html,application/xml,application/json
将按照如下顺序进行produces的匹配 ①text/html ②application/xml ③application/json
②Accept:application/xml;q=0.5,application/json;q=0.9,text/html
将按照如下顺序进行produces的匹配 ①text/html ②application/json ③application/xml
参数为媒体类型的质量因子,越大则优先权越高(从0到1)
③Accept:*/*,text/*,text/html
将按照如下顺序进行produces的匹配 ①text/html ②text/* ③*/*
即匹配规则为:最明确的优先匹配。
Requests部分
Header
解释
示例
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: user@email.com
Host 指定请求的服务器的域名和端口号 Host:
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer:
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning
Responses 部分
Header
解释
示例
Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
Content-Encoding web服务器支持的返回内容压缩编码类型。 Content-Encoding: gzip
Content-Language 响应体的语言 Content-Language: en,zh
Content-Length 响应体的长度 Content-Length: 348
Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.htm
Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location:
Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic
refresh 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)
Refresh: 5; url=
Retry-After 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 Retry-After: 120
Server web服务器软件名称 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie 设置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer 指出头域在分块传输编码的尾部存在 Trailer: Max-Forwards
Transfer-Encoding 文件传输编码 Transfer-Encoding:chunked
Vary 告诉下游代理是使用缓存响应还是从原始服务器请求 Vary: *
Via 告知代理客户端响应是通过哪里发送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 警告实体可能存在的问题 Warning: 199 Miscellaneous warning
WWW-Authenticate 表明客户端请求实体应该使用的授权方案 WWW-Authenticate: Basic
3.2 params的示例
[html] view plain copy
@RequestMapping(value = "/test/{userId}", method = RequestMethod.GET, params="myParam=myValue")
public void findUser(@PathVariable String userId) {
// implementation omitted
}
仅处理请求中包含了名为“myParam”,值为“myValue”的请求,起到了一个过滤的作用。
3.3 consumes/produces
[html] view plain copy
@Controller
@RequestMapping(value = "/users", method = RequestMethod.POST, consumes="application/json", produces="application/json")
@ResponseBody
public ListUser addUser(@RequestBody User userl) {
// implementation omitted
return ListUser users;
}
方法仅处理request Content-Type为“application/json”类型的请求. produces标识==处理request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json;
4. 总结
在本文中,首先介绍了Content-Type主要支持的格式内容,然后基于@RequestMapping标注的内容介绍了主要的使用方法,其中,headers, consumes,produces,都是使用Content-Type中使用的各种媒体格式内容,可以基于这个格式内容来进行访问的控制和过滤。
spring mvc 常用注解详解
前言
现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了。不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理。
Spring mvc 介绍
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发
image.png
spring mvc 常用注解详解
@Controller
在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 等一些注解用以定义请求URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。其标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。此外我们还需要将controller注册到spring里
@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径,作用于方法上,表明该处理器的请求地址=父路径+方法上url+method,其拥有6个属性
1、 value, method;定义处理器访问的具体体质
value: 指定请求的实际地址,指定的地址可以是URI Template 模式;
method: 指定请求的method类型, GET、POST、PUT、DELETE等;
2、consumes,produces 定义处理器内容类型
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
3、params,headers 定义处理器处理类型
params: 指定request中必须包含某些参数值,才让该方法处理!
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
@PathVariable
用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。如:
@requestParam
@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),它有三个常用参数:defaultValue = "0", required = false, value = "isApp";defaultValue 表示设置默认值,required 铜过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。
@ResponseBody
作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json等)使用;
@RequestBody
该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。
spring mvc 拦截器配置
preHandle:预处理回调方法,返回值:true表示继续流程,false表示流程中断(如登录检查失败),不会继续续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
spring mvc 静态资源放问配置
image.png
spring mvc 文件上传
前端
后端
spring mvc 工作流程详解
image.png
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
如果你也对Java架构比如分布式、微服务、源码分析、性能优化、高并发高可用等技术感兴趣可以在手机上面私信我,回复「架构」二字即可免费领取一套价值3880的架构资料哦。