WEB10-request-response篇笔记
- 格式:doc
- 大小:145.00 KB
- 文档页数:8
Request和Response详解Request 和 Response 对象起到了服务器与客户机之间的信息传递作⽤。
Request 对象⽤于接收客户端浏览器提交的数据,⽽ Response 对象的功能则是将服务器端的数据发送到客户端浏览器。
⼀、Request对象的五个集合:QueryString:⽤以获取客户端附在url地址后的查询字符串中的信息。
例如:stra=Request.QueryString ["strUserld"]Form:⽤以获取客户端在FORM表单中所输⼊的信息。
(的method属性值需要为POST)例如:stra=Request.Form["strUserld"]Cookies:⽤以获取客户端的Cookie信息。
例如:stra=Request.Cookies["strUserld"]ServerVariables:⽤以获取客户端发出的HTTP请求信息中的头信息及服务器端环境变量信息。
例如:stra=Request.ServerVariables["REMOTE_ADDR"],返回客户端IP地址ClientCertificate:⽤以获取客户端的⾝份验证信息例如:stra=Request.ClientCertificate["VALIDFORM"],对于要求安全验证的⽹站,返回有效起始⽇期。
⼆、Response对象Response对象⽤于动态响应客户端请⽰,控制发送给⽤户的信息,并将动态⽣成响应。
Response对象提供了⼀个数据集合cookie,它⽤于在写⼊cookie值。
若指定的cookie不存在,则创建它。
若存在,则将⾃动进⾏更新。
结果返回给客户端浏览器。
语法格式:Response.Cookies(CookieName)[(key)|.attribute]=value。
这⾥的CookiesName是指定的Cookie的名称,如果指定了Key,则该Cookie就是⼀个字典,Attribute属性包括Domain,Expires,HasKeys,Path,Secure。
【EasyNetQ笔记】RequestResponse、SendReceive模式Request/Response模式介绍EasyNetQ也⽀持Request/Response这种⽅式的消息模式。
适合在client/Server应⽤中执⾏,客户端发送⼀个请求到服务器,服务器然后处理请求后返回⼀个响应。
和传统的RPC机制不同,EasyNetQ request/response操作不需要url,仅仅需要简单的定义⼀对request/response消息类型。
发送同步请求var myRequest = new MyRequest{Text ="hello Server"};var response = bus.Request<MyRequest, MyResponse>(myRequest);Console.WriteLine(response.Text);发送异步请求通常来说,使⽤RequestAsync⽅法返回⼀个Task是⽐较好的选择。
var task = bus.RequestAsync<TestRequestMessage,TestResponseMessage>(request);task.ContinueWith(response =>{Console.WriteLine("Got Response:{0}",response.Result.Text);});同步响应bus.Respond<MyRequest,MyResponse>(request =>new MyResponse{ Text ="Responding to " + request.Text});Respond带有单个参数Func<TRequest, TResponse>,接收⼀个请求并返回响应。
假如你有持续很长时间的IO,应该使⽤ResponseAsync。
一、中文乱码问题1. 出现乱码的原因1) 在计算机中数据以二进制的形式进行存储的, 数据的传输也是通二进制的形式2)需要存字符,会出现字符与字节之间的转换 (输入字符读到的字符)3) 字符和字节之间如何实现转换?都是通过查码表4) 字符到字节是编码,字节到字符是解码,编码和解码用到了不同码表就会出现乱码问题2. 解决乱码1) 拿到乱码基本上都是由于解码错误导致的,解决办法,重新编码再解码2) 以后将文件交给解析器,出现乱码,首先想到是否通知别人文件的编码格式Servlet对象一旦创建就驻留在内存,Request和response对象,web容器会针对每次用户的请求创建一个request和response 请求结束,响应发给ie。
Request和response对象就会立即被销毁二、 Response 对象1. response getWriter方法获得字符流,用于向浏览器输出字符数据中文乱码问题2. 文件下载文件名中文乱码问题由于文件名是跟着 content-disposition 头发送给浏览器的凡是http头的数据都会经过 url 编码,编成全世界通用的符号,这样传输过程中才不会乱码3. 请求重定向发送 302 状态码和 location 头ie向浏览器发送了两次请求第一次直接请求资源,第二次重定向的页面地址栏是有变化4. getWriter 和 getOutputStream 不能同时使用,有冲突response的流我们不用关闭,交给web容器去管理三、 Request 对象1. request 帮助我们取获取 ie 浏览器发送给服务器的请求消息 (请求行消息头消息体)2. request 获得请求参数getParameter getParameterValues3. request 中文参数乱码问题表单提交post方式下 : request.setCharacterEncoding(“utf-8”);指定处理消息体的解码方式表单提交get方式下 :1) 手动解决乱码问题byte[] bytes = username.getBytes("iso-8859-1");String str = new String(bytes, "utf-8");2) 在 %tomcat%\conf\server.xml 中找到当前连接器元素 Connector配置URIEncoding 属性它用于指定web容器的url解码方式3)配置useBodyEncodingForURI 属性指定为 true用于让tomcat按照处理消息体的编码方式处理消息头超链接提交参数:也是使用 get 方式提交,和表单的区别是,表单提交ie自动进行url编码超链接提交,ie不进行url编码,此时我们需要将超链接中的中文参数手动进行url编码在服务器端的处理方式和表单 get 方式的处理一样4. 请求转发Servlet 负责对用户的请求做处理,处理完的结果交给jsp来做显示获得 RequestDispatcher 对象做请求转发请求转发的时候需要将处理结果存入 request 域带给 jsp请求转发的时候, web容器会清空response中的数据转发后也无法向response输入数据在Servlet中不输出任何数据,所有数据显示的事情都交给jsp请求转发forward和包含include的区别Forward的时候,web容器会清空response的数据,并且转发了,当前Servlet无法再写入数据Include的时候,web容器会让两个Servlet的数据都写入responsemvc 的过程1) 用户发送请求(提交表单,超链接)2) Servlet 做处理,将数据(响应结果)封装到 javabean对象3) 将 javabean 对象存入request域4) 请求转发给 jsp5) jsp 页面中从request域取出数据做显示Web资源访问的流程1. 客户端(IE)发送请求给服务器2. 用一个 Servlet 来响应客户的需求基本上分为两种:1) 查看数据请求转发给jsp做显示2) 用户登陆\购买商品完成某一个特定的功能结果都是成功或失败请求重定向到一个目标资源面试题:请求转发和请求重定向的区别?1) 请求重定向地址栏有变化请求转发地址栏无变化2) 请求重定向客户端向服务器发送两次请求请求转发发送一次请求3) 应用场景:一件事情做完了,应该做第二件事情了,就请求重定向 (用户登陆、购物)Servlet处理完了,让jsp做显示,用请求转发(mvc设计模式)web应用中的路径怎么写?读取web中的文件用 context 读取,路径要写相对于web应用的路径可以加’/’严禁用绝对路径,通通以”/”开头原则:就看路径是给浏览器用的还是给服务器用的,给浏览器用的,要加上web应用的名称给服务器用的,斜线即表示当前web应用1) 请求转发地址是给服务器用的 /表示web应用,不用加web应用的名称 /a.jspweb.xml文件中用到了路径给服务器用的, 不需要加web应用 /b.jsp /servlet/Servlet1 2) 请求重定向路径给浏览器,加上web应用名称 /day06/a.jsp3) 超链接路径给浏览器用的,/day06/a.jsp4) 表单的action提交路径给浏览器用的,/day06/a.jsp5) img标签的src属性路径给浏览器用的,/day06/a.jpg6) script src 给浏览器用的 /day06/js/a.js记住:路径以“/”开头,请求转发不加web应用名,其他的都要加。
Response对象:一、HttpServletResponse对象简介:http响应消息分为三个部分:状态行、响应消息、消息正文(也叫实体内容)ServletResponse接口用于创建响应消息,Servlet程序通过调用ServletResponse对象的方法可以向客户端回送基本的响应消息。
HttpServletResponse是专门用于HTTP一些的ServletResponse子接口,它用于封装Http响应消息,允许操控http协议相关的数据,包括响应头和状态码,支持Coookies和session跟踪。
HttpServletResponse也定义了一系列用于描述各种Http状态码的常量。
对于一个Servlet的每次访问请求,Servlet引擎都会创建一个用于封装HTTP请求消息的对象和一个代表HTTP响应消息的对象,然后调用此servlet对象的service()方法,并将这两个对象作为参数传递给service()方法。
在service()方法内部可调用response对象的各种方法来创建响应消息。
response对象拥有的方法:setStatus(int );设置状态码;setHeader(String name,String value);addHeader(String name,String value);状态码为200的正常响应消息,通过向客户端发送各种Http响应消息头字段,可以让浏览器执行各种特殊功能。
如让浏览器自动定时刷新,告诉浏览器以何种字符集显示网页,禁止浏览器缓存页面等。
setContentLength方法用于设置响应消息的实体内容的大小,单位为字节setContentType方法用于设置servlet输出内容的MIME类型,对于HTTP协议来说,就是设置Content-Type 响应头字段的值。
例如:发送到客户端的内容是html文本response.setContentType("text/html;charset=utf-8");==>>response.setHeader("Conte nt-type","text/html;charset=utf-8");发送到客户端的内容是jpg图片response.setContentType("image/jpeg");===>response.setHeader("content-type","ima ge/jpeg");发送到客户端的内容是xml文本response.setContentType("text/xml");===>response.setHeader("content-type","text/xml;charset=utf-8");Servlet引擎默认设置的输出内容类型是"text/plain";即普通的文本类型,而网页文档类型通常为text/html所以servlet程序中需要显式地调用setContextType方法来对此进行指定。
Request对象response对象常见属性请求和响应Express 应⽤使⽤回调函数的参数: request 和 response 对象来处理请求和响应的数据。
app.get('/', function (req, res) {// --})request 和 response 对象的具体介绍:Request 对象 - request 对象表⽰ HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。
常见属性有:1. req.app:当callback为外部⽂件时,⽤req.app访问express的实例2. req.baseUrl:获取路由当前安装的URL路径3. req.body / req.cookies:获得「请求主体」/ Cookies4. req.fresh / req.stale:判断请求是否还「新鲜」5. req.hostname / req.ip:获取主机名和IP地址6. req.originalUrl:获取原始请求URL7. req.params:获取路由的parameters8. req.path:获取请求路径9. req.protocol:获取协议类型10. req.query:获取URL的查询参数串11. req.route:获取当前匹配的路由12. req.subdomains:获取⼦域名13. req.accepts():检查可接受的请求的⽂档类型14. req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第⼀个可接受字符编码15. req.get():获取指定的HTTP请求头16. req.is():判断请求头Content-Type的MIME类型Response 对象 - response 对象表⽰ HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。
1Response代表http响应的对象1.1继承结构ServletResponse -- 通用的接口, 定义了一个response对象应该具有的功能||--HttpServletResponse 在ServletResponse基础上, 增加很多和Http协议相关的方法1.2response重要方法Http响应消息:一个状态行: HTTP/1.1 200 OK若干响应头:xxx...xxx(一个空行)响应实体内容: xxxxx设置状态码的方法!!void setStatus(int sc)void setStatus(int sc, String sm)设置响应头的方法!!void setHeader(String name, String value)void setDateHeader(String name, long date)void setIntHeader(String name, int value)void addHeader(String name, String value)void addDateHeader(String name, long date)void addIntHeader(String name, int value)设置响应实体内容的方法!!ServletOutputStream getOutputStream()!!PrintWriter getWriter()1.3response对象功能1.3.1向客户端发送数据 (!!!重点, 特别是乱码问题)getOutputStream()getWriter()◆字节流发送数据的中文乱码问题?服务器端指定了用utf-8来发送数据, 浏览器在接受数据时, 如果不指定将使用默认的平台码GBK, 编解码不一致导致乱码.解决方案:response.setHeader("Content-Type", "text/html;charset=utf-8");// 通知浏览器使用utf-8打开服务器发送过去的数据response.getOutputStream().write("中国".getBytes("utf-8"));// 指定编码为utf-8response.setHeader("Content-Type", "text/html;charset=utf-8");等价于 <=======>response.setContentType("text/html;charset=utf-8");◆字符流发送数据的中文乱码问题?利用字符流发送数据, 底层还是要转成字节. 服务器端如果不手动指定, 服务器默认会使用iso8859-1码表, 由于里面没有中文汉字, 所以服务器端发送给客户端就是一堆乱码, 客户端不管使用什么码表都无法转成正常的字符* 服务器会根据getCharacterEncoding()方法返回的编码来发送数据, 如果没有指定, 该方法默认返回iso8859-1解决方案:第一步, 需要指定服务器发送数据使用utf-8response.setCharacterEncoding("utf-8"); //通知服务器使用utf-8来发送响应实体中数据第二步: 需要指定浏览器在接收数据时也使用同一个编码来打开数据response.setHeader("Content-Type", "text/html;charset=utf-8");等价于<==>response.setContentType("text/html;charset=utf-8");需要注意的是:在通知浏览器使用什么编码接受服务器发送的数据时, 服务器很智能, 会使用相同的编码来发送数据, 所以指定服务器以什么编码发送数据的代码可以省略不写总结: 不管是字符流还是字节流, 解决乱码问题, 可以用一行代码搞定:response.setContentType("text/html;charset=xxx");get OuputStream(“中国”.getBytes(“utf-8”));getWriter.write(“中国”);response开发细节**getOutputStream()和getWriter() 这两个方法是互斥的, 在一次请求当中调用了其中的一个, 就不能再调用另一个!!!**在调用完getOutputStream()或getWriter()方法之后, 不需要手动去关闭流, 服务器会自动帮我们去关闭!!!**这两个方法获取到的流并不是指向客户端的流, 而是指向response缓冲区的流, 通过流将数据写入response缓冲区, service方法执行结束, 请求回到服务器, 由服务器将数据组织成响应消息打给浏览器!!1.3.2实现重定向 (!!重点)可以通过302状态码加上location响应头实现请求重定向response.setStatus(302);response.setHeader(“location”, “/day10/index.jsp”);上面两行代码等价于下面这一行<===>response.send Redirect(“/day10/index.jsp”);重定向的特点:两次请求, 两次响应地址栏地址会发生变化既可以实现在同一个WEB应用内部资源之间进行跳转, 也可以在不同的WEB应用或者是不同的服务器资源之间进行跳转1.3.3定时刷新可以通过refresh头实现在多少秒之后跳转指定的资源.实现代码:response.set Header(“refresh”, “3;url=/day10/index.jsp”);定时刷新的特点:两次请求, 两次响应地址栏地址会发生变化既可以实现在同一个WEB应用内部资源之间进行跳转, 也可以在不同的WEB应用或者是不同的服务器资源之间进行跳转1.3.4控制浏览器的缓存行为 (!掌握)由于不同的浏览器的缓存行为可能是不同的, 我们可以在服务器中通过设置响应头来控制浏览器的缓存行为.控制浏览器不要缓存:setDateHeader("Expires", -1);setHeader("Cache-control", "no-cache");setHeader("Pragma", "no-cache");控制浏览器缓存:setDateHeader("Expires", System.currentTimeMillis()+1000*60*60*24);setHeader("Cache-control", "max-age=60");1.4总结请求转发/请求重定向/定时刷新都可以实现资源的跳转, 区别是什么呢?➢请求转发:一次请求,一次响应 request对象是同一个地址栏不会发生变化只能用于服务器内部的资源跳转, 并且只能是同一应用中的不同资源上进行跳转, 不可用在不同应用和不同服务器中的资源跳转➢请求重定向:两次请求,两次响应 request对象不是同一个地址栏会发生变化可以用于服务器内部的资源跳转, 也可以用于不同应用和不同服务器之间的资源跳转➢定时刷新:两次请求,两次响应 request对象不是同一个地址栏会发生变化可以用于服务器内部的资源跳转, 也可以用于不同应用和不同服务器之间的资源跳转和重定向不同的是, 定时刷新可以在刷新到新的地址之间设置一个时间, 在间隔的这段时间内可以输出文本到浏览器并维系一段时间那什么时候用哪种方式进行资源的跳转呢?(1)如果是同一服务器中的同一应用内部的资源跳转:如果在跳转时, 需要通过request对象带数据到目的地, 只能用请求转发如果在跳转时, 希望地址栏地址不要发生变化, 只能用请求转发如果在跳转时, 希望地址栏地址发生变化, 只能使用重定向或定时刷新如果没有什么具体需要, 三种方式都可以, 最好使用请求转发. 可以减少访问服务器的次数, 降低服务器的压力!(2)如果是不同服务器或不同WEB应用内部的资源跳转, 只能用重定向或者定时刷新:由于重定向是立即跳转, 而定时刷新是在多少秒之后再进行跳转. 并且可以在跳转之前的时间里输出文本数据到浏览器并维系一段时间.如果跳转时, 需要指定多条秒或者是需要在跳转之前发送数据到浏览器, 只能使用定时刷新, 否则两种方式都可以!。
request和response对象常⽤⽅法request:request.getRequestURL(): 浏览器发出请求时的完整URL,包括协议主机名端⼝(如果有)"request.getRequestURI(): 浏览器发出请求的资源名部分,去掉了协议和主机名"request.getQueryString(): 请求⾏中的参数部分,只能显⽰以get⽅式发出的参数,post⽅式的看不到request.getRemoteAddr(): 浏览器所处于的客户机的IP地址request.getRemoteHost(): 浏览器所处于的客户机的主机名request.getRemotePort(): 浏览器所处于的客户机使⽤的⽹络端⼝request.getLocalAddr(): 服务器的IP地址request.getLocalName(): 服务器的主机名request.getMethod(): 得到客户机请求⽅式⼀般是GET或者POSTrequest.getParameter(): 是常见的⽅法,⽤于获取单值的参数request.getParameterValues(): ⽤于获取具有多值的参数,⽐如注册时候提交的 "hobits",可以是多选的。
request.getParameterMap(): ⽤于遍历所有的参数,并返回Map类型。
response:设置响应编码有两种⽅式1. response.setContentType("text/html; charset=UTF-8");2. response.setCharacterEncoding("UTF-8");这两种⽅式都需要在response.getWriter调⽤之前执⾏才能⽣效他们的区别在于1. response.setContentType("text/html; charset=UTF-8");不仅发送到浏览器的内容会使⽤UTF-8编码,⽽且还通知浏览器使⽤UTF-8编码⽅式进⾏显⽰。
HttpWebRequest和HttpWebResponse⽤法⼩结最近公司拓展市场异常迅猛,数周之类开出去⼏⼗套系统,虽然系统名字不⼀样,但各个内容相似。
由于时间紧迫,很多开出去的系统出现各种神奇的错误,当初虽然有记录错误⽇志,然⽽很多客户使⽤的是⾃⼰的服务器和数据库,出了问题我们并不能⽴即掌握信息,因此决定做⼀个捕获所有系统的异常并保存到⾃家数据库中。
实现思路在每个系统出写⼊报告错误代码(找个合理的理由,⽐如系统免费升级) -> ⾃家服务器接收并处理错误报告 -> 反馈⽤户(解决掉BUG就⾏,不要太声扬)基础回顾---参考msdn1.HttpWebRequest类:提供WebRequest类的Http特定的实现。
HttpWebRequest 类对 WebRequest 中定义的属性和⽅法提供⽀持,也对使⽤户能够直接与使⽤ HTTP 的服务器交互的附加属性和⽅法提供⽀持。
不要使⽤构造函数创建HttpWebRequest实例,请使⽤.WebRequest.Create(URI uriString)来创建实例,如果URI 是Http://或Https://,返回的是HttpWebRequest对象。
(建⽴请求特定URI的对象)当向资源发送数据时,GetRequestStream⽅法返回⽤于发送数据的Stream对象。
(获取请求数据的流对象) GetResponse⽅法向RequestUri属性指定的资源发出同步请求并返回包含该响应的HttpWebResponse。
(获取来⾃internet的响应)实例讲解1.远程请求并返回响应复制代码代码如下:/// <summary>/// 报告系统错误/// </summary>/// <param name="ex"></param>/// <returns></returns>public static string Sys_ReportError(Exception ex){try{//要提交表单的URI字符串string uriString = "http://localhost/Sys_ReportError.aspx";HttpContext context = HttpContext.Current;if (context == null) return string.Empty;string targetSite = ex.TargetSite.ToString();string stackTrace = ex.StackTrace;string friendlyMsg = ex.Message;string errorPage = context == null || context.Request == null ? "" : context.Request.Url.ToString();string projectName = Config.Sys_Title();//要提交的字符串数据string postString = "targetSite=" + HttpUtility.UrlEncode(targetSite);postString += "&stackTrace=" + HttpUtility.UrlEncode(stackTrace);postString += "&friendlyMsg=" + HttpUtility.UrlEncode(friendlyMsg);postString += "&errorPage=" + HttpUtility.UrlEncode(errorPage);postString += "&projectName=" + HttpUtility.UrlEncode(projectName);postString += "&key=" + "";HttpWebRequest webRequest = null;StreamWriter requestWriter = null;string responseData = "";webRequest = .WebRequest.Create(uriString) as HttpWebRequest;webRequest.Method = "POST";webRequest.ServicePoint.Expect100Continue = false;webRequest.Timeout = 1000 * 60;webRequest.ContentType = "application/x-www-form-urlencoded";//POST the data.requestWriter = new StreamWriter(webRequest.GetRequestStream());try{requestWriter.Write(postString);}catch (Exception ex2){return "连接错误";}finally{requestWriter.Close();requestWriter = null;}responseData = WebResponseGet(webRequest);webRequest = null;return responseData;}catch{return "未知错误";}}复制代码代码如下:/// <summary>/// Process the web response./// </summary>/// <param name="webRequest">The request object.</param>/// <returns>The response data.</returns>public static string WebResponseGet(HttpWebRequest webRequest){StreamReader responseReader = null;string responseData = "";try{responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());responseData = responseReader.ReadToEnd();}catch{return "连接错误";}finally{webRequest.GetResponse().GetResponseStream().Close();responseReader.Close();responseReader = null;}return responseData;}2.远程服务器读取流复制代码代码如下:_context = HttpContext.Current;Stream stream = _context.Request.InputStream; //获取当前传⼊Http输⼊流long length = stream.Length;byte[] data = _context.Request.BinaryRead((int)length);//对当前输⼊流进⾏指定字节数的⼆进制读取string strContent = Encoding.UTF8.GetString(data);//解码为UTF8编码形式的字符串代码讲解到此结束,⼀些相关补充:1.HttpWebRequest对象有⼀些相关设置属性,如Method(发送⽅式),TimeOut(请求超时时间),ContentType(Http标头的值)等等。
webwork Action中获取request, response,session对象的方法文库.txt为什么我们在讲故事的时候总要加上从前?开了一夏的花,终落得粉身碎骨,却还笑着说意义。
webwork Action 中获取request, response对象的方法import com.opensymphony.xwork.ActionSupport;importjavax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.opensymphony.webwork.ServletActionContext;import com.opensymphony.xwork.ActionContext;ActionContext ctx = ActionContext.getContext();HttpServletRequest request = (HttpServletRequest)ctx.get(ServletActionContext.HTTP_REQUEST);HttpServletResponse response = (HttpServletResponse)ctx.get(ServletActionContext.HTTP_RESPONSE);//ServletActionContext.APPLICATION;//ServletActionContext.SESSION;//ServletActionContext.PAGE_CONTEXT;在webwork2的action里取request.getParameter参数webwork的action已经脱离的request,是用getXxx()来取提交过来的参数如果在写程序的时候特定需要自己来取Parameter可以通过以下两种方法实现第一种用ActionContext类,所有的参数都从这里ActionContext.getContext().getParameters()取他返回的是一个Map类型Map param= ActionContext.getContext().getParameters();如果有一个提交过来的username那就可以这样写param.get("username");不过这里要注意一下param.get("username")是一个String数组(为什么要返回数据我也不知道,我从weblogic窗口看到param.get("username")被out出来ng.String,忙活了半天)String value[] = (String[])param.get("username");String username = "";for(int i=0;i<value.length;i++){username +=value[i];}这样就可以得到正确的username了第二种方法是直接把request引用进来ServletActionContext.getRequest().getParameter("username") ServletActionContext.getRequest()就是httpservletrequest这个类再import com.opensymphony.webwork.ServletActionContext用起来方便些webwork的action已经脱离的request,是用getXxx()来取提交过来的参数如果在写程序的时候特定需要自己来取Parameter可以通过以下两种方法实现WebWork之Session ---------由于WebWork对request,parameter,Session和Application都进行了封装,将这些隐含的对象封装成了相应的Map,如RequestMap,ParameterMap,SessionMap和ApplicationMap,而这些Map就组成了ActionContext,因此我们通常都不再需要与request,session这些底层的对象打交道了,这也是我一开始觉得迷惑的地方,因为我找不到Session了。
第10章WEB10-requet&response篇今日任务登录系统后完成文件下载商城系统注册功能.教学导航1.1上次课内容回顾:HTTP协议:* HTTP协议请求部分:* 请求行 :请求方式请求路径协议版本* 请求头 :一个key对应一个value ,也有一个key对应多个value* Referer,User-Agent,If-Modified-Since* 请求体 :POST方式的参数.* HTTP协议响应部分:* 响应行 :协议版本状态码状态码描述* 状态码:200 302 304 404 500* 响应头 :一个key对应一个value ,也有一个key对应多个value* Location,Refresh,Last-Modified,禁用本地缓存,Content-Dispostion* 响应体 :显示到页面的内容.Servlet:服务器端程序.* 编写Servlet:* 编写一个类,实现Servlet接口.继承GenericServlet,HttpServlet.* 配置Servlet.在web.xml中配置Servlet* Servlet的执行原理:* Servlet的生命周期:* 第一次访问Servlet的时候,服务器创建一个Servlet的对象.init方法就会执行.任何一次请求服务器都会创建一个新的线程执行service方法.service的方法内部根据请求方式调用doXXX方法.当服务器关闭的时候,servlet就会被销毁.destroy方法就会执行.* Servlet的接口实现关系:* Servlet的登录的案例:* 页面提交Servlet* 获得请求参数:request.getParameter();* 封装请求参数:* 调用业务层类:* 根据处理结果作出响应:* 页面定时刷新:* ServletConfig对象:(了解)* ServletContext对象:(重要)-被多个用户共享.* 记录网站被登录的次数.* 在服务器启动的时候ServletContext就会被创建.一个WEB项目创建一个ServletContext对象.在服务器关闭的时候销毁.域对象-存的数据有作用范围.* 功能:* 1.获得文件的MIME的类型.* 2.获得全局初始化参数.* 3.存取数据-作为域对象来使用.* setAttribute(String name,String value);* getAttribute(String name);* removeAttribute(String name);* 4.读取WEB项目的文件:* getResourceAsStream(String path);* getRealPath(String path);1.2案例一:完成登录用户对他提供文件的下载的功能.1.2.1需求:之前的案例中已经完成的了一个登录的功能,登录失败后回到登录页面.登录成功以后,服务器提供多个文件的下载的链接,点击链接可以完成文件的下载的功能.1.2.2分析:1.2.2.1技术分析:【响应对象-Response对象】响应行:Response设置状态码:响应头:Response设置响应头:* 一个key对应一个value* 一个key对应多个value响应体:Response设置响应体:【response处理中文乱码】字节流:设置浏览器默认打开编码response.setHeader("Content-Type", "text/html;charset=UTF-8");中文转成字节数组编码response.getOutputStream().write("王守义".getBytes("UTF-8"));字符流:设置response的缓冲区的编码response.setCharacterEncoding("UTF-8");设置浏览器默认打开的编码.response.setHeader("Content-Type", "text/html;charset=UTF-8");response.setContentType("text/html;charset=UTF-8");相当于上面两句【文件下载】一种:超链接方式.(不推荐)* <a href=”aa.zip”>下载</a>* <a href=”1.jpg”>下载</a>二种:手动编码方式完成文件下载.* 设置两个头和一个流:* Content-Type:文件MIME的类型.* Content-Dispostion:* 文件的输入流:1.2.2.2步骤分析:之前的登录案例已经存在:登录成功跳转的页面上提供一组链接:当点击下载的链接之后,提交到Servlet:设置两个头和一个流:1.2.3代码实现:1.在页面中提供一组下载的链接:response.getWriter().println("<h2>手动编码方式下载</h2>");response.getWriter().println("<ahref='/WEB10/downloadServlet?filename=a.bmp'>a.bmp</a><br/>");response.getWriter().println("<ahref='/WEB10/downloadServlet?filename=WEB01.zip'>WEB01.zip</a>");2.编写DownloadServlet:protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {/*** 接收参数:* 设置两个头和一个流:* 文件输入流和响应的输出流对接:*/// 接收参数:get乱码 new String("中文".getBytes("ISO-8859-1"),"UTF-8");String filename = request.getParameter("filename");System.out.println(filename);// 设置两个头和一个流:// 设置Content-Type头String fileType = this.getServletContext().getMimeType(filename);response.setContentType(fileType);// 设置Content-Disposition:response.setHeader("Content-Disposition","attachment;filename="+filename);// 设置文件的输入流:String path = this.getServletContext().getRealPath("/download/"+filename); //InputStream is = new FileInputStream(path);OutputStream os = response.getOutputStream();int len = 0;byte[] b = new byte[1024];while((len = is.read(b))!=-1){os.write(b, 0, len);}is.close();}1.2.4总结:1.2.4.1中文文件名下载:中文文件在不同的浏览器中编码方式不同:IE :URL编码Firefox :Base64编码if(agent.contains("Firefox")){// 火狐浏览器filename = base64EncodeFileName(filename);}else{// IE,其他浏览器filename = URLEncoder.encode(filename, "UTF-8");}public static String base64EncodeFileName(String fileName) { BASE64Encoder base64Encoder = new BASE64Encoder();try {return "=?UTF-8?B?"+ new String(base64Encoder.encode(fileName.getBytes("UTF-8"))) + "?=";} catch (UnsupportedEncodingException e) {e.printStackTrace();throw new RuntimeException(e);}}1.3案例二:网站的注册的功能的实现:1.3.1需求:在商城的网站上完成一个注册的功能:1.3.2分析:1.3.2.1技术分析【请求对象-request对象】获得客户机信息:* getMethod(); ---获得请求方式.* getQueryString(); ---获得请求路径后的参数.* getRemoteAddr(); ---获得客户机的IP地址.* getRequestURI(); ---获得请求的路径* getRequestURL(); ---获得请求的路径* getContextPath(); ---获得工程名获得请求头* request.getHeader(“User-Agent”);* request.getHeader(“Referer”);请求参数:用来作为域对象存取值:1.3.2.2步骤分析:步骤一:设计注册页面:步骤二:点击页面中的注册的按钮:提交到Servlet中. 步骤三:在Servlet中接收参数:步骤四:封装实体中.步骤五:调用业务层.处理数据.步骤六:根据处理的结果做出响应.1.3.3代码实现:1.创建数据库create database web10;use web10;create table user(id int primary key auto_increment,username varchar(20),password varchar(20),email varchar(20),name varchar(20),sex varchar(10),birthday date,hobby varchar(50));2.接收参数:* request.getParameter(String name);* request.getParameterValues(String name);* request.getParamaterMap();3.参数接收中的乱码处理.POST乱码处理:* <form method=”post”>的时候,这种提交才是POST提交.其他的都是get.* POST方式提交的参数在请求体中.request对象在后台接收参数.request对象有缓存区.默认缓冲区的编码ISO-8859-1.* 处理方式:设置request的缓冲区的编码.* request.setCharacterEncoding(“UTF-8”);GET方式乱码处理:* GET方式提交的参数会在地址栏上显示在请求行的路径后面.浏览器就会对路径进行一次编码.将编码后内容取出来.再进行一次编码.* 处理方式:* 修改服务器提交的编码.* 采用URLEncoder 和 URLDecoder类对中文进行编码和解码.* 使用String类的构造方法:username = new String(username.getBytes("ISO-8859-1"),"UTF-8");System.out.println(username);4.数据的封装:BeanUtils.(内省技术)1.3.4总结:1.3.4.1转发和重定向的区别:【重定向】response.sendRedirect(String path); -- 完成重定向【转发】request.getRequestDispatcher(String path).forward(request,response);【区别】1.转发的地址栏不变的.重定向的地址栏发生变化的.2.转发是一次请求一次响应,重定向是两次请求两次响应.3.request域对象存取的值在转发中是有效的,在重定向无效的.4.转发的路径不需要加工程名.重定向的路径需要加工程名.1.3.4.2使用转发和重定向对登录的功能优化:使用request域保存一个值:在一次请求范围内有效的.登录失败就可以保存一个错误信息到request中在动态页面中取出这个值${msg}。