JavaWeb入门实战—Request&Response

介绍

Web服务器收到客户端的http请求后,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。

request和response对象分别代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了。


HttpServletResponse
HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。
response常见应用
一、向客户端输出中文数据
a、用OutputStream(字节流)发送数据:
1、response.getOutputStream().write(“中国”.getBytes());//以默认编码发送数据
2、response.getOutputStream().write("中国".getBytes("UTF-8"));//以UTF-8编码发送数据,浏览器(默认用GB2312)会出现乱码
画图描述出现该问题的原因。
解决办法:
2.1通过更改浏览器的编码方式:IE/”查看”/”编码”/”UTF-8”(不可取)
2.2通过设置响应头告知客户端编码方式:response.setHeader(“Content-type”, “text/html;charset=UTF-8”);//告知浏览器数据类型及编码
2.3通过meta标签模拟请求头:out.write("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />".getBytes());
2.4通过以下方法:response.setContentType("text/html;charset=UTF-8");

总结:程序以什么编码输出,就需要告知客户端以什么编码显示。


b、用PrintWriter(字符流)发送数据:
示例:response.getWriter().write(“中国” );有没有乱码?
原因:以默认编码发送数据 ISO-8859-1(没有中国二字编码),此时会发生乱码
解决办法:
response.setCharacterEncoding(“UTF-8”);//更改编码为UTF-8
response.setHeader(“Context-type”,”text/html;charset=UTF-8”);//告诉客户端编码方式
注意:不要忘记告诉客户端的编码方式。
由于经常改动编码,response提供了一种更简单的方式

response. setContentType(“text/html;charset=UTF-8”);其作用相当于以上两条代码。

示例代码如下:

public class ServletDemo5 extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

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

//		write2(response);
		write1(response);
	}
	
	/*
	 * 以字节方式发送中文
	 */
	private void write1(HttpServletResponse response) throws IOException {
		//通知客户端编码方式
		response.setContentType("text/html;charset=UTF-8");
		response.getOutputStream().write("中国".getBytes("UTF-8"));//默认使用系统默认编码GBK
		
	}
	
	/*
	 * 以字符方式发送中文
	 */
	private void write2(HttpServletResponse response) throws IOException {
		//通知客户端编码方式
//		response.setCharacterEncoding("UTF-8");
//		response.setHeader("Content-Type", "text/html;charset=UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();	//默认使用编码ISO-8859-1
		out.print("中国");
		out.flush();
		out.close();
	}
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

二、下载中文名称的文件

//下载文件:中文文件
public class ResponseDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//得打文件的真实路径
		ServletContext sc = getServletContext();
		String realpath = sc.getRealPath("/images/芙蓉姐姐.jpg");
		//C:\tomcat\day05\images\fr.jpg
		//构建输入流
		InputStream in = new FileInputStream(realpath);
		//截取文件名
		String filename = realpath.substring(realpath.lastIndexOf("\\")+1);
		System.out.println("文件名是:"+filename);
		//告知客户端以下载的方式
		response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"UTF-8"));//对下载的中文文件名进行编码
		//得到response的输出流
		OutputStream out = response.getOutputStream();
		int len = -1;
		byte b[] = new byte[1024];
		while((len=in.read(b))!=-1){
			out.write(b, 0, len);
		}
		in.close();
//		out.close();//容器会自动为你关闭
	}

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

		doGet(request, response);
	}

}

三、生成随机图片验证码

//生成随机图片验证码
public class ResponseDemo4 extends HttpServlet {
	private static final int WIDTH = 120; 
	private static final int HEIGHT = 25;
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//不要缓存
//		response.setHeader("Expires", "-1");
		response.setIntHeader("Expires", -1);
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");
		
//		BufferedImage  代表一副内存图片
//		Graphics  代表画笔
//		ImageIO   用户输出图片
		
