JavaWeb-day47

Day47 Servlet、跳转方式、ajax交互

1. 软件构成和分层

在这里插入图片描述

2. Response

2.1 Http响应消息

*格式:

HTTP/1.1 200 OK
			Content-Type: text/html;charset=UTF-8
			Content-Length: 101
			Date: Wed, 06 Jun 2018 07:08:42 GMT
			(空行)
			<html>
			  <head>
			    <title>$Title$</title>
			  </head>
			  <body>
			  	hello , response
			  </body>
			</html>

	1) 响应行
		1. 组成:协议/版本 响应状态码 状态码描述
		2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
			1. 状态码都是3位数字 
			2. 分类:
				1xx:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
				2xx:成功。代表:200
				3xx:重定向。代表:302(重定向),304(访问缓存)
				4xx:客户端错误。
					* 代表:
						* 404(请求路径没有对应的资源) 
						* 405:请求方式没有对应的doXxx方法
				5xx:服务器端错误。代表:500(服务器内部出现异常)
				
	2) 响应头:
		1. 格式:头名称: 值
		2. 常见的响应头:
			1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
			2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
				* 值:
					* in-line:默认值,在当前页面内打开
					* attachment;filename=xxx:以附件形式打开响应体。文件下载
		3) 响应空行

2.2 Response对象

HttpServletResponse继承ServletResponse接口,专门封装HTTP响应消息

2.3 Response功能

  1. 设置响应行
    1. 格式:HTTP/1.1 200 ok
    2. 设置状态码:setStatus(int sc) 2) 设置响应头:setHeader(String name, String value) 3) 设置响应体: * 使用步骤:
      1. 获取输出流
        • 字符输出流:PrintWriter getWriter()
        • 字节输出流:ServletOutputStream getOutputStream()
      2. 使用输出流,将数据输出到客户端浏览器
        response.getWriter().println(“xxxx”);
        4)设置编码
        response.setContentType(“text/html;charset=utf-8”);
package com.tledu.zrz.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/api1")
public class _01_ResponseAPI_01 extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 单独设置编码,需要在获取流之前,默认编码为ISO-8859-1
		resp.setCharacterEncoding("utf-8");
		// 响应类型和编码
		resp.setContentType("text/html;charset=utf-8");
		
		// 获取字符流,输出数据
		PrintWriter pw = resp.getWriter();
		pw.write("你好");
		
		pw.println("我很好");
	}
}

在这里插入图片描述

package com.tledu.zrz.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/api2")
public class _02_ResponseAPI_02 extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 单独设置编码,需要在获取流之前,默认编码为ISO-8859-1
		resp.setCharacterEncoding("utf-8");
		// 响应类型和编码
		resp.setContentType("text/html;charset=utf-8");

		// 字节
		ServletOutputStream sos = resp.getOutputStream();
		sos.write(97);
		// 设置状态
		// resp.setStatus(500);
	}
}

在这里插入图片描述

package com.tledu.zrz.controller;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class _03_ServletContext extends HttpServlet {
	@Override
	public void init(ServletConfig config) throws ServletException {
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
	}
}

package com.tledu.zrz.controller;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class _04_init implements Servlet {

	@Override
	public void init(ServletConfig config) throws ServletException {
		// 局部参数获取,使用config对象调用getInitParameter(key) 获取
		String username = config.getInitParameter("username");
		
		// 全局参数需要使用servletContext获取,而servletContext被封装在servletConfig中
		ServletContext servletContext = config.getServletContext();
		String age  = servletContext.getInitParameter("age");
		System.out.println(username +" : "+age);
	}

	@Override
	public void service(ServletRequest req, ServletResponse res)
			throws ServletException, IOException {

	}

	@Override
	public ServletConfig getServletConfig() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}

request ,session ,servletContext 区别

3. Ajax交互

package com.tledu.zrz.controller;

import java.io.IOException;

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

