语法篇·Servlet基础

一、初识Servlet

1.1简介

Servlet是一种使用Java语言来开发动态网站的技术。Servlet是运行在Web服务器或应用服务器上的程序,它是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。Servlet可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页

1.2步骤

Sun在这些API中提供一个接口叫做: Servlet, 如果你想开发一个Servlet程序, 只需要完成两个小步骤:

  • 编写一个类,实现Servlet接口
  • 把开发好的Java类部署到web服务器中。

1.3Servlet映射

Servlet映射是指将Servlet类与URL(前端访问服务器的链接)一一对应的过程。Servlet映射可以通过XML文件或注解的方式进行配置

XML文件方式

XML文件方式:在web.xml文件中,使用<servlet>元素和<servlet-mapping>元素来定义Servlet类和URL的对应关系

<servlet>
  <servlet-name>MyServlet</servlet-name>
  <servlet-class>com.example.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>MyServlet</servlet-name>
  <url-pattern>/myServlet</url-pattern>
</servlet-mapping>

这样就将com.example.MyServlet类映射到了/myServlet这个URL上,客户端可以通过http://localhost:8080/myServlet来访问这个Servlet

注解方式

注解方式:在Servlet类上,使用@WebServlet注解来指定URL的对应关系

@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {
  // ...
}

这样就将MyServlet类映射到了/myServlet这个URL上,客户端可以通过http://localhost:8080/myServlet来访问这个Servlet

多重映射

注意,一个Servlet可以被映射到多个URL上,也就是多重映射

<servlet>
  <servlet-name>MyServlet</servlet-name>
  <servlet-class>com.example.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>MyServlet</servlet-name>
  <url-pattern>/myServlet</url-pattern>
  <url-pattern>/myServlet2</url-pattern>
</servlet-mapping>

或者

@WebServlet({"/myServlet", "/myServlet2"})
public class MyServlet extends HttpServlet {
  // ...
}

这样就将MyServlet类映射到了/myServlet和/myServlet2两个URL上,客户端可以通过http://localhost:8080/myServlet或http://localhost:8080/myServlet2来访问这个Servlet

1.4Servlet原理

Servlet和容器:

Servlet是一个Java类,它实现了javax.servlet.Servlet接口,用来处理客户端的请求和响应。Servlet需要运行在一个支持Java Servlet规范的容器中,例如Tomcat、Jetty等。容器负责加载、初始化、调用和销毁Servlet,以及提供一些服务和资源给Servlet 

Servlet生命周期

Servlet的生命周期是指从Servlet被创建到被销毁的过程,它包括以下几个阶段:


初始化:当容器第一次收到对某个Servlet的请求时,它会加载并实例化这个Servlet,并调用它的init()方法进行初始化工作。这个方法只会被调用一次,在整个生命周期中。


服务:当容器收到对某个Servlet的请求时,它会调用它的service()方法来处理这个请求,并生成一个响应。这个方法会被调用多次,每次请求都会执行这个方法。service()方法会根据请求的HTTP方法(GET、POST、PUT、DELETE等)来调用相应的doGet()、doPost()、doPut()、doDelete()等方法。


销毁:当容器决定卸载某个Servlet时,它会调用它的destroy()方法来释放资源并执行清理工作。这个方法只会被调用一次,在整个生命周期的最后。

Servlet映射

Servlet映射是指将Servlet类与URL(前端访问服务器的链接)一一对应的过程

Servlet映射可以通过XML文件或注解的方式进行配置

注意

Servlet请求和响应

当客户端发送一个HTTP请求到服务器时,容器会创建一个javax.servlet.ServletRequest对象和一个javax.servlet.ServletResponse对象,并传递给对应的service()方法。

ServletRequest对象封装了客户端发送的数据,包括参数、属性、头信息、cookie等。

ServletResponse对象封装了服务器返回的数据,包括状态码、头信息、cookie、输出流等。

如果是HTTP协议,那么ServletRequest和ServletResponse对象会被转换为javax.servlet.http.HttpServletRequest和javax.servlet.http.HttpServletResponse对象,提供更多的HTTP相关的方法和属性

1.5Log(日志)

Log(日志),记录应用运行的事件信息,统计系统运行情况,高效定位追踪问题,等等

  • 执行状态的变化
  •  系统入口/出口
  • 业务异常
  • 非预期执行
  • 特定程序运行时间
  • 执行进度
  • … …

java.util.logging.Logger,Java提供的简单日志工具,仅会使用info()方法即可。后期课程使用功能更强大的日志框架

1.6@WebServlet

二、Servlet入门 

2.0GET与POST

post请求以相同的语法提供参数,只是它位于请求的“body”部分,因此用户很难看到 Post请求,参数封装在请求体,而非请求地址

2.1ServletContext

共享数据·

我在这个Servlet中保存的数据,可以在另外一个servlet中拿到;

获取初始化参数

请求转发

读取资源文件 

2.2HttpServletResponse响应

