javaweb——Servlet——20200630

javaweb

  1. javaweb的概念
    javaweb、请求、响应、请求和响应的关系
  2. web资源的分类
    1. 静态资源:html/css/js/视频/图片
    2. 动态资源 :jsp,servlet
  3. 常见的web服务器
    tomcat(最广泛)、JBoss、GlassFish、Resin、WebLogic(收费产品中应用最广泛)
  4. Tomcat服务器和Servlet版本的关系
TomcatServlet/SPJavaEE运行环境
4.12.3/1.21.3JDK1.3
5.02.4/2.01.4JDK1.4
5.5/6.02.5/2.15.0JDK5.0
7.03.0/2.26.0JDK6.0
8.03.1/2.37.0JDK7.0

浏览器直接打开html文件,使用的是file协议。

Idea相关

整合Tomcat服务器

File | Settings | Build, Execution, Deployment | Application Servers
添加服务器

创建动态web工程

  • new -> module
  • 勾选 Web Application
  • 命名,模块创建成功
    在这里插入图片描述
    • src:java源代码
    • web:web工程的资源文件
      • web-inf目录是受服务器保护的目录,浏览器无法直接访问到此目录的内容
      • web.xml整个动态web工程的配置描述文件。比如:servlet、filter、listener、session等
    • lib:存放第三方jar包(IDEA需要自己配置导包)
添加第三方jar包步骤
  • Project Strcuture | Libraries
    +New Project Library(Java) -> 勾选jar包(一个或多个,会生成一个lib库,可重命名)-> 选择生效的module -> apply
  • Project Strcuture | Artifacts
    点击fix,将类库添加到打包部署中
