javaweb-day06-4&5&6 (Servlet-Request-方法、表单获取客户端中文信息、URL编码、Request容器和请求转发、RequestDispatcher.include()

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

javax.servlet.http 包 interface  HttpServletRequest  extends ServletRequest
这个接口里面的方法都是以 get 开头的获取请求头信息方法,还有几个以 is 开头的判断方法。

request 常用的方法
  • getRequestURL 方法返回客户端发出请求时的完整URL。
  • getRequestURI 方法返回请求行中的资源名部分。***
  • getQueryString 方法返回请求行中的参数部分。
  • getRemoteAddr 方法返回发出请求的客户机的IP地址。***
  • getRemoteHost 方法返回发出请求的客户机的完整主机名。
  • getRemotePort 方法返回客户机所使用的网络端口号。
  • getLocalAddr 方法返回WEB服务器的IP地址。
  • getLocalName 方法返回WEB服务器的主机名。
  • getMethod 得到客户机请求方式。***
day06 - 4 (Servlet - Request - ) - Dandelion - 油菜地

package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//在IE地址栏输入:http://localhost:8080/myday06/servlet/RequestDemo1?name=mengmei
		
		//互联网中的统一资源定位符,地址栏?前面的部分
		System.out.println(request.getRequestURL()); //http://localhost:8080/myday06/servlet/RequestDemo1
		
		//请求行:GET /myday06/servlet/RequestDemo1?name=mengmei HTTP/1.1
		System.out.println(request.getRequestURI()); //请求行中的资源名部分,/myday06/servlet/RequestDemo1
		
		//地址栏?后面的部分
		System.out.println(request.getQueryString()); //name=mengmei
		
		//客户端信息
		System.out.println(request.getRemoteAddr()); //发出请求的客户机的IP,
		
		System.out.println(request.getRemoteHost()); //发出请求的客户端主机名,
		
		System.out.println(request.getRemotePort()); //发出请求的客户端浏览器占用的网络端口号,56252
		
		System.out.println(request.getMethod()); //得到客户机的请求方式,GET
		
		//服务器信息
		System.out.println(request.getLocalAddr()); //WEB服务器的IP地址,
		
		System.out.println(request.getLocalName()); //WEB服务器的主机名,
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}


Request常用方法---map
  • 获得客户机请求头
    • getHeader ( String  name )
    • getHeaders ( String  name )
    • getHeaderNames ()
package cn.mengmei.request;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String head = request.getHeader("Accept-Encoding");
		if(head.contains("gzip")){
			//发送压缩数据
		}else{
			//发送不压缩数据
		}
		
		//获取指定名称的所有请求头的值
		Enumeration e = request.getHeaders("Accept-Encoding");
		while(e.hasMoreElements()){
			String value = (String) e.nextElement();
			System.out.println(value);
		}
		
		System.out.println("------------------------------------------");
		
		//获取所有请求头的名称和值
		e = request.getHeaderNames();
		while(e.hasMoreElements()){
			String name = (String) e.nextElement();
			String value = request.getHeader(name);
			System.out.println(name + " = " + value);
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}
在IE浏览器地址栏输入:http://localhost:8080/myday06/servlet/RequestDemo2
运行结果如下:
gzip, deflate
------------------------------------------
accept = text/html, application/xhtml+xml, */*
accept-language = zh-CN
user-agent = Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
accept-encoding = gzip, deflate
host = localhost:8080
connection = Keep-Alive



  • 获得客户机请求参数(客户端提交的数据)
    • getParameter ( String  name )
    • getParameterValues ( String  name )
    • getParameterNames ()
    • getParameterMap ()    //框架大量使用  //由于键不能重复,键是String,值是String[]
package cn.mengmei.request;

import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	//http://localhost:8080/myday06/servlet/RequestDemo3?name=mengmei&like=code&like=swim
		
		//获取指定名称参数的第一个值
		String name = request.getParameter("name");
		System.out.println(name); //mengmei
		
		System.out.println("----------------------------------------");
		
		//获取指定名称参数的所有的值
		String[] likes = request.getParameterValues("like");
		/*if(likes != null){
			for(String like : likes){
				System.out.println(like); 
			}
		}*/
		for(int i=0; likes!=null && i<likes.length; i++){
			System.out.println(likes[i]);
		}
		
		System.out.println("----------------------------------------");
		
		//获取所有的请求行参数的名称
		Enumeration e = request.getParameterNames();
		while(e.hasMoreElements()){
			String attr = (String) e.nextElement();
			System.out.println(attr);
		}
		
		System.out.println("----------------------------------------");
		
		//做框架用的比较多
		//获取请求行参数的Map集合
		Map<String,String[]> map = request.getParameterMap(); //由于键不能重复,键是String,值是String[]
		for(Map.Entry<String, String[]> me : map.entrySet()){
			String key = me.getKey();
			String[] values = me.getValue();
			System.out.println(key + "=" + Arrays.asList(values));
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}
浏览器地址栏输入: http://localhost:8080/myday06/servlet/RequestDemo3?name=mengmei&like=code&like=swim
运行结果如下:
mengmei
----------------------------------------
code
swim
----------------------------------------
name
like
----------------------------------------
name=[mengmei]
like=[code, swim]



