1、简介
request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了。
2、response
(1)、输出中文数据:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String data="中国";
response.setHeader("Content-Type","text/html;charset=UTF-8");
ServletOutputStream out = response.getOutputStream();
out.write(data.getBytes("UTF-8"));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String data="中国";
ServletOutputStream out = response.getOutputStream();
out.write("<meta http-equiv='Content-type' content='text/html;charset=UTF-8'>".getBytes());
out.write(data.getBytes("UTF-8"));
}
public void test3(HttpServletResponse response) throws IOException {
//用字符流输出数据
String data="中国";
//response.setHeader("Content-Type","text/html;charset=UTF-8");
response.setContentType("text/html;charset=UTF-8");
//response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.write(data);
}
response.setContentType("text/html;charset=UTF-8");
起到了注释掉的两行代码的作用
(2)、文件下载:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String realPath = this.getServletContext().getRealPath("/download/1.jpg");
String name = realPath.substring(realPath.lastIndexOf("\\")+1);
InputStream in =new FileInputStream(realPath);
response.setHeader("Content-Disposition","attachment;filename="+name);
byte buffer[]=new byte[1024];
int len=0;
OutputStream out = response.getOutputStream();
while((len = in.read(buffer)) >0 ){
out.write(buffer,0,len);
}
in.close();
out.close();
}
如果 文件名是中文的话,而http里面只能是ascii码,因此需要进行提前的转换
URLEncoder类
response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(name,"UTF-8"));
(3)、生成随机图片:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通知浏览器以什么样的方式接收图片
response.setHeader("Content-Type","image/jpeg");
//设置头控制浏览器不要缓存图片数据
response.setHeader("expires","-1");
//在内存中创建一副图片
BufferedImage bi = new BufferedImage(80,30, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics = (Graphics2D) bi.getGraphics();
//修改背景颜色
graphics.setColor(Color.GRAY);
graphics.fillRect(0,0,80,30);
//向图片上写数据
graphics.setColor(Color.RED);
graphics.setFont(new Font("宋体",Font.BOLD,20));
graphics.drawString(makeNum(),0,20);
//将图片写给浏览器
ImageIO.write(bi,"jpg",response.getOutputStream());
}
private String makeNum() {
Random r = new Random();
String num = r.nextInt(9999999)+"";
StringBuffer buffer = new StringBuffer();
for (int i=0;i<7-num.length();i++){
buffer.append("0");
}
return buffer.toString()+num;
}
(4)、定时刷新:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setHeader("refresh","5");
response.setHeader("Content-Type","text/html;charset=UTF-8");
response.getWriter().write("我是中国人");
}
(5)、请求重定向(尽量不用,主要用于登陆进入主页):
一个web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。- 浏览器发送两次请求
- 浏览器地址会发生改变
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//请求重定向
/*response.setStatus(302);
response.setHeader("location","/index.jsp");*/
response.sendRedirect("/index.jsp");
}
(6)、WEB开发中的地址问题:
- 一定要“/”开头,相对地址
- "/"到底是从哪里开始,看是给谁用的,如果给服务器用则代表web工程;如果是给浏览器用则代表webapps
- \\用于电脑硬盘上的地址,/用于url地址
(7)、注意事项:
getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。
Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。
Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象。
3、request
获取客户端的数据就是利用request对象(1)、获得客户机信息:
- getRequestURL方法返回客户端发出请求时的完整URL。
- getRequestURI方法返回请求行中的资源名部分。
- getQueryString 方法返回请求行中的参数部分。
- getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
- getRemoteAddr方法返回发出请求的客户机的IP地址
- getRemoteHost方法返回发出请求的客户机的完整主机名
- getRemotePort方法返回客户机所使用的网络端口号
- getLocalAddr方法返回WEB服务器的IP地址。
- getLocalName方法返回WEB服务器的主机名
- getMethod()返回客户机的请求方式
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//url是uri的子集,uri表示任何资源地址,url仅表示网络地址
System.out.println(request.getRequestURL());//得到请求url地址
System.out.println(request.getRequestURI());//得到请求的资源
}
(b)、getQueryString
http://localhost:8080/Request1? name=flx
(2)、获得客户机请求头:
- getHeader方法 :request.getHeader("Accept-Encoding") 查看支持何种压缩数据
- getHeaders方法
- getHeaderNames方法
(3)、获得客户机请求参数(客户端提交的数据):
- getParameter方法
- getParameterValues(String name)方法
- getParameterNames方法
- getParameterMap方法//常用于框架
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
System.out.println(name);
String[] names = request.getParameterValues("name");
for(int i =0 ; names!=null&& i<names.length;i++){
System.out.println(names[i]);
}
Enumeration<String> parameterNames = request.getParameterNames();
while(parameterNames.hasMoreElements()){
String s = parameterNames.nextElement();
String value = request.getParameter(s);
System.out.println(s+":"+value);
}
System.out.println("-----------------------------------------------");
//用于框架
Map<String, String[]> parameterMap = request.getParameterMap();
for(Map.Entry<String, String[]> me: parameterMap.entrySet()){
String n = me.getKey();
String[] value = me.getValue();
}
}
text、password、radio、checkbox、file、select、textarea、 hidden
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="Request4" method="post">
用户名<input type="text" name="username"><br>
密码<input type="password" name="password"><br>
性别<input type="radio" value="male" name="gender">男
<input type="radio" value="femal" name="gender">女<br>
城市
<select name="city">
<option value="BJ">北京</option>
<option value="SH">上海</option>
<option value="CQ">重庆</option>
<option value="TJ">天津</option>
</select><br>
爱好
<input type="checkbox" value="music" name="hobby">音乐
<input type="checkbox" value="sport" name="hobby">运动
<input type="checkbox" value="reading" name="hobby">看书
<input type="checkbox" value="shopping" name="hobby">购物<br>
备注<textarea rows="5" cols="60" name="beizhu"></textarea><br>
照片<input type="file" name="file"><br>
<input type="hidden" value="sss" name="name">
<input type="submit" value="提交">
</form>
</body>
</html>
Request4
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(request.getParameter("username"));
System.out.println(request.getParameter("password"));
System.out.println(request.getParameter("gender"));
System.out.println(request.getParameter("city"));
String[] hobbies = request.getParameterValues("hobby");
for(int i = 0 ;hobbies!=null&&i<hobbies.length;i++){
System.out.println(hobbies[i]);
}
System.out.print(request.getParameter("name"));
System.out.print(request.getParameter("beizhu"));
}
其中文件的上传和隐藏还没有详细讲述,会在以后说明!
注意:
if (username == null || username.trim().equals("")){
//为空操作
}else
{//不为空操作
}
②POST提交内容为中文事项
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
System.out.println(username);
response.setContentType("text/html;charset=GB2312");
PrintWriter writer = response.getWriter();
writer.write(username);
显示正常
设置request方式的编码无效,用户想不乱吗只能手工转换
String username = request.getParameter("username");
byte[] bytes = username.getBytes("iso8859-1");
username = new String(bytes,"UTF-8");
System.out.println(username);
转码过程等同于:
URIEncoding | This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, UTF-8 will be used unless the |
useBodyEncodingForURI | This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitly set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is Notes: 1) This setting is applied only to the query string of a request. Unlike |
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
URIEncoding="UTF-8" 过于固定
貌似get方式的默认编码就是utf-8,post用iso8859-1
4、request的请求转发
(1)、forward方法实现转发:
请求转发的应用场景:MVC设计模式
//转发方式1---context
this.getServletContext().getRequestDispatcher("/test.jsp").forward(request,response);
//转发方式2---request
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/test.jsp");
requestDispatcher.forward(request,response);
两种转发方式相同的效果,没有区别
- setAttribute方法
- getAttribute方法
- removeAttribute方法
- getAttributeNames方法
request.setAttribute("data",data);
this.getServletContext().getRequestDispatcher("/test.jsp").forward(request,response);
<h1>
<%
String data = (String) request.getAttribute("data");
out.write(data);
%>
</h1>
注意:
如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常。
如果在调用forward方法之前向Servlet引擎的缓冲区中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。
(2)、请求重定向与请求转发的区别:
- 请求重定向浏览器发出两次请求,两个request和response,浏览器地址栏发生变化;
- 请求转发浏览器只发送了1次请求,但是服务器有两次响应,只创建一个request和一个response,浏览器的地址没有发生变化。
一个web资源收到客户端请求后,通知浏览器去访问另外一个web资源,称之为 请求重定向。
- RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。
- 如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
- 调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
- HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。
- RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。
(3)、include方法实现转发:
- RequestDispatcher.include方法用于将RequestDispatcher对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能。
- 被包含的Servlet程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("我是网头");
}
FootServlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("我是网脚");
}
Request8:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
request.getRequestDispatcher("HeadServlet").include(request,response);
response.getWriter().write("<br>abc<br>");
request.getRequestDispatcher("FootServlet").include(request,response);
}