【JavaWeb】2、Servlet、JSP、Listener

三、Servlet程序

Sevlet技术

1、介绍

  1. Servlet是JavaEE规范之一,是一个接口
  2. Servlet是JavaWeb三大组件之一,分别是Servlet程序、Filter过滤器、Listener监听器
  3. Servlet是运行在服务器上的一个java小程序,可以接受客户端发送过来的请求,并且响应数据

2、手动实现Servlet程序

  1. 编写一个实现Servlet接口的类
  2. 实现service方法:处理请求并响应数据
  3. 在web.xml中配置servlet程序的访问地址
<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  • servlet

    • servlet-name:servlet的程序名,一般用类名
    • servlet-class:servlet的全类名
  • servlet-mapping:给servlet程序配置访问地址

    • servlet-name:该地址匹配的servlet程序名

    • url-pattern:配置访问地址

      /hello 表示地址为htpp://ip:port/工程路径/hello

注:访问地址必须加“ / ”、servlet-name必须对应

3、url到servlet程序的访问顺序

ip—端口号—程序名—资源名/hello—xml—匹配到url /hello—匹配的servlet程序HelloServlet—匹配到类com.atguigu.servlet.HelloServlet

4、Servlet生命周期

  1. 执行Servlet构造器

  2. 执行init初始化方法

    第1、2步,在第一次访问的时候创建Servle程序时调用

  3. 执行service方法

    第3步,每次访问都会调用

  4. 执行destroy销毁方法

    第4步在web工程停止时调用

5、Get和Post处理

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("3. HelloServlet被访问了");
//        类型转换,因为它有getMethod()方法
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
//        获取请求方式
        String method = httpServletRequest.getMethod();
        if("POST".equals(method)){
            doPost();
        }else if("GET".equals(method)){
            doGet();
        }

    }
    public void doGet(){
        System.out.println("GET请求");
    }
    public void doPost(){
        System.out.println("POST请求");
    }

6、HttpServlet

在实际开发中,一般使用继承HttpServlet类的方式实现Servlet程序

  1. 编写一个继承HttpServlet的类
  2. 根据业务需要重写**doGet()doPost()**方法
  3. 到web.xml中配置Servlet程序的访问地址

在Idea中新建Servlet文件会自动创建继承HttpServlet的类

7、Servlet继承体系

ServletConfig类

ServletConfig是Servlet程序的配置信息类

作用:

  1. 可以获取Servlet程序的别名 servlet-name 的值
  2. 获取初始化参数 init-param
  3. 获取ServletContext对象

Servlet程序和ServletConfig对象都是由Tomcat负责创建

  • Servlet程序默认是第一次访问时创建
  • ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象

在xml的servlet标签中可以设置初始化参数init-param

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
<!--        init-param是初始化参数,name是参数名,value是参数值-->
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123456</param-value>
        </init-param>
    </servlet>
public void init(ServletConfig servletConfig) throws ServletException {
    System.out.println("2. init()");
    System.out.println(servletConfig.getServletName());
    System.out.println(servletConfig.getInitParameter("url"));
    System.out.println(servletConfig.getInitParameter("username"));
    System.out.println(servletConfig.getInitParameter("password"));
    System.out.println(servletConfig.getServletContext());
}

ServletContext类

  1. ServletContext是一个接口,表示Servlet上下文对象

  2. 一个web工程只有一个ServletContext对象实例

  3. ServletContext对象是一个域对象(可以存取数据),这里的是指存取数据的范围,是整个web工程

  4. ServletContext对象在web工程启动时创建,停止时销毁

  5. 可以在Servlet程序中调用getServletConfig().getServletContext();获取,也可以直接调用getServletContext()获取

存数据取数据删除数据
Mapput( )get( )remove( )
域对象setAttribute( )getAttribute( )removeAttribute( )

作用:

  1. 获取web.xml中配置的上下文参数 context-param(属于整个web工程)

  2. 获取当前工程路径,格式: /工程路径

  3. 获取工程打包部署后在服务器硬盘上的绝对路径

  4. 像Map一样存取数据

  5. 获取web.xml中配置的上下文参数 context-param(属于整个web工程)

<context-param>
    <param-name>username</param-name>
    <param-value>root</param-value>
</context-param>
<context-param>
    <param-name>password</param-name>
    <param-value>123456</param-value>
</context-param>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ServletContext servletContext = getServletConfig().getServletContext();
    String username = servletContext.getInitParameter("username");
    System.out.println("context-param参数username的值是:"+username);
    String password = servletContext.getInitParameter("password");
    System.out.println("context-param参数password的值是:"+password);
}
  1. 获取当前工程路径,格式: /工程路径