工程部署到tomcat运行
  • edit configurations:建议修改web工程对应的tomcat运行实例的名称
  • 将需要部署的web工程添加到tomcat运行实例中(或删除不需要的)
    在这里插入图片描述
  • 默认的访问地址(http://localhost:8080/web_01_war_exploded/,可修改)
    在这里插入图片描述

1. Servlet

什么是Servlet

  1. Servlet是javaEE规范之一。规范就是接口。
  2. Servlet是javaweb的三大组件(servlet、filter和listener)之一。
  3. Servlet是运行在服务器上的一个java小程序,它可以接受客户端发送的请求,并响应数据给客户端。

实现Servlet

  1. 编写一个类去实现Servlet接口
  2. 实现service方法,处理请求,并响应数据
  3. 到web.xml中去配置Servlet程序的访问地址
<!--  servlet标签给tomcat配置Servlet程序  -->
    <servlet>
        <!-- 给Servlet程序起一个别名       -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- Servlet程序的全类名       -->
        <servlet-class>com.javaee.servlet.HelloServlet</servlet-class>
    </servlet>
    <!-- 给Servlet配置访问地址   -->
    <servlet-mapping>
        <!-- 指明是哪个HelloServlet程序(别名)       -->
        <servlet-name>HelloServlet</servlet-name>
        <!--        访问地址
                / 表示工程路径 ==> http://ip:port/工程路径

         -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

配置错误会报IllegalArgumentException

Servlet生命周期

Servlet创建:

  1. 执行Servlet构造器方法
  2. 执行init初始化方法

Servlet每次访问都会调用:

  1. 执行service方法

Servlet销毁:

  1. 执行destroy销毁方法

通过继承HttpServlet来实现Servlet程序

  1. 编写一个类继承HttpServlet
  2. 重写doPost()或doGet()方法
  3. 到web.xml文件中配置

使用Idea实现Servlet程序

new -> create new Servlet
实现效果与上一步相同,更便捷

Servlet体系

  • Servlet接口:负责定义访问规范
  • GenericServlet 类:
    • 实现了Servlet接口;
    • 做了Servlet很多空方法实现;
    • 并持有一个ServletConfig的引用,并对ServletConfig的使用写了一些方法
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable{
    private static final long serialVersionUID = 1L;
    private transient ServletConfig config;

    public GenericServlet() {
    }

    public void destroy() {
    }

    public String getInitParameter(String name) {
        return this.getServletConfig().getInitParameter(name);
    }

    public Enumeration<String> getInitParameterNames() {
        return this.getServletConfig().getInitParameterNames();
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public ServletContext getServletContext() {
        return this.getServletConfig().getServletContext();
    }

    public String getServletInfo() {
        return "";
    }

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    public void init() throws ServletException {
    }

    public void log(String message) {
        this.getServletContext().log(this.getServletName() + ": " + message);
    }

    public void log(String message, Throwable t) {
        this.getServletContext().log(this.getServletName() + ": " + message, t);
    }

    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    public String getServletName() {
        return this.config.getServletName();
    }
}
  • HttpServlet类:
    • 继承了GenericServlet类
    • service()方法中,对请求进行分发实现

*HTTP的请求类型

2. ServletConfig类

  • ServletConfig类是Servlet程序的配置信息类
  • Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们只负责使用。
  • Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象

ServletConfig的作用

  1. 可以获取Servlet程序的别名servlet-name的值
  2. 获取初始化参数init-param
  3. 获取ServletContext对象
final ServletConfig servletConfig = super.getServletConfig();
System.out.println(servletConfig.getInitParameterNames());//java.util.Collections$3@1cdec88
System.out.println(servletConfig.getServletName());//HelloIdeaServlet
System.out.println(servletConfig.getServletContext());//org.apache.catalina.core.ApplicationContextFacade@f0a02c1

注意:继承HttpServlet的类初始化的时候
super.init(config),就可以使用tomcat创建的config对象

3. ServletContext类

  1. ServletContext是一个接口,它表示Servlet上下文对象
  2. 一个web工程,只有一个ServletContext对象实例。
  3. ServletContext对象是一个域对象
    域对象:是可以像Map一样存取数据(一般是k-v对)的对象。使用setAttribute()/getAttribute()
    域:存取数据的操作范围,即整个web工程

ServletContext的作用

  1. 获取web.xml中配置的上下文参数context-param
<context-param>
        <param-name>username</param-name>
        <param-value>context</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>root</param-value>
    </context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("let's do get()");
//        super.doGet(req, resp);

        ServletContext servletContext =getServletConfig().getServletContext();
//        ServletContext只能获取<context-param>,不能获取<init-param>
        final Object username = servletContext.getInitParameter("username");//username:context
        final Object password = servletContext.getInitParameter("password");//password:root
        System.out.println("username:"+username+"\npassword:"+password);
        System.out.println("ContextPath:" + servletContext.getContextPath());//ContextPath:
        System.out.println("realPath:"+servletContext.getRealPath("/"));//realPath:D:\web\IdeaProjects\javaEEdemos\demo1\out\artifacts\02_web_war_exploded\
        System.out.println("realPath(/web-inf/css): " + servletContext.getRealPath("/web-inf/css"));
        //realPath(/web-inf/css): D:\web\IdeaProjects\javaEEdemos\demo1\out\artifacts\02_web_war_exploded\web\web-inf\css

    }
  1. 获取当前的工程路径,格式:/工程路径
  2. 获取工程部署后在服务器硬盘上的绝对路径
  3. 像Map一样存取数据

4.Http协议

什么是Http协议

客户端和服务器之间通信时,发送 的数据,需要遵守的规则,叫HTTP协议。
协议中的数据又叫保温

请求的HTTP协议格式

GET请求

  1. 请求行
    1. 请求的方式 : GET
    2. 请求的资源路径 : [+?+请求参数]
    3. 请求协议的版本号 : HTTP/1.1
  2. 请求头
    key:value 组成不同的键值对,表示不同的含义。
GET /hello2 HTTP/1.1  # 请求行:方式 路径 版本号
# 以下是请求头
Host: localhost:8080 # 请求服务器的ip和端口号
Connection: keep-alive # 告诉服务器请求连接如何处理,keep-alive表示保持连接,closed表示关闭
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 
# 浏览器的信息
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
# 告诉服务器,客户端可以接收的数据类型
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/a.html
Accept-Encoding: gzip, deflate, br # 客户端可以接收的数据编码(压缩)格式
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 # 客户端可以接收的语言类型
Cookie: JSESSIONID=D4298EA7BF0A68FA2B3789335A4E82AD

POST请求

  1. 请求行
    1. 请求的方式 : POST
    2. 请求的资源路径 : [+?+请求参数]
    3. 请求协议的版本号 : HTTP/1.1
  2. 请求头
    key:value 组成不同的键值对,表示不同的含义。
  3. 请求体
#请求行
POST /hello3 HTTP/1.1
#请求头
Host: localhost:8080
Connection: keep-alive
Content-Length: 27
Cache-Control: max-age=0
# 表示如何控制缓存 no-cahe表示不缓存
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded 
#表示发送数据的类型
# application/x-www-form-urlencoded 表示提交的数据格式是 name=value&name=value...,然后对其进行url编码
# multipart/form-data 表示以多段的形式提交数据给服务器(以流的形式提交,用于上传)
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/b.html #请求发起时,浏览器地址栏中的地址(从哪来)
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: JSESSIONID=5E3D2E322B85BC5DD5F7456906B33655
# 请求体
action=login&username=admin

Content-Type:表示发送数据的类型

  • application/x-www-form-urlencoded 表示提交的数据格式是 name=value&name=value…,然后对其进行url编码
  • multipart/form-data 表示以多段的形式提交数据给服务器(以流的形式提交,用于上传)

get和post

GET请求有哪些:

  • form标签 method=get
  • a标签
  • link标签引入css
  • script标签引入js
  • iframe标签引入html页面
  • 在浏览器地址栏中输入地址后敲回车

POST请求有哪些:

  • form标签 method=post

响应的HTTP协议格式

  1. 响应行
    1. 响应的协议和版本号 HTTP/1.1
    2. 响应状态码 200
    3. 响应状态描述符 OK
  2. 响应头
    1. key:value
    2. 空行
  3. 响应体
    1. 回传给客户端的数据
#响应行
HTTP/1.1 200
#响应头
Accept-Ranges: bytes
ETag: W/"382-1593527753052"
Last-Modified: Tue, 30 Jun 2020 14:35:53 GMT
Content-Type: text/html
Content-Length: 382 #响应体长度
Date: Tue, 30 Jun 2020 14:57:54 GMT #请求响应的时间
#响应体
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>post</title>
</head>
<body>
    <form action="http://localhost:8080/hello3" method="post">
        <input  name="action" type="hidden" value="login">
        <label>
            <input  name="username" type="text">
        </label>
        <input type="submit">
    </form>
</body>
</html>

响应码

响应码表示
200请求成功
302请求重定向
404请求服务器以及收到了,但是请求的数据不存在(请求地址错误)
500服务器已经收到请求,但是服务器内部错误(代码错误)

MIME类型说明

MIME是HTTP协议中数据类型,全称Multipurpose Internet Mail Extensions ,即多功能互联网邮件扩充服务。MIME类型的格式是“大类型/小类型”,并于某一种文件的扩展名相对应

文件MIME类型
超文本标记语言文本.html/.htm text/html
普通文本text/plain
RTF文本application.rtf
gif图形image/gif

5. HttpServletRequest类

每次只要有请求进入tomcat服务器,tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中。然后传递到service方法中给我们使用。可以通过该类,来获取到所有请求的信息

常用方法

测试:

System.out.println("URI => " + req.getRequestURI()); //URI => /request
        System.out.println("URL => " + req.getRequestURL()); //URL => http://localhost:8080/request
        System.out.println("客户端 IP地址 => " + req.getRemoteHost()); // 客户端 IP地址 => 127.0.0.1 如果是访问的真实IP地址,则得到真实IP地址
        System.out.println("请求头 User-Agent => "+req.getHeader("User-Agent"));
        //请求头 User-Agent => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36

        String username = req.getParameter("username");
//        System.out.println(req.getAttribute("username"));//null
        String password = req.getParameter("password");
        String[] hobby = req.getParameterValues("hobby");

        System.out.println("name:" + username);//name:admin

        System.out.println("hobby:" + Arrays.toString(hobby));//hobby:[java, c]

对应表单:

<form action="http://localhost:8080/request" method="get">
        <label>用户名:<input type="text" name="username"></label>
        <label>密码:<input type="password" name="password"></label>
        <label>爱好:<input type="checkbox" name="hobby" value="cpp">C++
        <input type="checkbox" name="hobby" value="java">java
        <input type="checkbox" name="hobby" value="c">C</label>
        <input type="submit">
    </form>

若是POST,如果不设置

req.setCharacterEncoding("UTF-8");

则可能出现中文乱码

请求的转发

请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源的操作。

实现demo

从Servlet1转发到Servlet2,共同完成一个完整的业务功能

public class Servlet_01 extends HttpServlet {
	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doGet(req, resp);

        String username = req.getParameter("username");
        System.out.println("On Servlet1 查看参数"+username);

        //传递给Servlet2的参数
        req.setAttribute("username",username);
        req.setAttribute("key","Servlet1");
        //传递给Servlet2 ,以斜杠/打头的地址
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet02");
        requestDispatcher.forward(req,resp);
    }
}
public class Servlet_02 extends HttpServlet {
	@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);

        String username = req.getParameter("username");
        System.out.println("On Servlet2 查看参数"+username);

        //接收Servlet1的参数
        final Object username1 = req.getAttribute("username");
        final Object key = req.getAttribute("key");

        System.out.println("Servlet1 是否标记:"+"Servlet1".equals(key));

        System.out.println("Servlet2 执行操作");
    }
}

