web学习三——request_response编程

5.request_response编程

5.1 Response对象

代表一次http响应的对象

5.1.1 设置响应行中状态码

使用
这里写图片描述
这里写图片描述

5.1.1.1关联源码

这里写图片描述
这里写图片描述

5.1.2设置响应头信息

调用 response.setHeader(name,value)
addHeader(String,String) 在原有值添加
setHeader(String,String) 替换原有值

除了以上api, 还会有 :
这里写图片描述
设置 一个 日期值
这里写图片描述
设置 一个 int值

5.1.2.1使用302+location响应头实现请求重定向

请求重定向: 访问某个资源, 某个资源 通知来访者去 定位访问 另外一个资源.
请求重定向常见的应用场景是, 登录成功的时候使用, 如果用户登录成功,那么让浏览器重新定向到网站的首页去 .
response.setStatus(302);
response.setHeader(“location”, “/day09_response/index.html”);

response.sendRedirect("/day09_response/index.html");

5.1.2.2 设置refresh头,实现定时刷新

使用refresh头实现页面定时的刷新.
方式一:

response.setHeader("refresh", "5;http://localhost:8080");

方式二:

<!-- 表示页面5秒后跳转到页面首页 -->
 <meta http-equiv="refresh" content="5;http://localhost:8080">

这里写图片描述
实际开发过程中, 使用refresh 头刷新页面, 最多 的应用场景是 一些股票的页面, 还会这样的场景,通过 http的响应头头, 在html页面中模拟这样的头. 实现 一些特殊的功能,例如 , 页面定时跳转…

5.1.2.3 使用禁止缓存的三个头通知浏览器不要缓存

浏览器 很多时候, 会对访问的资源进行缓存, 这个时候,如果访问的资源是一个 实时都会变化的页面,那么 浏览器缓存后 就看不到 实时的最新的 值了.
所以这个时候要通知 浏览器禁止缓存 一些页面 的内容.
通知浏览器 禁止缓存可以使用 如下的三个头:
Cache-control: no-cache
Pragma: no-cache
Expires: 时间值 — 只需要是当前时间值之前的值就表示 不缓存

//设置浏览器禁止缓存
		response.setHeader("cache-control", "no-cache");
		response.setHeader("pragma", "no-cache");
		response.setDateHeader("expires", -1);
		response.getWriter().print(new Date().toLocaleString());

5.1.2.4 设置编码,调用getWriter().print()

//老外喜欢用iso8859-1,西欧的编码,不支持中文
		//1.中文---二进制
//		response.setCharacterEncoding("UTF-8");
		
		//2.告诉浏览器以UTF-8的码表去解二进制数据
//		response.setContentType("text/html;charset=utf-8");
		
//以上解决乱码,可以只写一行代码即可
//由于charset=utf-8会覆盖setCharacterEncoding的编码,所以这里只调用这一行代码即可//通过<meta>标签设置http请求头   <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
		response.setContentType("text/html;charset=utf-8");
		//设置编码时,要先设置编码,再调用getWriter().print()
		response.getWriter().print("欢饮");

5.1.3 设置响应体的内容

有getWriter() ----------- 字符流
有getOutputStream() ------ 字节流

  1. 在一次请求中, 不能同时去调用getWriter和 getOutputStream . 否则出现如下异常getWriter() has already been called for this response
    为什么? 一次请求中, 不好控制 输出的先后顺序, 以及 不好控制编码问题, 所以 就 不让同时调用. 实际上就是要让两个方法 互斥.( 定义个布尔值, 然后 在 调用某个之后, 立刻将布尔值 更改下,然后 再 后面又 调用另外的 一方时,进行判断, 如果发现 布尔值 更改过, 直接抛 异常…)
  2. 一般 javaio 不用了之后要关闭, 但是 由于这里是在serlvet中, 我们调用了getOutputStream , getWriter 之后, 如果没有关闭,服务器 会检查 是否已经, 没有关, 就 会自己去关闭. 调用close的时候,应该会调用flushBuffer

5.1.4 使用contentType生成一个xml格式文件输出到浏览器

//setContentType告诉浏览器打过去的数据是什么格式的数据类型
		//需要查到xml文件对应的mime类型
    response.setContentType("application/xml");
	response.getWriter().println("<world>");
	response.getWriter().println("<china>");
	response.getWriter().println("<beijing>beijing</beijing>");
	response.getWriter().println("</china>");
	response.getWriter().println("</world>");

5.1.5 生成验证码图片

//首先需要在内存中构建一张图片出来
		BufferedImage bf=new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		
		Graphics2D graphics=(Graphics2D) bf.getGraphics();
		
		Color color=new Color(203,232,225);
		
		//设置背景颜色
		graphics.setColor(color);
		graphics.fillRect(0, 0, WIDTH, HEIGHT);
		
		String base="ABCDEFGHIJKLMN";
		Random random=new Random();
		//状态机:如果之前设置过相应属性,下次没有调用相应API时,其状态不会发生改变
		graphics.setColor(Color.RED);
		graphics.setFont(new Font("楷体",Font.BOLD,18));
		
		int m=13;
		for(int i=0;i<4;i++) {
			int index=random.nextInt(base.length());
			char charAt=base.charAt(index);
			
			//-30-------30
			int jiaodu=random.nextInt(60)-30;
			double theta=jiaodu*Math.PI/180;
			
			graphics.drawString(charAt+"", m, 15);
			graphics.rotate(theta, m, 15);
			m+=20;
		}
		
		
		for(int i=0;i<4;i++) {
			int x1=random.nextInt(WIDTH);
			int y1=random.nextInt(HEIGHT);
			int x2=random.nextInt(WIDTH);
			int y2=random.nextInt(HEIGHT);
			graphics.drawLine(x1, y1, x2, y2);
		}
		
		ImageIO.write(bf,"png",response.getOutputStream());