System.out.println("当前工程路径:"+servletContext.getContextPath());
  1. 获取工程打包部署后在服务器硬盘上的绝对路径

    “ / ”表示打包后将工程的web目录解析为根目录,可以获取web目录下的任意绝对路径

System.out.println("当前工程绝对路径:"+servletContext.getRealPath("/"));
  1. 像Map一样存取数据

    servletContext.setAttribute("test",123);
    servletContext.getContext("test");
    

HTTP协议

客户端和服务器通信发送数据时需要遵守的规则

GET请求

  1. 请求行

    1. 请求的方式 GET
    2. 请求的资源路径(+ ?+请求参数)
    3. 请求的版本协议号 HTTP/1.1
  2. 请求头

    key:value 组成

GET /05_servlet/a.html HTTP/1.1
Host: localhost:8080
Connection: keep-alive
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=3765909C328781ED1C9F3041383D21B1; Idea-57bd47a4=5b0d8787-d44e-4ebb-b51b-eaf23a520394
If-None-Match: W/"359-1644928208251"
If-Modified-Since: Tue, 15 Feb 2022 12:30:08 GMT

POST请求

  1. 请求行

    1. 请求的方式 POST
    2. 请求的资源路径(+ ?+请求参数)
    3. 请求的版本协议号 HTTP/1.1
  2. 请求头

    key:value

    空行

  3. 请求体——发送给服务器的数据

POST /05_servlet/hello3 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 34
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Referer: http://localhost:8080/05_servlet/a.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=2FE995CA836DE7D806AB96F426096D81; Idea-57bd47a4=5b0d8787-d44e-4ebb-b51b-eaf23a520394

常用请求头

Accept:表示客户端可以接收的数据类型

Accept-Language:表示客户端可以接收的语言类型

User-Agent:表示客户端浏览器的信息

Host:表示请求时的服务器ip和端口号

常见请求

GET:

  1. form表单 method=get
  2. a标签
  3. link标签引入css
  4. script标签引入js
  5. img标签引入图片
  6. iframe引入html页面
  7. 浏览器地址栏输入地址访问

POST:

  1. form表单 method=post

HTTP响应报文格式

  1. 响应行

    1. 响应的协议/版本号
    2. 响应状态码
    3. 响应状态描述符
  2. 响应头

    key:value

    空行

  3. 响应体——服务器回传给客户端的数据

HTTP/1.1 200
Content-Length: 0
Date: Tue, 15 Feb 2022 15:02:37 GMT
Keep-Alive: timeout=20
Connection: keep-alive

常见状态码:

**200 OK:**表示从客户端发送给服务器的请求被正常处理并返回;

**301 Moved Permanently:**永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;

**302 Found:**临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;

**403 Forbidden:**服务器拒绝该次访问(访问权限出现问题)

**404 Not Found:**表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;

**500 Inter Server Error:**表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;

HttpServletRequest类

每当有请求到达Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析并封装到Request对象中,然后传递到service方法(doGet和doPost)中,我们可以通过HttpServletRequest对象,获取到请求的所有信息

常用方法

  • getRequestURI():获取请求的资源路径
  • getRequestURL():获取请求的统一资源定位符(绝对路径)
  • getRemoteHost():获取客户端ip
  • getHeader():获取请求头
  • getParameter():获取请求的参数
  • getParameterValues():获取请求的参数(多个值,比如checkbox)
  • getMethod():获取请求的方式GET或POST
  • setAttribute(key,value):设置域数据
  • getAttribute(key):获取域数据
  • getRequestDispatcher():获取请求转发对象
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("URI="+request.getRequestURI());
//        URI=/06_servlet/api
        System.out.println("URL="+request.getRequestURL());
//        URL=http://localhost:8080/06_servlet/api
        System.out.println("客户端ip地址="+request.getRemoteHost());

        System.out.println("请求头的User-Agent="+request.getHeader("User-Agent"));
//          请求头的User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36
    }

请求中文乱码解决

设置请求体的字符集为UTF-8,避免post请求的中文乱码问题

request.setCharacterEncoding("UTF-8");

注:在获取请求参数之前调用才有效

请求转发

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

请求转发不可以访问工程以外的资源,因为会将路径名开头默认解析为" /工程名 " + …

req.getRequestDispatcher("/xxx").forward(req,resp);

Base标签

在html的head标签中可以设置base标签

base标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转

HttpServletResponse类