Request 通过表单来收集用户数据 以及 常见问题:
  • 防盗链
  • 各种表单输入项数据的获取
    • text、password、radio、checkbox、
    • file、select、textarea、hidden
    • image、button    给 js 编程用
/myday06/form.html :
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>form.html</title>
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
  </head>
  
  <body>
    <form action="/myday06/servlet/RequestDemo4" method="post">
		<table>
			<tr>
				<td>用户名:</td>
				<td><input type="text" name="username"></td>
			</tr>
			<tr>
				<td>密码:</td>
				<td><input type="password" name="password"></td>
			</tr>
			<tr>
				<td>性别:</td>
				<td><input type="radio" name="gender" value="male">男
					<input type="radio" name="gender" value="female">女</td>
			</tr>
			<tr>
				<td>所在地:</td>
				<td><select name="city">
						<option value="bj">北京</option>
						<option value="sh">上海</option>
						<option value="gz">广州</option>
				</select></td>
			</tr>
			<tr>
				<td>技术:</td>
				<td><input type="checkbox" name="tec" value="html">HTML 
					<input type="checkbox" name="tec" value="css">CSS 
					<input type="checkbox" name="tec" value="javascript">javascript 
					<input type="checkbox" name="tec" value="java">Java </td>
			</tr>
			<tr>
			<td valign="top">留言板:</td>
			<td><textarea rows="5" cols="35" name="message" >Leave a message...</textarea></td>
			</tr>
			<tr>
			<td>文件:</td>
			<td><input type="file" name="file">
				<input type="hidden" name="hidInfo" value="隐藏信息"></td>
			</tr>
			<tr>
				<td colspan="2" align="center"><input type="submit" value="提 交"> <input type="reset" value="重 置"></td>
			</tr>
		</table>
	</form>
  </body>
</html>
/myday06/servlet/RequestDemo4 :
package cn.mengmei.request;

import java.io.IOException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo4 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		request.setCharacterEncoding("UTF-8");
		
		String user = request.getParameter("username");
		String pass = request.getParameter("password");
		String gender = request.getParameter("gender");
		String city = request.getParameter("city");
		String[] tecs = request.getParameterValues("tec");
		String message = request.getParameter("message");
		//以后专门有一节讲文件上传怎么处理。
		String hidInfo = request.getParameter("hidInfo");
		
		System.out.println(user);
		System.out.println(pass);
		System.out.println(gender);
		System.out.println(city);
		if(tecs != null){
			System.out.println( Arrays.asList(tecs) );
		}
		System.out.println(message);
		System.out.println(hidInfo);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}
在浏览器地址栏输入:http://localhost:8080/myday06/form.html
day06 - 4 (Servlet - Request - ) - Dandelion - 油菜地
填写表单,并点击提交按钮,服务器端就会接收到用户提交的数据,并打印如下:
mengmei
123456
female
gz
[html, css, javascript, java]
Leave a message...
隐藏信息