5.2 Request对象

Request对象代表着 一次客户端的http的请求, http请求分为请求行,请求头,请求体, 一次请求中所有的数据都会被封装在这个request对象中, 其中这个request对象是 服务器在调用Servlet的service方法的时候,传递进来的.也是就是说 服务器创建好了这个对象, 并且将所有的数据封装到了这个对象中, 所以如果要获得来自客户端请求的数据,通通找 request .
这里写图片描述

5.2.1 获取客户机信息

		String addr = request.getRemoteAddr();
		StringBuffer requestURL=request.getRequestURL();
		String requestURI=request.getRequestURI();
		String ip = request.getRemoteAddr();
		String method=request.getMethod();
		String ContextPath=request.getContextPath();

5.2.2 referer 实现资源防盗链

response.setContentType("text/html;charset=UTF-8");
		String referer=request.getHeader("referer");
		
		if(referer==null||!"http://localhost:8080/day09/1.html".equals(referer)) {
			//如果进来说明为盗链
			response.getWriter().println("盗链");
		}else {
			response.getWriter().println("点击链接进来");
		}

5.2.3 Get和post的乱码解决

获得请求的参数, 由于 get和post请求方式是不一样的, 传递的参数 会放在不同的地方. 所以 要分开去 讨论

//get()方法

String value = request.getParameter("username");
		//采用迂回的方式
		//重新将乱码的值按照ISO8859-1的编码编回去
//		byte[] bytes=value.getBytes("ISO8859-1");
		//再以UTF-8的编码进行解码
//		value=new String(bytes,"UTF-8");

//post()方法

//覆盖了请求体中的编码方式
		request.setCharacterEncoding("UTF-8");
		String value = request.getParameter("username");

5.2.4 获得复杂表单数据

form.html

<tr>
<td>性别:</td>
<td>
 <input type="radio" name="gender" value="male">男
 <input type="radio" name="gender" value="female">女
</td>
</tr>
<tr>
<td>爱好:</td>
<td>
<input type="checkbox" name="hobbies" value="游泳">游泳
<input type="checkbox" name="hobbies" value="打毛衣">打毛衣
<input type="checkbox" name="hobbies" value="打球">打球
<input type="checkbox" name="hobbies" value="跑步">跑步
</td>
</tr>
<tr>
<td>城市:</td>
<td>
<select name="city">
<option value="深圳">深圳 </option>
<option value="北京">北京 </option>
<option value="上海">上海 </option>
</select>
</td>
</tr>

servlet.java

request.setCharacterEncoding("UTF-8");
		String username = request.getParameter("username");
		System.out.println(username);
		
		String[] values = request.getParameterValues("hobbies");
		for(String vl:values) {
			System.out.println("爱好:"+vl);
		}

5.3 Request&Response

5.3.1 重定向与转发的区别

转发与重定向的区别

  • 1.请求重定向是找response,而转发是找request
  • 2.重定向有两次请求,转发只有一次请求
  • 3.重定向浏览器地址栏发生变化,转发浏览器地址栏不发生变化
  • 4.重定向地址栏发生变化,用户可以感知到访问了其他资源,而转发是服务器内部的行为,用户是不知道的
  • 5.重定向是可以指向互联网上的任何资源的,而转发只能指向服务器的内部资源
    转发与数据共享:
    A Servlet
 //使用request实现数据的共享
		request.setAttribute("name", "张三");
		//不想处理来访者的请求
		//将请求转发给B servlet去处理,转发指向服务器内部资源
		//写的时候必须要写/,这个/表示web应用
		request.getRequestDispatcher("/request2").forward(request, response);

B Servlet

String name=(String) request.getAttribute("name");
		response.setContentType("text/html;charset=UTF-8");
		response.getWriter().println("B Servlet------"+name);

请求重定向:

response.sendRedirect("http://localhost:8080");

应用场景:
用户登录的时候:
成功: 重定向到网站的首页 去 … Response.sendRedirect(“/day10/index.html”);
失败: 使用转发的技术, 再次回到 登录的页面, 并且 在登录的页面 提示友好错误信息
request.getRequestDispatcher("/login.jsp").forward(request, response);

5.3.2 域对象

在serlvet中只要涉及到域对象的时候 应该想到 具有如下的特点:
1.容器
2.有范围大小
3.SetAttribute(String name, Object obj)
getAttribute(name)
removeAttribute(name);

serlvetContext 域对象 :
范围是 web应用的范围内, 可以使用 如上的 三个方法 来实现 数据的共享
request域对象:
范围是一次请求的范围内, 可以 使用 如上的三个 方法来实现数据共享
Session域对象:
范围是 **一个浏览器 (一次会话 )**的范围内, 可以 使用 如上的三个 方法来实现数据共享

按照从小到大的顺序排个序:
request < session <servletContext

  • 到底什么时候 用哪个 ?
    能够用小的,就不 用大的 .
    统计网站的访问次数--- 用serlvetContext对象
    实现用户登录成功的时候, 存储登录的用户, 在网站的首页显示出来------- 用session
    在登录失败的时候, 取出友好的错误提示信息------------ 用 request

猜你喜欢

转载自blog.csdn.net/lln_lln/article/details/80749316