与HttpServletRequest一样,每当有请求到达,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用,HttpServletRequest表示请求信息,HttpServletResponse表示响应信息,如果需要设置给客户端响应的信息,可以通过HttpServletResponse来设置

两个输出流

字节流:getOutputStream(),常用于下载文件(传递二进制数据)

字符流:getWriter(),常用于回传字符串(常用)

二者同时只能使用一个

给客户端响应字符串

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        writer.write("response's content");
    }

响应中文乱码解决

方式一(不推荐)

设置服务器字符集为UTF-8

response.setCharacterEncoding("UTF-8");

通过响应头,设置浏览器也使用UTF-8字符集

response.setHeader("Content-Type","text/html;charset=UTF-8");

方式二(推荐)

同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头

response.setContentType("text/html;charset=UTF-8");

请求重定向

方式一

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("访问到了Response1");
//        设置响应状态码302,表示重定向
        response.setStatus(302);
//        设置响应头,说明新的地址位置
        response.setHeader("Location","http://localhost:8080/06_servlet/response2");
    }

方式二(推荐)

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

四、JSP

jsp是java server pages,Java的服务器页面,代替Servlet程序回传html页面的数据

jsp页面本质上是一个Servlet程序,当第一次访问jsp页面时,Tomcat服务器会把jsp页面翻译成为一个java源文件,并对他编译为.class字节码程序

jsp翻译出来的java类,继承了HttpServlet类,即为一个Servlet程序

jsp头部的page指令

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

jsp的page指令可以修改jsp页面中一些重要的属性,或者行为

  1. language:表示jsp翻译后是什么语言文件,暂时只支持java

  2. contentType:表示jsp返回的数据类型,也就是源码中response.setContentType( )的参数值

  3. pageEncoding:表示jsp页面文件本身的字符集

  4. import:导包、导类

    以下两个属性是给out输出流使用

  5. autoFlush:设置当out输出流缓冲区满了之后,是否自动自动刷新缓冲区,默认值是true

  6. buffer:设置out缓冲区的大小,默认是8kb

  7. errorPage:当jsp页面运行出错时,自动跳转到的页面

  8. isErrorPage:设置当前jsp页面是否是错误信息页面,默认是false

  9. session:设置访问当前jsp页面,是否会创建HTTPSession对象,默认是true

  10. extends:设置jsp翻译出来的java类默认继承哪个类,

jsp常用脚本

1、声明脚本(极少使用)

格式: <%! java代码 %>

作用:可以给jsp翻译出来的java类定义属性和方法,还可以定义静态代码块和内部类

<%--1、声明类的属性--%>
   <%! private  int id;
        private String name;
        private static Map<String,Object> map;
   %>

<%--  2、声明静态代码块 --%>
<%!
    static {
        map = new HashMap<>();
        map.put("key1","value1");
        map.put("key2","value2");
    }
%>

<%--   3、声明类的方法--%>
<%!
    public int abc(){
        return 12;
    }
%>

<%-- 4、声明内部类  --%>
<%!
    public static class A{
        private int id = 12;
        private String abc = "abc";
    }
%>

2、表达式脚本

格式: <%=表达式%>

作用:在jsp页面上输出数据

特点:

  1. 表达式脚本会被翻译到_jspService方法中,

  2. 会被翻译到out.print()输出到页面上

  3. _jspService方法中的对象都可以直接使用

  4. 表达式不能以分号结束

<%=12%>
<%=12.12%>
<%="我是字符串"%>
<%=map%>

3、代码脚本

格式: <% java语句 %>

作用:在jsp页面中,用java语句编写需要的功能

特点:

  1. 代码脚本翻译之后都在_jspService()方法中
  2. 在_jspService()方法中的现有对象都可以直接使用,如request、response
  3. 多个代码脚本块可以组合拼接为一个完整的java语句
  4. 代码脚本可以和表达式脚本一起组合使用,在jsp页面上输出数据

jsp九大内置对象

在Tomcat翻译jsp页面为Servlet源代码后,内部提供的九大内置对象

  1. request ——请求对象
  2. response——响应对象
  3. pageContext——jsp上下文对象
  4. session——会话对象
  5. application——ServletContext对象
  6. config ——ServletConfig对象
  7. out——jsp输出流对象
  8. page——指向当前jsp的对象
  9. exception——异常对象

jsp四大域对象

九大内置对象中包括四个域对象

域对象是可以像Map一样存取数据的对象

  1. pageContext——(PageContextImpl类),在当前jsp页面范围内有效
  2. request——(HttpServletRequest类),在一次请求内有效
  3. session——(HttpSession类),在一次会话范围内有效(打开浏览器访问服务器直到关闭浏览器)
  4. application——(ServletContext类),整个web工程范围内都有效(只要web工程不停止,数据都在)