如何处理空数据,避免空指针异常:
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//处理空数据
public class RequestDemo5 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String username = request.getParameter("username"); //空有  null 、"" 、 "   "  这几种情况
		if(username==null || username.trim()==""){
			//代表用户没带数据过来
		}else{
			//用户带数据过来了
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}



  • 请求参数的中文乱码问题
表单是以post方式提交的情况:
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo6 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		//post方式提交
		//服务器端会接收客户端表单提交过来的数据,
		//表单是自己写的,用了哪个码表,在这里也将request设置为哪个码表,这样中文数据才可以正确接收。
		request.setCharacterEncoding("UTF-8");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
表单是以get方式提交的情况:
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo7 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		//以get方式提交,设置request的码表是解决不了中文乱码问题的
		//因为表单以get方式提交的话,request还是会用ISO-8859-1来解码的。
		//request.setCharacterEncoding("UTF-8");
		String username = request.getParameter("username");
		
		//我们只好将接收到的乱码用ISO-8859-1反编译为字节,再用和表单同样的码表将字节转成字符串。
		String user = new String(username.getBytes("iso-8859-1"),"UTF-8");
		System.out.println(user);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}

我们在接收表单提交过来的数据时候,先判断一下它是以什么方式提交的,再以对应方法解决:
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo7 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String method = request.getMethod();
		if(method.compareToIgnoreCase("get") == 0){
			String username = new String(request.getParameter("username").getBytes("iso-8859-1"), "UTF-8");
			System.out.println(username);
		}else{
			request.setCharacterEncoding("UTF-8");
			String username = request.getParameter("username");
			System.out.println(username);
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
改配置文件也可以解决中文乱码问题,在 tomcat\config\server.xml 配置文件中的 <Connector port="8080" /> 标签中添加一条属性  URIEncoding="UTF-8" 即可,但是不建议改。
还有一种方法,将  useBodyEncodingForURI 这个属性置为 "true" 的话,你为 request 设置了什么编码,连接器就默认用什么编码。这种方法更为灵活,但是同样也不建议使用。


  • URL地址的编码
如果表单中有超链接带中文参数:
<a href="/myday06/servlet/RequestDemo7?name=中国">点点</a>
这种方式提交数据,你如果还用上面反编码再解码的方式是不行的。
开发里面有一种规范:当 URL 地址后面带了中文的话,一定要经过 URL 编码。
java.net 类 URLEncoder 的方法:
staticStringencode(String s, String enc)

JSP 页面就可以嵌套这样的 java 代码:
String url = URLEncoder.encode("/myday06/servlet/RequestDemo7?name=中国", "UTF-8");
记住:凡是地址栏后面带中文参数一定要经过 URL 编码,编成 ASCII 码后再发送。



request常见应用2:(重点中的重点)
  • request对象实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。
    • 请求转发的应用场景:MVC设计模式
    • request 对象和 ServletContext 都提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。两种没有任何区别,用哪个都可以。
  • Request对象同时也是一个域对象,开发人员通过Request对象在实现转发时,把数据通过Request对象带给其他web资源处理。
    • setAttribute方法
    • getAttribute方法
    • removeAttribute方法
    • getAttributeNames方法
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo7 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String data = "abcdefg"; //产生数据后,用 JSP 排版输出给客户端。
		//this.getServletContext().setAttribute("data", data); 
		//做web工程千万不可以拿Context做容器,
		//因为Context代表工程本身,许多人会同时访问这个网站,
		//第一个人存进去一个data,第二个人又存进去一个data,
		//第二个人就把第一个人的data给覆盖掉了,
		//然后第一个人看到的数据可能是第二个人存进去的。
		
		//那么在MVC设计模式下,我们用什么把数据带给JSP呢?
		//注意:Request对象自身也是一个容器,每收到一个请求就会创建一个Request对象,
		//在请求转发时再将这个Request转发给另一个web资源,
		//在一次请求中浏览器地址栏的地址始终不会变,Request对象就始终是那一个。
		request.setAttribute("data", data);
		
		//转发方式1:
		//this.getServletContext().getRequestDispatcher("/test.jsp").forward(request, response);
		
		//转发方式2:
		request.getRequestDispatcher("/test.jsp").forward(request, response);
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
test.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'test.jsp' starting page</title>
  </head>
  
  <!--  JSP 底层是一个 Servlet,
  	请求既然是转发过来的,Request 对象就是转发过来的。
  	JSP 的几大隐式对象:
  	final javax.servlet.jsp.PageContext pageContext;
    	javax.servlet.http.HttpSession session = null;
   	final javax.servlet.ServletContext application;
    	final javax.servlet.ServletConfig config;
    	javax.servlet.jsp.JspWriter out = null;
    	final java.lang.Object page = this;
    	javax.servlet.jsp.JspWriter _jspx_out = null;
   -->

  <body>
	<h1>
		<%
			String data = (String) request.getAttribute("data");
			out.write(data);
		%>
	</h1>
</body>
</html>
浏览器地址栏输入:http://localhost:8080/myday06/servlet/RequestDemo7
显示结果:

abcdefg




请求转发的细节
  • forward 方法用于将请求转发到 RequestDispatcher 对象封装的资源。
  • 如果在调用 forward 方法之前,在 Servlet 程序中写入的部分内容已经被真正的传送到了客户端,forward 方法将抛出IllegalStateException 异常。
  • 如果在调用 forward 方法之前向 Servlet 引擎的缓冲区(response)中写入了内容,只要写入到缓冲区中的内容没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的内容将被清空,但是,已写入到 HttpServletResponse 对象中的响应头字段信息保持有效。



请求重定向和请求转发的区别
一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理,称之为 请求转发
一个web资源收到客户端请求后,通知浏览器去访问另外一个web资源,称之为请求 重定向



请求重定向和请求转发的区别(细节)
  • RequestDispatcher.forward 方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。
  • 如果传递给 HttpServletResponse.sendRedirect 方法的相对URL以 "/" 开头,它是相对于整个WEB站点的根目录(webapps目录);如果创建 RequestDispatcher 对象时指定的相对URL以 "/" 开头,它是相对于当前WEB应用程序的根目录。
  • 通用 HttpServletResponse.sendRedirect 方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发送改变,由初始的URL地址变成重定向的目标URL;调用 RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
  • HttpServletResponse.sendRedirect 方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;RequestDispatcher.forward 方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。
  • RequestDispatcher.forward 方法的调用者与被调用者之间共享相同的 Request 对象和 Response 对象,它们属于同一个访问请求和响应过程;而 HttpServletResponse.sendRedirect 方法调用者与被调用者使用各自的 Request 对象和 Response 对象,它们属于两个独立的访问请求和响应过程。



RequestDispatcher 除了 forward 方法外,还有 include 方法:
  • RequestDispatcher.include 方法用于将 RequestDispatcher 对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能。
  • 被包含的 Servlet 程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略。
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HeadServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		response.getWriter().write("这是网头。一般一个网站的网头是保持不变的!");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FootServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		response.getWriter().write("这是网脚。一般一个网站的网脚是保持不变的!");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
package cn.mengmei.request;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestDemo8 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/html;charset=UTF-8");
		
		request.getRequestDispatcher("/servlet/HeadServlet").include(request, response);
		
		response.getWriter().write("<br/>这是网页的body!可以DIY哦。<br/>");
		
		request.getRequestDispatcher("/servlet/FootServlet").include(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}



Request 作业:
  • 看Request文档,查看获取请求方式getMethod、请求资源getRequestURI、请求头getHeader、请求参数getParameter的方法。
  • 如何向客户机输出不同类型的表单,以收集客户机的数据,并在服务器端获取
  • 获取中文数据
  • 理解请求转发,以及请求转发方式中,Servlet如何把数据交给jsp显示。


练习:








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值