类型 异常报告
消息 提交响应后无法转发
描述 服务器遇到一个意外的情况,阻止它完成请求。
java.lang.IllegalStateException: 提交响应后无法转发


原因:Servlet1和Servlet2中的 super.doGet(req, resp);没删除
两个都必须删除,Servlet1中的不删除会显示此URL不支持Http方法GET;Servlet2中的不删除则会转发失败

请求转发的特点

  1. 浏览器地址栏没有变化
  2. 他们是一次请求
  3. 共享request域中的数据
  4. 可以转发到web-info中
  5. 无法访问工程外的目录

base标签的作用

  • 所有相对路径在工作时候都会参照当前浏览器地址栏中的地址进行跳转。
  • 当采用转发时,地址栏中的地址不变。
  • 那么<a>标签中若有相对地址,且是参照<a>标签所在的html文件的位置(也即是转发之后的地址,而不是转发之前的地址)来写的,那么此时,参照地址栏中的地址(即转发前的地址)则可能会出错。
  • 此时可以采用base标签来锁定地址“参照物”。
    <base href="xx/ss/">(注意:最后若不写斜杠,则ss会被认为是文件)写在<title>下面,则<a>中跳转的相对路径,都是参照base标签中的位置。

* 斜杠/的意义

在web中斜杠是一种绝对路径。

  • 如果被浏览器解析,得到的地址是http://ip:port/
  • 如果被服务器解析,得到的地址是http://ip:port/工程路径
    • <url-pattern>/hello</url-pattern>
    • servletContext.getRealPath("/")
    • req.getRequestDispatcher("/servlet02");
    • 注意: responce.sendRedirect("/")把斜杠发送给浏览器解析,得到的地址是http://ip:port/

