Servlet
目录
1.res,req使用方法
1.1 请求响应的流程:
注:服务器每次受到请求时,都会为这个请求开辟一个新的线程
1.2 response方法
response->HttpServletResponse(与http协议有关)
HttpServletResponse对象中常见的方法:
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletRxception,IOException{
response.sendError(int sc);//发送错误状态码,404,500
response.sendError(int sc,String msg);//发送带错误信息的状态码
response.setStatus(int sc);//发送成功的状态码,302
}
响应头相关方法:Context-Type,Refresh,Location…
- setHeader(String name,String value)//适用于单值的响应头(常用)
- addHeader(String name,String value)//适用于多值的响应头(一个名称=多个值)
- setIntHeader(String name,int value)//适用于单值的int类型的响应头
- addIntHeader(String name,int value)//适用于多值的int类型的响应头
- setDateHeader(String name,long value)//适用于单值的毫秒类型的响应头
- addDateHeader(String name,long value)//适用于多值的毫秒类型的响应头
- sendRedirect(String location)//设置重定向
response的两个流:
ServletOutputStream->用来向客户端发送字节数据–获取方法:getOutputStream()
PrintWriter->用来向客户端发送字符数据(需要设置编码)-- 获取方法:getWriter()
注:两个流不能同时使用
1.3 request方法
requset->HttpServletRequest
HttpServletResponse对象获取常见信息的方法:
request.getRemoteAddr();//获取客户端IP
request.getMethod();//获取请求方式GET/POST
request.setCharaceterEncoding(“utf-8”)//设置请求编码
请求头的相关方法:
String getHeader(String name)//适用于单值的请求头
int getIntHeader(String name)//适用于单值int类型的请求头
long getDareHeader(String name)//适用于单值毫秒类型的请求头
Enumeration getHeaders(String name)//适用于多值请求头
获取请求URL相关信息的方法:
//假设项目地址url是http://localhost:8080/hello/BServlet
String getScheme();//获取协议 ,http
String getServerName();//获取服务器名:localhost
String getServerPort();//获取服务器端口8080
String getContextPath();//获取项目名hello
String getServletPath();//获取Servlet路径
String getQueryString();//获取参数部分,即?后面的部分
String getRequestURI();//获取请求URI(项目名+Servlet路径)
String getRequestUTL();//获取请求URL(不包含参数的整个请求路径)
获取请求参数的方法(在请求体中:POST,在URL之后:GET):
String getParameter(String name)//获取指定名称的请求参数值(单值)
String[] getParameterValues(String name)//获取指定名称的请求参数值(多值)
Enumeration getParameterName();//获取所有请求参数名称
Map<String,String[]>getParameterMap()//获取所有请求参数(参数名,参数值)
2 response响应
2.1概述
response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse。在客户端发出每个请求时,服务器都会创建一个response对象,并传入给Servlet.service()方法。response对象是用来对客户端进行响应的,这说明在service()方法中使用response对象可以完成对客户端的响应工作。
response对象的功能分为以下四种:
- 设置响应头信息;
- 发送状态码;
- 设置响应正文;
- 重定向;
2.2 response响应正文
response是响应对象,向客户端输出响应正文(响应体)可以使用response的响应流,repsonse一共提供了两个响应流对象:
PrintWriter out = response.getWriter():获取字符流;
ServletOutputStream out = response.getOutputStream():获取字节流;
当然,如果响应正文内容为字符,那么使用response.getWriter(),如果响应内容是字节,例如下载时,那么可以使用response.getOutputStream()。
注意,在一个请求中,不能同时使用这两个流!也就是说,要么你使用repsonse.getWriter(),要么使用response.getOutputStream(),但不能同时使用这两个流。不然会抛出IllegalStateException异常。
2.3 字符响应流
字符编码
在使用response.getWriter()时需要注意默认字符编码为ISO-8859-1,如果希望设置字符流的字符编码为utf-8,可以使用response.setCharaceterEncoding(“utf-8”)来设置。这样可以保证输出给客户端的字符都是使用UTF-8编码的!
但客户端浏览器并不知道响应数据是什么编码的!如果希望通知客户端使用UTF-8来解读响应数据,那么还是使用response.setContentType(“text/html;charset=utf-8”)方法比较好,因为这个方法不只会调用response.setCharaceterEncoding(“utf-8”),还会设置content-type响应头,客户端浏览器会使用content-type头来解读响应数据。经常与 request.setCharaceterEncoding(“utf-8”)//设置请求编码一起使用
servlet请求之后
protected void doPost(HttpServletRequest request, HttpServletResponse response){
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
.......
}
缓冲区
response.getWriter()是PrintWriter类型,所以它有缓冲区,缓冲区的默认大小为8KB。也就是说,在响应数据没有输出8KB之前,数据都是存放在缓冲区中,而不会立刻发送到客户端。当Servlet执行结束后,服务器才会去刷新流,使缓冲区中的数据发送到客户端。
如果希望响应数据马上发送给客户端:
向流中写入大于8KB的数据;
调用response.flushBuffer()方法来手动刷新缓冲区;
2.4 设置响应头信息
可以使用response对象的setHeader()方法来设置响应头!使用该方法设置的响应头最终会发送给客户端浏览器!
response.setHeader(“content-type”, “text/html;charset=utf-8”):设置content-type响应头,该头的作用是告诉浏览器响应内容为html类型,编码为utf-8。而且同时会设置response的字符流编码为utf-8,即response.setCharaceterEncoding(“utf-8”);
response.setHeader(“Refresh”,”5; URL=http://www.baidu.com“):5秒后自动跳转到百度主页。
2.5 设置状态码及其他方法
response.setContentType(“text/html;charset=utf-8”):等同与调用response.setHeader(“content-type”, “text/html;charset=utf-8”);
response.setCharacterEncoding(“utf-8”):设置字符响应流的字符编码为utf-8;
response.setStatus(200):设置状态码;
response.sendError(404, “您要查找的资源不存在”):当发送错误状态码时,Tomcat会跳转到固定的错误页面去,但可以显示错误信息。
3 重定向
当你访问http://www.sun.com时,你会发现浏览器地址栏中的URL会变成http://www.oracle.com/us/sun/index.htm,这就是重定向了。
重定向是服务器通知浏览器去访问另一个地址,即再发出另一个请求。
3.1 完成重定向
响应码为200表示响应成功,而响应码为302表示重定向。所以完成重定向的第一步就是设置响应码为302。
因为重定向是通知浏览器再第二个请求,所以浏览器需要知道第二个请求的URL,所以完成重定向的第二步是设置Location头,指定第二个请求的URL地址。
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setStatus(302);[设置响应码为302,表示重定向]
response.setHeader("Location", "http://www.baidu.com");//设置新请求的URL
}
}
上面代码的作用是:当访问AServlet后,会通知浏览器重定向到百度主页。客户端浏览器解析到响应码为302后,就知道服务器让它重定向,所以它会马上获取响应头Location,然发出第二个请求。
3.2 便捷的重定向方式
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendRedirect("http://www.baidu.com");
}
}
response.sendRedirect()方法会设置响应头为302,以设置Location响应头。
如果要重定向的URL是在同一个服务器内,那么可以使用相对路径,例如:
public class AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendRedirect("/hello/BServlet");
}
}
重定向的URL地址为:http://localhost:8080/hello/BServlet。//hello是项目名,不需要输入package名称,重定向时的地址要加项目名,例如"/hello/BServlet"
3.3 重定向小结
- 重定向是两次请求;
- 重定向的URL可以是其他应用,不局限于当前应用,所以url中包含项目名;
- 重定向的响应头为302,并且必须要有Location响应头;
- 重定向就不要再使用response.getWriter()或response.getOutputStream()输出数据,不然可能会出现异常;
4 请求转发和请求包含
4.1 使用场景
适用场景:体格请求需要多个Servlet写作才能完成(使用的是同一个response和request)
RequestDispatcher rd = request.getRequestDispatcher("/MyServlet");
请求转发->rd.forward(request,response);//由下一个Servlet完成响应体,当前Servlet可以设置响应头
请求包含->rd.include(request,response);//由两个Servlet共同完成响应体
//请求转发例子,A转发给B
class AServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletRxception,IOException{
System.out.println("oneServlet....");//在console中执行
response.setHeader("aaa","AAA");//设置响应头
response.getWriter().print("hello one servlet ");//这句话不执行,留头不留尾,如果是include包含,则执行
request.getRequestDispatcher("/BServlet").forward(request,response);
}
}
class BServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletRxception,IOException{
response.getWriter().print("BServlet");//设置响应体
System.out.println("two servlet");//在console中执行
}
]
request域(请求转发包含时使用):
Servlet中三大域对象request,session,application(ServletContext)的方法进行传值
void setAttribute(String name,Object value)–>request.setAttribute
Object getAttribute(String name)–>request.getAttribute
void removeAttribute(String name)
4.2 请求转发与重定向的区别
- 请求转发时是一个请求一次响应,而重定向是两次请求两次响应
- 请求转发地址栏不变化(servlet之间的跳转),而重定向会显示后一个请求的地址
- 请求转发只能转发本项目中的其它Servlet,而重定向还能重定向到其它项目中
- 请求转发是服务端的行为,只需要给出转发到的Servlet路径,而重定向需要给出requestURI
- 请求转发url不需要输入项目名,而重定向要输入项目名
- 转发中数据的存取可以用request作用域:
request.setAttribute(), request.getAttribute()
,重定向是取不到request中的数据的。只能用session。
注:请求转发的效率比重定向高,在需要下一个Servlet中获取request域中的数据,必须使用转发。forward()更加高效,在可以满足需要时,尽量使用RequestDispatcher.forward()方法。
什么时候用请求转发,什么时候用URL重定向
如果需要共享参数 :请求转发
如果需要地址栏改变:重定向
如果需要跳转WEB-INF:请求转发
如果跳转外部链接:重定向
5.编码
5.1 编码使用
响应编码:
请求编码:
分给两种请求:
GET->String username = new String(request.getParmeter(“ios-8859-1”,“utf-8”))
一般不使用修改文件的方法(tomcat8之后GET默认编码为utf-8)
POST->String username = new String(request.getParmeter(“ios-8859-1”,“utf-8”))
或者在获取参数前,request.setCharacterEncoding(“utf-8”)
5.2 URL编码:
表单的类型:Content-Type=application/x-www-form-urlencoded,把url中的中文转换为%加十六进制
其不是字符吧编码,只是客户端与服务端之间传递参数的一种方式
POST请求默认使用URL编码,且tomcat会自动使用URL解码
URL编码:String username = URLEncoder.encode(username,“utf-8”);
URL解码:String username = URLDecoder.decode(username,“utf-8”);
适用场景:对链接中的中文参数,适用url解码才能使用(jsp)
5.3 路径
Servlet路径:web.xml中
转发和包含路径:以“/”开头,相对当前项目路径;不以“/”开头,则相对当前Servlet路径
重定向路径:以“/”开头,相对当前主机
页面中超链接和表单路径:与重定向相同
ServletContext获取资源路径:相对当前路径,即当前index.jsp所在目录
ClassLoader获取资源路径:相对classer目录
Class获取资源路径:以“/”开头相对于classer目录;不以“/”开头,则相对当前.class文件所在目录