		//1、创建内存图像
		BufferedImage image  = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
		//2、得到属于该图像的画笔
		Graphics g = image.getGraphics();
		//3、设置画笔颜色:画边框
		g.setColor(Color.RED);
		g.drawRect(0, 0, WIDTH, HEIGHT);//ctrl+shift+x变大写   +y
//			画背景
		g.setColor(Color.YELLOW);
		g.fillRect(1, 1, WIDTH-2, HEIGHT-2);
//			画干扰线:9
		g.setColor(Color.GREEN);
		Random r = new Random();
		for(int i=0;i<9;i++)
			g.drawLine(r.nextInt(WIDTH), r.nextInt(HEIGHT), r.nextInt(WIDTH), r.nextInt(HEIGHT));
//			画验证码:4(数字 随机的)
		g.setColor(Color.RED);
		g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 16));
		int x = 25;
		for(int i=0;i<4;i++){
			g.drawString(r.nextInt(10)+"", x, 15);
			x+=20;
		}
		//4、输出图片
		ImageIO.write(image, "JPEG", response.getOutputStream());
	}

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

		doGet(request, response);
	}

}

html页面代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>1.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>
  	<script type="text/javascript">
  		function changeImage(){
  			//得到img标签对象
  			 var imgObj = document.getElementById("image");
  			 imgObj.src=imgObj.src+"?"+new Date().getTime();
  		}
  	</script>
  	<form action="">
  		用户名:<input type="text" name="username"/><br/>
  		密码:<input type="password" name="password"/><br/>
  		验证码:<input type="text" name="code" /><img id="image" alt="" src="/day05/servlet/ResponseDemo4">
  		[<a href="javascript:changeImage()">看不清</a>]
  		<br/>
  		<input type="submit" value="登陆"/>
  		
  	</form>
    
  </body>
</html>

四、控制客户端定时刷新

public class ResponseDemo5 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		response.setHeader("Refresh", "2;URL=/day05/1.html");
		PrintWriter out = response.getWriter();
		out.print(new Random().nextInt());
	}

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

		doGet(request, response);
	}

}

五、控制客户端资源文件缓存时间

//指示客户端缓存的时间
public class ResponseDemo7 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String data = "黑马";
		response.setContentType("text/html;charset=UTF-8");
		response.setDateHeader("Expires", System.currentTimeMillis()+1*60*60*1000);
		PrintWriter out = response.getWriter();
		out.write(data);
	}

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

		doGet(request, response);
	}

}

六、请求重定向

//请求重定向:
//浏览器的行为,发出了2次请求。原理就是302、307加Location 头
public class ResponseDemo8 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.sendRedirect("/day05/regist.html");
	}

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

		doGet(request, response);
	}

}


HttpServletRequest

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

  • getRequestURL方法返回客户端发出请求时的完整URL。
  • getRequestURI方法返回请求行中的资源名部分。
  • getQueryString 方法返回请求行中的参数部分。
  • getRemoteAddr方法返回发出请求的客户机的IP地址
  • getRemoteHost方法返回发出请求的客户机的完整主机名
  • getRemotePort方法返回客户机所使用的网络端口号
  • getLocalAddr方法返回WEB服务器的IP地址。
  • getLocalName方法返回WEB服务器的主机名
  • getMethod得到客户机请求方式
获得客户机请求头
  • getHead(name)方法 
  • getHeaders(String name)方法 
  • getHeaderNames方法 
获得客户机请求参数(客户端提交的数据)
  • getParameter(name)方法
  • getParameterValues(String name)方法
  • getParameterNames方法 
  • getParameterMap方法  //做框架用,非常实用


Request常用的方法

//Request常用的方法
public class RequestDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
//		out.print("a<br/>");
//		out.print("b");
		out.print("getRequestURL="+request.getRequestURL()+"<br/>");
		out.print("getRequestURI="+request.getRequestURI()+"<br/>");
		out.print("getQueryString ="+request.getQueryString()+"<br/>");
		out.print("getRemoteAddr="+request.getRemoteAddr()+"<br/>");
		out.print("getRemoteHost="+request.getRemoteHost()+"<br/>");
		out.print("getRemotePort="+request.getRemotePort()+"<br/>");
		out.print("getMethod="+request.getMethod()+"<br/>");
	}

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

		doGet(request, response);
	}

}


