HttpServlet的相关知识点学习笔记

Servlet

概念
步骤
执行原理
生命周期
Servlet3.0 注解配置
Servlet的体系结构
  • GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将 service() 方法作为抽象
    • 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
  • HttpServlet:对http协议的一种封装,简化操作
    • 定义类继承HttpServlet
    • 复写 doGet/doPost 方法(判断请求方式)
    • 通过浏览器直接请求时GET
Servlet/接口
GenericServlet/抽象类
Servlet相关配置
  1. urlpartten:Servlet访问路径
    • 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
    • 路径定义规则
      • /xxx:路径匹配
      • /xxx/xxx:多层路径,目录结构
      • *.do:扩展名匹配
@WebServlet("/servletDemo")
public class ServletDemo extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

HTTP

  • 概念:Hyper Text Transfer Protocol 超文本传输协议
  • 传输协议:客户端和服务器端通信时,发送数据的格式

特点

  1. 基于TCP/IP的高级协议
  2. 默认端口号:80
  3. 基于 请求/响应 模型:一次请求对应一次响应
  4. 无状态的:每次请求之间相互独立,不能交互数据

历史版本

  • 1.0:每一次请求响应都会建立新的连接
  • 1.1:复用连接

请求消息数据格式(Request)

POST /login.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
		
username=zhangsan	
请求行
  • 请求方式 请求url 请求协议/版本
  • GET /login.html HTTP/1.1
  • 请求方式(HTTP协议有7种请求方式,常用的有2种)
    1. GET:
      1. 请求参数在请求行中,在url后。
      2. 请求的url长度有限制的
      3. 不太安全
    2. POST:
      1. 请求参数在请求体中
      2. 请求的url长度没有限制的
      3. 相对安全
请求头
  • 请求头名称:请求头值

  • 客户端浏览器告诉服务器一些信息

  • 常见的请求头

    • User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
      • 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
    • Referer:http://localhost/login.html
      • 告诉服务器,当前请求从哪里来
      • 作用:防盗链、统计工作
请求空行
  • 空行,就是用于分割POST请求的请求头和请求体的
请求体(正文)
  • 封装POST请求消息的请求参数的

Request

request 对象和 response 对象的原理

  • request对象是来获取请求消息
  • response对象是来设置响应消息
请求、响应步骤
  1. tomcat服务器会根据请求url中的资源路径,创建对应的ServletDemo对象

  2. request和response对象是由服务器创建的(request对象中封装请求消息数据),我们来使用它们

  3. tomcat将request和response两个对象传递给service方法,并且调用service方法

  4. 我们可以通过request对象获取请求消息数据,通过response对象设置响应消息数据

  5. 服务器在给浏览器做出响应之前,会从response对象中拿出我们设置的响应消息数据

request 对象继承体系结构

ServletRequest/接口
HttpServletRequest/接口

request 功能

获取请求消息数据
获取请求行数据(方法)
  • GET /day14/demo1?name=zhangsan HTTP/1.1
  • 获取请求方式(GET):String getMethod()
  • 获取虚拟目录(/day):String getContextPath()
  • 获取Servlet路径(/demo1):String getServletPath()
  • 获取get方式请求参数(name=zhangsan):String getQueryString()
  • 获取请求URI
    • String getRequestURI():/day14/demo1
    • StringBuffer getRequestURL():http://localhost/day14/demo1
    • URI(统一资源标识符):/day14/demo1
    • URL(统一资源定位符): http://localhost/day14/demo1
  • 获取协议及版本(HTTP/1.1):String getProtocol()
  • 获取客户机的IP地址:String getRemoteAddr()
获取请求头数据(方法)
  • 通过请求头的名称获取请求头的值String getHeader(String name)
  • 获取所有的请求头名称:Enumeration<String> getHeaderNames()
// 获取请求头数据
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	// 获取所有请求头名称
    Enumeration<String> headerNames = request.getHeaderNames();
    // 遍历
    While(headerNames.hasMoreElements()){
        // 根据名称获取请求头的值
        String value = request.getHeader(name);
        System.out.println(name+":"+value);
    }
    
    // 演示获取请求头数据:user-agent
    String agent = request.getHeader("user-agent");
    // 判断agent的浏览器版本
    if(agent.contains("Chrome")){
        // 谷歌浏览器
    }else{
        // 其他浏览器
    }
}
获取请求体数据(方法)
  • 请求体:只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数
  • 步骤
    1. 获取流对象
      • 获取字符输入流(只能操作字符数据):BufferedReader getReader()
      • 获取字节输入流(可以操作所有类型数据):ServletInputStream getInputStream()
    2. 再从流对象中拿数据