HttpServletResponse是一个接口,它用于封装HTTP响应消息,简称response对象。它有一些方法可以设置响应的状态码,响应头,响应正文和重定向等功能。

负责向浏览器发送数据的方法

  • 可以使用response.getWriter()方法来获取一个PrintWriter对象,用于向客户端发送字符文本,例如HTML标签或纯文本。
  • 也可以使用response.getOutputStream()方法来获取一个ServletOutputStream对象,用于向客户端发送字节数据,例如图片,音频,视频等二进制文件。

负责向浏览器发送响应头的方法

  • 设置响应的字符集,可以使用response.setContentType()方法来指定content-type响应头,例如response.setContentType(“text/html;charset=utf-8”)。
  • 实现页面的自动刷新或跳转,可以使用response.setHeader()方法来设置Refresh响应头,例如response.setHeader(“Refresh”,“5;URL=www.baidu.com”)。

Response下载文件

Servlet部分

package com.web;

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


import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

@WebServlet("/down")
public class Servlet extends HttpServlet {

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

        // 获取下载文件的路径
        String filename = req.getParameter("filename");
        System.out.println(filename);
        String path = this.getServletContext().getRealPath("/dowmload/" + filename);
        // 获取下载文件的文件名
        filename = URLEncoder.encode(filename, "UTF-8"); // 处理中文文件名乱码问题
        // 设置响应头,告诉浏览器要以下载的形式打开文件
        resp.setHeader("content-disposition", "attachment;filename=" + filename);
        // 设置响应内容类型为二进制流
        resp.setContentType("application/octet-stream");
        // 获取下载文件的输入流
        FileInputStream in = new FileInputStream(path);
        // 创建缓冲区
        byte[] buffer = new byte[1024];
        int len = 0;
        // 获取输出流
        OutputStream out = resp.getOutputStream();
        // 将输入流中的数据写入缓冲区,再从缓冲区写入输出流
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        // 关闭输入流和输出流
        in.close();
        out.close();
    }
    }


JSP部分

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>下载</title>
</head>
<body>
<a href=${pageContext.request.contextPath}/down?filename=1.jpg>1.jpg</a><br>
<a href=${pageContext.request.contextPath}/down?filename=2.txt>2.txt</a><br>
</body>
</html>

href属性应该是"/down?filename=文件名",而不是"dowmload/文件名",这样才能调用你的Servlet类

/down?是一个URL,它表示要访问的Servlet类的路径和参数。/down表示你的Servlet类的注解@WebServlet(“/down”),它告诉服务器这个类的映射路径。?表示后面跟着的是参数,比如filename=文件1.txt,这个参数会被传递给你的Servlet类的doGet方法,然后你可以通过req.getParameter(“filename”)获取这个参数的值。

Response验证码

package com.web;

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

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/img")
public class Servlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //如何让浏览器5秒刷新一次?
        resp.setHeader("refresh","3");
        //在内存中创建图片
        BufferedImage image = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB);
        //开始画图
        Graphics2D g=(Graphics2D) image.getGraphics();
        //设置图片背景颜色
        g.setBackground(Color.white);
        g.fillRect(0,0,100,50);
        //写入验证码
        g.setColor(Color.GREEN);
        g.setFont(new Font(null, Font.PLAIN,20));
        g.drawString(makeNumber(),0,25);
        //高速浏览器,这个请求用图片的方式打开
        resp.setContentType("image/png");
        //设置不让浏览器缓存图片
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Program","no-cache");
        //把图片写给浏览器
        boolean write = ImageIO.write(image,"png", resp.getOutputStream());
    }
    //生成随机数
    private String makeNumber(){
        Random r = new Random();
        String num=r.nextInt(99999999)+"";
        StringBuffer sBuffer = new StringBuffer();
        for (int i = 0; i < 8-num.length(); i++) {
            sBuffer.append("x");
        }
        return sBuffer.toString()+num;
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

Response实现重定向

重定向的概念是指通过各种方法将网络请求重新定向到其他位置,比如网页重定向、域名重定向等。重定向的原理是服务器向请求发送一个特殊的响应,包含一个状态码和一个新的URL。浏览器收到响应后,会自动加载新的URL。重定向有不同的类型和应用场景,比如永久重定向、临时重定向、域名别称、站点迁移等

public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/r/img");//重定向
//拆分
/*
resp.setHeader("Location","/r/img");
resp.setStatus(302);
*/
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}

补充

登录判断 

package com.web;

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;

import java.io.IOException;