@WebServlet("/getData")
public class AjaxTest extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.setCharacterEncoding("utf-8");
		// 响应类型
		resp.setContentType("application/json;charset=utf-8");
		// 1 数据库查询 获取所有用户 得到集合
		// 2 把集合转换为jsons数组格式的字符串
		// JSON数组格式的字符串,一般为数据库查询出来的,然后转换为JSON格式
		String string = "[{id:1,'username':'admin','password':'root'},{id:2,'username':'test','password':'1234'}]";
		// 响应数据
		resp.getWriter().write(string);
	}
}

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        window.onload = function () {
            var btn = document.getElementById("btn");
            btn.onclick = function () {
        /**
         *  1 获取ajax引擎对象 XMLHttpRequest
         *  2 配置请求连接的URL,代表浏览器要发出的请求以及目的地,还有就是是否异步
         *      这个请求不是直接发送,而是配置给ajax引擎,有它去发送
         *  3 监视XMLHttpRequest对象的请求流程,根据不同的请求结果,做出不同的响应
         *  4 发送请求,上面都是准备,这里才是真正的发送
         */
                // 1 获取ajax引擎对象 XMLHttpRequest
                var xmlhttp;
                if (window.XMLHttpRequest) {
                    // code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp = new XMLHttpRequest();
                } else {
                    // code for IE6, IE5
                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                }
                // 2 配置请求连接的URL
                xmlhttp.open("GET", "getData", true);
                // 3 监听请求状态
                xmlhttp.onreadystatechange = function () {
                    // 为4 和 200 说明请求成功
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    	// 把JSON数组格式的字符串转换为JSON数组对象
                    	var jsons = eval(xmlhttp.responseText);
                    	// 遍历数组
                    	for(var i = 0; i < jsons.length; i++){
                    		// 遍历数组中每一个JSON对象
                    		for(key in jsons[i]){
                    			 document.getElementById("saveData").innerHTML +=  jsons[i][key]+"  ";
                    		}
                    		document.getElementById("saveData").innerHTML +="<br>";
                    	}
                       
                    }
                }

                // 4 发送请求
                xmlhttp.send();
                // post请求 如果需要传递参数 必须设置请求头
                // xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                // 参数 键=值&键=值
                // xmlhttp.send("fname=Bill&lname=Gates");
            }
        }


    </script>
</head>

<body>
    <button id="btn">获取数据</button>
    <div id="saveData"></div>
    <input type="text" name="" id="">
</body>

</html>

在这里插入图片描述
JSON
在这里插入图片描述

package com.tledu.zrz;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.tledu.zrz.pojo.User;

public class Test {
	public static void main(String[] args) {
		// 1 数据库查询数据,得到集合
		List<User> users = new ArrayList<User>();
		users.add(new User(1, "admin", "root", "管理员"));
		users.add(new User(2, "administrator", "root", "泽哥最帅"));
		users.add(new User(3, "test", "1234", "2楼说的对"));
		// 2 转换为JSON数组格式的字符串
		System.out.println(JSON.toJSONString(users));
		// 3 传递到页面
		// resp.getWriter().write(JSON数组格式的字符串);
	}
}

在这里插入图片描述

4. 初始化数据init

Init方法,最先执行,并且执行只执行一次,默认是第一次请求的时候执行
但是可以通过load-on-startup来设置执行时机
-1 是第一次请求
0和正整数 是启动tomcat的时候执行

结合init的执行时机,所以比较适合做一些数据初始化的工作
1 初始化java中对象或其他
2 初始化xml中的数据
1 局部
2 全局

可以解决硬代码问题,一般用来指定字符编码,和filter一起使用
4.1 局部
在这里插入图片描述
在这里插入图片描述
4.2 全局
在这里插入图片描述
在这里插入图片描述

5. 作用域

getAttribute
setAttribute
removeAttribute
以上三个方法,是request,session,servletContext都有的,用来向对应的作用域中保存数据,获取数据,删除数据
5.1 Request
当前请求有效,如果向request中保存数据,那么仅在当前请求中可以获取
一般用于页面和后端交互是需要进行的数据传递

package com.tledu.zrz.controller;

import java.io.IOException;
import java.io.PrintWriter;

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

@WebServlet("/req")
public class _05_Request extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=utf-8");
		
		// 创建输出流
		PrintWriter pw = response.getWriter();
		
		// 获取数据 ,返回Object类型,需要强制转换
		Integer count = (Integer) request.getAttribute("count");
		// 第一次请求 一定是获取不到的,因为得先保存,才能获取到
		if(count == null){
			count = 0;
		}else{
			count++;
		}
		// 保存数据
		request.setAttribute("count", count);
		
		// 向页面写出
		pw.println("<h1 align='center'>"+count+"</h1>");
	}
}

不管在那个浏览器,一次会话中只执行一次
一直都是0
在这里插入图片描述
5.2 Session
当前会话有效,建立的持续通信,一般是浏览器打开到浏览器关闭,是一次会话,不过也是可以设置会话时间的
一般用于保存登陆的用户信息

package com.tledu.zrz.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/ses")
public class _06_Session extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=utf-8");
		
		// 创建输出流
		PrintWriter pw = response.getWriter();
		
		// 获取session , true 说明没有session就新建一个
		HttpSession session = request.getSession(true);
		// 获取数据 ,返回Object类型,需要强制转换
		Integer count = (Integer) session.getAttribute("count");
		// 第一次请求 一定是获取不到的,因为得先保存,才能获取到
		if(count == null){
			count = 0;
		}else{
			count++;
		}
		// 保存数据
		session.setAttribute("count", count);
		
		// 向页面写出
		pw.println("<h1 align='center'>"+count+"</h1>");
	}
}