<!--html中form表单的action路径的写法:虚拟目录+Servlet的资源路径-->

<form action="demo/requestDemo" method="post">
    <input type="text" placeholder="请输入用户名" name="username"><br>
    <input type="text" placeholder="请输入密码" name="password"><br>
    <input type+"submit" value="注册">
</form>
@WebServlet("/requestDemo")
public class ServletDemo extends HttpServlet {
// 获取请求消息体(请求参数)
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取字符流
        BufferedReader br = request.getReader();
        // 读取数据
        String line = null;
        while((line = br.readerLine())!=null){
            System.out.println(line);	// 输出一行用户名、密码信息
        }
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
其他功能
获取请求参数通用方式
  • 不论 GET 还是 POST 请求方式都可以使用下列方法来获取请求参数

  • 根据参数名称获取参数值:String getParameter(String name)

    String name1 = request.getParameter("username");	// 根据标签name属性的值为username获取name1的值
    
    • username=zs&password=123
  • 根据参数名称获取参数值的数组:String[] getParameterValues(String name)

    String[] hobbies = request.getParameterValues("hobby");
    for(String hobby : hobbies){
        System.out.println(hobby);
    }
    
    • hobby=football&hobby=game
  • 获取所有请求的参数名称:Enumeration<String> getParameterNames()

    Enumeration<String> parameterNames = request.getParameterNames();
    while(parameterNames.hasMoreElements()){
        String name = parameterNames.nextElement();
        System.out.println(name);	// 请求的参数名称
        String value = request.getParameter(name);
        System.out.println(value);	// 根据参数名称获取参数值
    }
    
  • 获取所有参数的map集合:Map<String,String[]> getParameterMap()

    Map<String,String[]> parameterMap = request.getParameterMap();
    Set<String> keySet = parameterMap.keySet();	// 获取键
    for(String name : keySet){
        String[] values = parameterMap.get(name);	// 根据键获取值
        System.out.println(name);
        for(String value : values){
            System.out.println(value);
        }
    }
    
  • 中文乱码问题:

    • GET 方式:tomcat 8 已经将 GET 方式乱码问题解决了
    • POST 方式:会乱码
    • 解决:在获取参数前,设置 request 的编码 request.setCharacterEncoding("utf-8");
请求转发
  • 一种在服务器内部的资源跳转方式

  • 步骤

    1. 通过 request 对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
    2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
    request.getRequestDispatcher("/requestDemo").forward(request, response);
    
  • 注意事项

    1. 浏览器地址栏路径不发生变化
    2. 只能转发到当前服务器内部资源中
    3. 转发是一次请求
共享数据
  • 域对象:一个有作用范围的对象,可以在范围内共享数据
  • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
  • 方法
    • 存储数据:void setAttribute(String name,Object obj)
    • 通过键获取值:Object getAttitude(String name)
    • 通过键移除键值对:void removeAttribute(String name)
获取ServletContext
  • ServletContext getServletContext()

BeanUtils工具类,简化数据封装

用于封装JavaBean的

JavaBean:标准的Java类

要求
  1. 类必须被public修饰
  2. 必须提供空参的构造器
  3. 成员变量必须使用private修饰
  4. 提供公共setter和getter方法
功能:封装数据

概念

成员变量
  • 属性:setter和getter方法截取后的产物
  • 例如:getUsername() --> Username–> username

方法

  1. 设置:setProperty()
  2. 获取:getProperty()
  3. 将map集合的键值对信息,封装到对应的JavaBean对象中:populate(Object obj , Map map)
User user = new User();
try{
    BeanUtils.setProperty(user,"username","zhangsan");	// 将zhangsan的字符串存入user的username中
    Strign username = BeanUtils.getProperty(user,"username");	//取出username的值
}catch(IllegalAccessException e){
    e.printStackTrace();
}catch(InvocationTargetException e){
    e.printStackTrace();
}

HTTP协议

请求消息:客户端发送给服务器端的数据

  • 数据格式