获取请求消息头的值,示例代码如下:
//获取请求消息头的值
public class RequestDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//获取指定的头
		String hValue = request.getHeader("Accept-Language");
		System.out.println(hValue);
		System.out.println("----------------------------");
		//获取所有的头
		Enumeration enumers = request.getHeaderNames();
		while(enumers.hasMoreElements()){
			String headerName = (String)enumers.nextElement();
			System.out.println(headerName+"="+request.getHeader(headerName));
		}
		System.out.println("----------------------------");
		//以下获取重名的多个头的取值
//		request.getHeaders("")
	}

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

		doGet(request, response);
	}

}

获取客户端请求的参数,示例代码如下:

//获取客户端提交过来的请求参数的取值
public class RequestDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test6(request);
	}
	//getInputStream:以流的方式获取请求正文内容
	private void test6(HttpServletRequest request) throws ServletException, IOException {
		InputStream in = request.getInputStream();
		int len = -1;
		byte b[] = new byte[1024];
		while((len=in.read(b))!=-1){
			System.out.println(new String(b,0,len));
		}
	}
	//把请求数据封装到JavaBean中:专业做法:Map<String,String[]> key:请求参数的名称  value:请求参数的取值
	
	//使用Beanutils封装数据到JavaBean中的前提:请求参数的名称要与JavaBean中的属性名一致
	//BeanUtils还能进行类型转换(只限于基本数据类型)。其他类型转换的话,需要注册类型转换器
	private void test5(HttpServletRequest request) {
		User u = new User();
		Map map = request.getParameterMap();
//		for(Object o:map.entrySet()){
//			Map.Entry me = (Map.Entry)o;
//			System.out.println(me.getKey()+"="+((String[])me.getValue())[0]);
//		}
		try {
			//注册一个日期转换器
			ConvertUtils.register(new DateLocaleConverter(), Date.class);
			BeanUtils.populate(u, map);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
//		System.out.println(u.getUsername());
		System.out.println(u.getPassword());
		System.out.println(u.getAge());
		System.out.println(u.getBirthday());
		for(String s:u.getUsername())
			System.out.println(s);
	}
	//把请求数据封装到JavaBean中
	private void test4(HttpServletRequest request) {
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		User u = new User();
//		u.setUsername(username);
		u.setPassword(password);
		//保存U
	}
	//getParameterNames:获取所有的请求参数的名称
	private void test3(HttpServletRequest request) {
		Enumeration enumers = request.getParameterNames();
		while(enumers.hasMoreElements()){
			String paramName = (String)enumers.nextElement();
			System.out.println(paramName+"="+request.getParameter(paramName));
		}
		
		
		
	}
	//getParameterValues:获取一个请求参数的多个取值。如果该参数根本不存在,返回null。
	private void test2(HttpServletRequest request) {
		String values[] = request.getParameterValues("username");
		for(String s:values)
			System.out.println(s);
	}
	//getParameter:获取一个请求参数的取值。如果该参数根本不存在,返回null。如果该参数存在,但是取值为"",那就是""
	private void test1(HttpServletRequest request) {
		String nValue = request.getParameter("username");
		String pValue = request.getParameter("password");
		System.out.println(nValue);
		System.out.println(pValue);
	}

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

		doGet(request, response);
	}

}


各种表单输入项数据的获取

示例代码如下:

student.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>student.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="/day05/servlet/RequestDemo5" method="get">
    	姓名:<input type="text" name="name"/><br/>
    	密码:<input type="password" name="password"/><br/>
    	婚否:<input type="checkbox" name="married"/><br/>
    	性别:<input type="radio" name="gender" value="1" checked="checked"/>男
    		<input type="radio" name="gender" value="0"/>女<br/>
    	爱好:<input type="checkbox" name="hobby" value="eat"/>吃饭
    	<input type="checkbox" name="hobby" value="sleep"/>睡觉
    	<input type="checkbox" name="hobby" value="fr"/>看芙蓉<br/>
    	靓照:<input type="file" name="photo"/><br/>
    	故乡:<select name="address">
    		<option value="BJ">北京</option>
    		<option value="SD">山东</option>
    		<option value="HB">湖北</option>
    	</select><br/>
    	简介:<textarea name="description" rows="3" cols="55"></textarea><br/>
    	<input type="hidden" name="id" value="100">
    	<input type="submit" value="保存">
    </form>
  </body>
</html>

表单对应的Servlet代码如下:

//各种表单输入项数据的获取
public class RequestDemo4 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String name = request.getParameter("name");
		String password = request.getParameter("password");
		String married = request.getParameter("married");//对于一个checkbox,用户选了就不是null,若没有选择就是null
		String gender = request.getParameter("gender");//radio如果用户一个不选,会得到null
		String hobbies[] = request.getParameterValues("hobby");
		String address = request.getParameter("address");
		String description  =request.getParameter("description");
		System.out.println(name);
		System.out.println(password);
		System.out.println(married);
		System.out.println(gender);
		if(hobbies!=null&&hobbies.length>0){
			for(String s:hobbies){
				System.out.println(s);
			}
		}
		System.out.println(address);
		System.out.println(description);
	}

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

		doGet(request, response);
	}

}


请求参数的中文乱码问题

解决办法:浏览器是什么编码就以什么编码传送数据 

post请求方式:

request.setCharacterEncoding(“UTF-8”);//POST有效

与html或jsp页面的编码保持一致。


get请求方式(默认的字符集编码为ISO-8859-1):
new String(username.getBytes(“ISO-8859-1”),“UTF-8”);//GET方式

超链接:<a href=“/JavaWeb/RequestDemo2?name=中国”>cn</a>//GET方式
超链接中的href也是get请求,故中国二字需要urlEncoding

示例代码如下:

//解决中文请求参数值的问题
public class RequestDemo5 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test2(request);
		
	}
	
	//GET请求方式:发送数据按照ISO-8859-1
	private void test2(HttpServletRequest request)
	throws UnsupportedEncodingException {
		String name = request.getParameter("name");
		name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
		System.out.println(name);
	}
	//POST请求方式:request.setCharacterEncoding("UTF-8");//只对POST有效
	private void test1(HttpServletRequest request)
			throws UnsupportedEncodingException {
		//POST方式:页面的正文使用什么编码,就以什么编码发送中文数据
		//页面当前是UTF-8
		request.setCharacterEncoding("UTF-8");//只对POST有效
		String name = request.getParameter("name");
		System.out.println(name);
	}

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

		doGet(request, response);
	}

}


request常见应用2

request对象实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。
request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。
request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理。
setAttribute方法 
getAttribute方法  
removeAttribute方法
getAttributeNames方法

注意:这个域对象只存在转发的瞬间,只要客户端浏览器响应完毕,request、response就都没有了。


RequestDispather
表示请求分发器,它有两个方法:
forward():把请求转发给目标组件
public void forward(ServletRequest request,ServletResponse response)
             throws ServletException,java.io.IOException
include():包含目标组件的响应结果
public void include(ServletRequest request,ServletResponse response)
             throws ServletException,java.io.IOException
得到RequestDispatcher对象区别:
1、ServletContext对象的getRequestDispather(String path1)
path1必须用绝对路径,即以”/”开头,若用相对路径会抛出异常IllegalArgumentException
2、ServletRequest对象的getRequestDispatcher(String path2)
path2可以用绝对路径也可以用相对路径

总结