session 在服务器没有关闭 会话没有结束,刷新页面依然加一,同样打开新的链接,把url 赋值进去,数据不会丢失,因为,浏览器会有session,记住当前状态;如果换成其他浏览器,会话又是不一样的,是初始状态
在这里插入图片描述
会话中,数据共享
5.3 ServletContext
全局有效,只要服务器不关闭,永久存储,服务器关闭,数据消失

package com.tledu.zrz.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/sc")
public class _07_ServletContext extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=utf-8");
		
		// 创建输出流
		PrintWriter pw = response.getWriter();
		
		// 获取servletContext
		ServletContext application = request.getServletContext();
		
		// 获取数据 ,返回Object类型,需要强制转换
		Integer count = (Integer) application.getAttribute("count");
		// 第一次请求 一定是获取不到的,因为得先保存,才能获取到
		if(count == null){
			count = 0;
		}else{
			count++;
		}
		// 保存数据
		application.setAttribute("count", count);
		
		// 向页面写出
		pw.println("<h1 align='center'>"+count+"</h1>");
	}
}

对比session ,换个浏览器试,还当前会话,不是新的会话
在这里插入图片描述
只要tomcat不重新启动,数据一直存在,共享

6. 重定向和请求转发

6.1 请求转发

  1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
  2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)

forward
发送

package com.tledu.zrz.controller;

import java.io.IOException;

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

@WebServlet("/a/b/c")
public class _08_forward extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// 通过servletContext对象中的getRequestDispatcher 进行跳转
		// 因为这种是通过servletContext请求转发的,所以地址必须加 / ,/就是根目录(WebContent)
		// request.getServletContext().getRequestDispatcher("/test.html")
		// .forward(request, response);

		// 直接通过request进行跳转
		//  这种跳转,加 / 表示根目录(WebContent) , 不加 / 就是相对路径
		//		比如 当前servlet的路由为 /a/b/c 则 url 是这样 : http://localhost:8080/Servlet_02/a/b/c
		// 则 绝对路径 是 http://localhost:8080/Servlet_02/
		// 相对路径是 http://localhost:8080/Servlet_02/a/b/
		// /user/list
		 request.getRequestDispatcher("/test.html").forward(request, response);
		 //		 http://localhost:8080/Servlet_02/test.html
		 // http://localhost:8080/Servlet_02/a/b/test.html
	}
}

在这里插入图片描述
特点:
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求
客户无感知跳转,跳转方和被跳转方数据共享(request)

6.2 重定向
sendRedirect
直接发送

package com.tledu.zrz.controller;

import java.io.IOException;

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

@WebServlet("/send")
public class _09_sendRedirect extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 加/ 是绝对 : 绝对 定位到当前服务器 webapps,IP:8080
		// 不加/ 是相对 : 同forward的相对
		// 使用绝对要注意,需要写项目名
		// resp.sendRedirect("/Servlet_02/test.html");
		
		// 获取虚拟目录(/项目名)
		String name = req.getContextPath();
		resp.sendRedirect(name+"/test.html");
	}
}

输入send 路由 会直接转到test.html
在这里插入图片描述
在这里插入图片描述
6.3 区别

forward 和 redirect 区别
在这里插入图片描述

Forward是服务器内部跳转,两个页面中数据互通,使用同一个request对象,但是地址栏中依然显示第一次请求的url地址,用户感觉不到页面进行了跳转,也只会发送一次请求。

在这里插入图片描述
sendRedirect是重定向,两个页面数据不互通,使用的不是同一个request对象,地址栏中显示的是第二个请求的url地址,会发送两次请求

重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据
转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据

6.4 应用场景
1 比如登陆失败,或者被拦截到登陆页面,只要是需要用户输入之后,进行跳转的,一般使用重定向
如果此时使用forward跳转,则地址栏不变,那么此时如果刷新页面(重新请求地址栏),就会弹框,提示是否重复发送
在这里插入图片描述

Get请求 不会弹框提示,但是依然会发送

在这里插入图片描述

2 比如去后端获取数据,一般请求转发(因为request共享)
查询相关,都是forward
比如 搜索,用户列表
搜索比较特殊,需要传递数据(提交数据),一般搜索肯定使用get请求

如果是post请求,后端大部分使用重定向(一般发送数据使用post)
如果是get请求,后端大部分使用forward(一般获取数据使用get)

package com.tledu.zrz.controller;

import java.io.IOException;

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

@WebServlet("/login")
public class _10_LoginServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println(req.getParameter("username"));
		System.out.println(req.getParameter("password"));
		req.getRequestDispatcher("test.html").forward(req, resp);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值