@WebServlet("/login")
public class Servlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入这个请求");
        //处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
        //重定向一定要注意路径问题
        if (username.equals("admin") && password.equals("123456")){
            System.out.println("登陆成功");
            //请求转发
            //转发:服务器把这个请求转向另外一个Servlet去处理; (地址栏不会变)
            //RequestDispatcher ,需要使用RequestDispatcher来进行处理,我们需要获得这个类,参数为要转发到的页面
           req.getRequestDispatcher("/success.jsp").forward(req,resp);
        }else {
            req.getRequestDispatcher("/fail.jsp").forward(req,resp);
        }

    }

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

    }
}

 面试题:重定向与转发的区别

  • 相同点
    页面都会跳转
  • 不同点
    请求转发的时候,url不会产生变化
    重定向的时候,url地址栏会发生变化

 2.3会话

  • 概念

    在Web中,会话表示从浏览器打开某个网站,在这个网站中无论操作了什么,直到关闭浏览器,这一个过程,称之为一个会话。

  • 怎样算会话结束

    • 客户端关闭了
    • 服务器销毁了
  • 为什么要处理会话

    长期保持会话,无论用户关闭多少次浏览器,这个会话都存在(如虎牙的一个月免登录)

  • 保存会话的两种机制

    • Cookie:

      Cookie是客户端机制,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了

      好比超市给用户的会员卡,下次带去就知道之前来过

    • Session

      Session是服务器端技术,利用这个机制,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

      好比超市在自己的系统上保存了用户的信息,用户下次去直接说会员名就行

2.3.1Cookie

cookie: - -般会保存在本地的用户目录下appdata;

构造器: 

Cookie cookie = new Cookie(String name,String value);

服务器响应Cookie给客户端:

response.addCookie(Cookie);

 服务器查看用户带来的请求是否有Cookie

Cookie[] cookies = Request.getCookie();
//可以使用cookie来验证用户是否来过
//判断cookies是否为空,然后遍历即可
Cookie.getName();
Cookie.getValue();

Cookie测试用户是否来过

package com.example01;

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

@WebServlet("/c1")
public class ResponseHTMLServlet extends HttpServlet {
    Boolean flag = false;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //避免乱码问题:
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        System.out.println("1");
        //通过请求获取用户的Cookie
        Cookie[] cookies = req.getCookies();
        if (flag){
            //flag=true,表示用户不是第一次访问该url
            if (cookies!=null){
                //你有cookie

                for (int i = 0; i < cookies.length ; i++) {
                    Cookie cookie = cookies[i];
                    if (cookie.getName().equals("lastLoginTime")){
                        long lastLoginTime = Long.parseLong(cookie.getValue());
                        Date date = new Date(lastLoginTime);
                        resp.getWriter().println("你上一次来的时间为:"+cookie.getValue());
                        out.write(date.toString());
                    }
                }
            }
        }else {

            //flag=false,表示用户是第一次访问该url
            out.write("这是您第一次访问该页面");
        }
        //建立一个cookie,并把这个cookie发给客户端
        resp.addCookie(new Cookie("lastLoginTime",System.currentTimeMillis()+""));
        //将flag置为true,当用户再次访问该url时,会直接进入读取cookie的逻辑
        flag = true;
    }


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

    }

}

2.3.2Session

Session服务器端技术默认情况下,一个浏览器独占一个session对象。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。可以通俗的理解为,一个用户可以通过一个Session访问多个Web资源,且各个Web资源可以通过Session读取保存的用户数据。

Session实现原理:服务器创建session出来后,会把session的id号,cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着sessionid号去,服务器通过识别客户机浏览器的session_id,就会使用内存中与之对应的session为之服务。

事实上,只要客户端一旦连接上服务器,服务器就会自动产生Session,Session可以在一个会话中传递数据(即多个程序通过session获取数据),如果服务器重启,存储在session中的数据就会丢失

获取Session对象

如何注销Session?

session对象默认30分钟没有使用,则服务器会自动销毁session

可以使用以下两种方式注销Session:

  • 需要在程序中手动设置Session失效时,通过invalidate();注销当前Session。
request.getSession().invalidate();
  • web.xml文件中配置session的失效时间 :
<!-- 设置Session的有效时间:以分钟为单位-->
<session-config>
    <session-timeout>15</session-timeout>
</session-config>

使用场景:
●保存一个登录用户的信息;
●购物车信息;
●在整个网站中经常会使用的数据,我们将它保存在Session中;

Session和cookie的区别 

Cookie是把用户的数据写给用户的浏览器,属于客户端技术

Session是把用户的数据写到用户独占的session中,属于服务端技术

Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。

2.3.3作用域

 

2.4PrintWriter

PrintWriter是一个用于创建和写入文件的 Java 类。它可以用来输出不同类型的数据,从基本类型如数字、文本,到数组和对象 

package com.example01;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/example01/responsehtml")
public class ResponseHTMLServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter()
                .append("<!DOCTYPE html>\n")
                .append("<html\">\n")
                .append("<head>\n")
                .append("<meta charset=UTF-8>\n")
                .append("<title>Web开发技术</title>\n")
                .append("</head>\n")
                .append("<body><h1>Web开发技术</h1></body></html>");
    }
}

举例

package com.example01;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/responsehtml")
public class ResponseHTMLServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.print("hello");

    }
}

猜你喜欢

转载自blog.csdn.net/qq_62377885/article/details/131339062