绝对路径的写法(都以/开头)
如果是给客户端用的,要加项目名称,否则(给服务器用的),不加项目名称
转发:getRequestDispatcher(String path)     不需要加项目名称 /servlet/Demo2
重定向:sendRedirect(String path)  需要加项目名称 /day06/servlet/Demo2
Refresh=2;URL=path   需要加项目名称 /day06/servlet/Demo2
form表单的action     需要加项目名称 /day06/servlet/Demo2
a的href:      需要加项目名称 /day06/servlet/Demo2
包含:include(String path)  不需要加项目名称 /servlet/Demo2


转发
dispatcher.forward(request,response)的处理流程:
1、清空用于存放响应正文数据的缓冲区
2、如果目标组件为Servlet或JSP,就调用它们,把它们产生的响应结果发送到客户端;如果目标组件为文件系统中的静态HTML文档,就读取文档中的数据并把它发送给客户端。
特点
1、由于forward()方法先清空用于存放响应正文数据的缓冲区,因此源组件生成的响应结果不会被发送到客户端,只有目标组件生成的响应结果才会被送到客户端。
2、如果源组件在进行请求转发之前,已经提交了响应结果(如调用了response的flush或close方法),那么forward()方法会抛出IllegalStateException。为了避免该异常,不应该在源组件中提交响应结果。

包含
include()方法的处理流程:
1、如果目标组件为Servlet或JSP,就执行它们,并把它们产生的响应正文添加到源组件的响应结果中;如果目标组件为HTML文档,就直接把文档的内容添加到源组件的响应结果中。
2、返回到源组件的服务方法中,继续执行后续代码块。
特点:
1、源组件与被包含的目标组件的输出数据都会被添加到响应结果中。
2、在目标组件中对响应状态代码或者响应头所做的修改都会被忽略。


转发和包含
一个Servlet对象无法获得另一个Servelt对象的引用;如果需要多个Servet组件共同协作(数据传递),只能使用Servelt规范为我们提供的两种方式:

  • 请求转发:Servlet(源组件)先对客户请求做一些预处理操作,然后把请求转发给其他web组件(目标组件)来完成包括生成响应结果在内的后续操作。
  • 包含:Servelt(源组件)把其他web组件(目标组件)生成的响应结果包含到自身的响应结果中。
转发和请求的共同点
  • 源组件和目标组件处理的都是同一个客户请求,源组件和目标组件共享同一个ServeltRequest和ServletResponse对象
  • 目标组件都可以为Servlet、JSP或HTML文档
  • 都依赖 javax.servlet.RequestDispatcher接口


重定向
重定向机制的运作流程

  1. 用户在浏览器端输入特定URL,请求访问服务器端的某个组件
  2. 服务器端的组件返回一个状态码为302的响应结果。
  3. 当浏览器端接收到这种响应结果后,再立即自动请求访问另一个web组件
  4. 浏览器端接收到来自另一个web组件的响应结果。
HttpServeltResponse的sendRedirect(String location)用于重定向


特点
Servlet源组件生成的响应结果不会被发送到客户端。response.sendRedirect(String location)方法一律返回状态码为302的响应结果。
如果源组件在进行重定向之前,已经提交了响应结果,会抛出IllegalStateException。为了避免异常,不应该在源组件中提交响应结果。
在Servlet源组件重定向语句后面的代码也会执行。
源组件和目标组件不共享同一个ServletRequest对象。
对于sendRedirect(String location)方法的参数,如果以“/”开头,表示相对于当前服务器根路径的URL。以“http"//”开头,表示一个完整路径。
目标组件不必是同一服务器上的同一个web应用的组件,它可以是任意一个有效网页。


请求范围
web应用范围内的共享数据作为ServeltContext对象的属性而存在(setAttribute),只要共享ServletContext对象也就共享了其数据。
请求范围内的共享数据作为ServletRequest对象的属性而存在(setAttribute),只要共享ServletRequest对象也就共享了其数据。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值