四个域对象功能一样,而存取数据的范围不同

存:setAttribute(key, value)

取:getAttribute(key)

使用的优先顺序是数据范围从小到大的顺序

pageContext——request——session——application

out和response区别

out.write(123);
response.getWriter().write(123);

当jsp页面中所有代码执行完毕后会做以下两个操作:

  1. 执行out.flush()操作,把out缓冲区中的数据追加写入到response缓冲区末尾
  2. 执行response的刷新操作,把全部数据写给客户端

由于jsp翻译之后,底层源代码都是使用out进行输出,所以在jsp中通常用out来输出,以免打乱页面输出内容的顺序

out.write()输出字符串

out.print()可以输出任意类型数据,(都转换为字符串后调用write输出)

结论:可以统一使用out.print()进行输出

常用标签

1、静态包含

  • 格式

    <%@ include file = " " %>
    

    file属性指定要包含的jsp页面路径,地址中第一个斜杠 / 表示为http://ip:port/工程路径/ 映射到代码的web目录

  • 特点

    静态包含不会翻译被包含的jsp页面

    其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出

2、动态包含

  • 格式

    <jsp:include page = " "> </jsp:include >
    

    page属性指定要包含的jsp页面路径

  • 特点

    1. 动态包含会把被包含的jsp页面也翻译为java代码

    2. 底层代码使用如下代码去调用被包含的jsp页面执行输出

      JspRuntimeLibrary.include(request, response, "/include/foot.jsp", out, false);
      
    3. 动态包含还可以传递参数

      <jsp:include page="/include/foot.jsp">
          <jsp:param name="name" value="root"/>
      </jsp:include>
      

3、请求转发

  • 格式

    <jsp:forward page=""></jsp:forward>
    

    page属性指定请求转发的路径

练习

输出九九乘法表

<table style="border: 1px solid;margin: 0 auto;">
    <%for (int i = 1; i <= 9; i++) {%>
     <tr>
    <%for (int j = 1; j <= i; j++) {%>
         <td><%out.print(j+"*"+i+"="+j*i+"\t");%>
         </td>
    <%}%>
     </tr>
    <%}%>
</table>

请求转发练习

get请求Servlet,Servlet查询数据库并将结果集保存到request域,请求转发给jsp页面显示

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        获取请求的参数
//        发sql语句查询学生信息,用for循环模拟
        List<Student> studentList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            int t = i+1;
            studentList.add(new Student(t, "name"+t, 18+t, "phone"+t));
        }
//        保存查询结果到request域
        req.setAttribute("stuList",studentList);
//        请求转发到showStudent.jsp页面
        req.getRequestDispatcher("/showStudent.jsp").forward(req,resp);

    }

showStudent.jsp

<table>
    <tr>
        <th>编号</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>电话</th>
        <th>操作</th>
    </tr>
    <%for(Student stu : studentList){%>
    <tr>
        <td><%=stu.getId()%></td>
        <td><%=stu.getName()%></td>
        <td><%=stu.getAge()%></td>
        <td><%=stu.getPhone()%></td>
        <td>修改/删除</td>
    </tr>
    <%}%>
</table>

五、Listener监听器

  • Listener监听器是JavaWeb的三大组件之一(Servlet程序、Filter过滤器、Listener监听器)

  • Listener是JavaEE的规范,就是接口

  • 作用:监听某种事物的变化,通过回调函数,返回给客户(程序)去执行相应的处理

ServletContextListener监听器

  • ServletContextListener可以监听ServletContext对象的创建和销毁

  • ServletContext对象在web工程启动时创建,在web工程停止时销毁

在监听到创建和销毁后会分别调用相应方法进行反馈

两个回调方法分别为:

public interface ServletContextListener extends EventListener {
    //在ServletContext对象创建之后马上调用,做初始化
    default void contextInitialized(ServletContextEvent sce) {
    }
	
    //在ServletContext对象销毁之后调用
    default void contextDestroyed(ServletContextEvent sce) {
    }
}

使用监听器监听ServletContext对象的方法步骤:

  1. 编写一个类,实现ServletContextListener
  2. 实现两个回调方法
  3. 在web.xml中配置监听器

1、2

public class MyServletContextListenerImpl  implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext对象被创建了!");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext对象被销毁了!");
    }
}

3、web.xml下添加配置

<!--   配置监听器 -->
    <listener>
        <listener-class>com.atguigu.listener.MyServletContextListenerImpl</listener-class>
    </listener>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值