    • 请求行
    • 请求头
    • 请求空行
    • 请求体

响应消息:服务器端发送给客户端的数据

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

    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>
    

Response对象

功能:设置响应消息

设置响应行
  • 格式:HTTP/1.1 200 ok
  • 设置状态码:setStatus(int sc)
设置响应头
  • setHeader(String name,String value)
设置响应体
使用步骤
  1. 获取输出流
    • 字符输出流:PrintWriter getWriter()
    • 字节输出流:ServletOutputStream getOutputStream()
  2. 使用输出流,将数据输出到客户端浏览器

重定向(资源跳转的方式)

  • a资源无法完成,b资源可以完成
  • 告诉浏览器重定向:状态码302
  • 告诉浏览器b资源路径:响应头location:b资源的路径
// 访问/responseDemo0,会自动跳转到/responseDemo
//1.设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/day/responseDemo");

//简单的重定义方法
response.sendRedirect("/day/responseDemo");
重定向的特点:redirect
  • 地址栏发生变化
  • 重定向可以访问其他站点(服务器)的资源
  • 重定向是两次请求。不能使用request对象来共享数据
转发的特点:forward
  • 转发地址栏路径不变
  • 转发只能访问当前服务器下的资源
  • 转发是一次请求,可以使用request对象来共享数据
路径写法
  • 相对路径:通过相对路径不可以确定唯一资源

    • 如:./index.html
    • 不以 / 开头,以 . 开头路径
    • 规则:找到当前资源和目标资源之间的相对位置关系
      • ./:当前目录
      • ../:后退一级目录
  • 绝对路径:通过绝对路径可以确定唯一资源

    • 如:http://localhost/day/responseDemo
    • day/responseDemo
    • 以 / 开头的路径
    • 规则:判断定义的路径是给谁用的?->判断请求将来从哪里发出
      • 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
        • 建议虚拟目录动态获取:request.getContextPath()
        • <a>,<form>重定向…
      • 给服务器使用:不需要加虚拟目录
        • 转发路径

服务器输出字符数据到浏览器

步骤
  1. 获取字符输出流
  2. 输出数据
// 获取流对象之前,设置流的默认编码为utf-8
response.setCharacterEncoding("utf-8");

// 告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码
// response.setHeader("content-type","text/html;charset=utf-8");
// 简化为以下代码
response.setContentType("text/html;charset=utf-8");

// 获取字符输出流
PrintWriter pw = response.getWriter();	// 一次响应后自动被销毁
// 输出数据到页面
pw.write("<h1>hello response</h1>");
注意乱码问题
  • PrintWriter pw = response.getWriter();:获取的流的默认编码是ISO-8859-1
  • 设置该流的默认编码
  • 告诉浏览器响应体使用的编码
  • 简单的形式(设置编码在获取流之前设置):response.setContentType("text/html;charset=utf-8");

服务器输出字节数据到浏览器

步骤
  1. 获取字符输出流
  2. 输出数据
// 获取字节输出流
ServletOutputStream sos = response.getOutputStream();
// 输出数据
sos.write("hello".getBytes());

ServletContext对象

概念

  • 代表整个web应用,可以和程序的容器(服务器)来通信

获取

  • 通过request对象获取:request.getServletContext();

  • 通过HttpServlet获取:this.getServletContext();

ServletContext context1 = request.getServletContext();
ServletContext context2 = this.getServletContext();
// context1 == context2

功能

  • 获取MIME类型

    • MIME类型:在互联网通信过程中定义的一种文件数据类型
    • 格式:大类型/小类型 text/html image/jpeg
    • 获取:String getMimeType(String file)
  • 域对象:共享数据

    • setAttribute(String name,Object value)
    • getAttribute(String name)
    • removeAttribute(String name)
    • ServletContext对象范围:所有用户所有请求的数据
@WebServlet("/servletContextDemo1")
public class ServletContextDemo1 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 通过HttpServlet获取
        ServletContext context = this.getServletContext();
        // 设置数据
        context.setAttribute("msg","hello");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

@WebServlet("/servletContextDemo2")
public class ServletContextDemo2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 通过HttpServlet获取
        ServletContext context = this.getServletContext();
        // 获取数据
        Object msg = context.getAttribute("msg");
        System.out.println(msg);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 获取文件的真实(服务器)路径的方法:String getRealPath(String path)
@WebServlet("/servletContextDemo3")
public class ServletContextDemo3 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 通过HttpServlet获取
        ServletContext context = this.getServletContext();
        // 获取文件的服务器路径
        String realPath = context.getRealPath("/b.txt");// web目录下资源访问
        
        String realPath2 = context.getRealPath("/WEB-INF/c.txt");// WEB-INF目录下的资源访问
        
        String realPath3 = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值