5. HttpServletResponce类

作用

  • 每次请求进来,tomcat服务器都会创建一个Responce对象传递给Servlet程序去使用。HttpServletResponce表示所有响应的信息。
  • 如果有需要设置返回给客户端的信息,都可以通过HttpServletResponce对象来进行设置

两个输出流

  • 字节流:传递二进制数据
  • 字符流:回传字符串
  • 两个流只能使用一个。调用两个会报错,例如java.lang.IllegalStateException: 已为此响应调用getWriter()
  • 输出的时候要注意编码问题:
//它会设置客户端和服务器都使用该字符集,还设置了响应头,但必须在获取流之前才有效
//        resp.setContentType("text/html;charset=UTF-8");
//        //设置响应头
//        resp.setHeader("Content-Type","text/html;charset=UTF-8");

请求重定向

是指客户端给服务器发请求,然后服务器告诉客户端,可以去新地址访问,让请求重定向。

特点

  1. 浏览器地址栏会发生变化
  2. 有两次请求
  3. 不共享request域中数据

测试demo

  • Responce1程序 被Responce2程序所取代,大概服务器访问程序1时,应当重定向到程序2。
  • 当服务器访问程序1时,程序一返回:
    响应码:302(重定向)
    响应头:Location——程序2的地址
resp.setStatus(302);
resp.setHeader("Location","/servlet02");

疑问?
在重定向之前,用writer输出,如果关闭writer,就会无法重定向
原因:未知????

        final PrintWriter writer = resp.getWriter();         final ServletOutputStream outputStream = resp.getOutputStream();        
//它会设置客户端和服务器都使用该字符集,还设置了响应头,但必须在获取流之前才有效 //       
resp.setContentType("text/html;charset=UTF-8");         //设置响应头
        resp.setHeader("Content-Type","text/html;charset=UTF-8");
//
        writer.write("Hello , "+req.getParameter("username")+"\nRedirect to Servlet2");
        writer.close();

        resp.setStatus(302);
        resp.setHeader("Location","/servlet02"); ```

推荐方式:

resp.sendRedirect("/servlet02");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值