servlet介绍及使用

Servlet

简介

Servlet就是sun公司用于开发动态web的一门技术。sun公司在这些API中提供了一个接口叫做:Servlet。如果你想开发一个Servlet程序,只需要完成两个小步骤:
1、编写一个类实现Servlet接口
2、把开发好的java类部署到web服务器中。
把实现了Servlet接口的java程序叫做Servlet,本质还是Java

HelloServlet

Servlet接口在sun公司有两个默认的实现类:HttpServlet、GenericServlet

Servlet原理

Servlet是由web服务器调用,web服务器在收到浏览器请求后,就有以下的方法去请求和响应:

在这里插入图片描述

Servlet实现

  • 构建一个Maven项目,删除src目录,在这个目录下创建Moudel,这个空的工程就是Maven主工程。

  • 关于Maven父子工程的理解

    父项目中会有

    <modules>
    	<module>servlet-01</module>
    </modules>
    
  • 子项目中会有

     <parent>
        <groupId>com.louis</groupId>
        <artifactId>kuang</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    

    父项目中的java再子项目中可以直接使用。

  • Maven环境优化

    1、修改web.xml为最新

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0"
             metadata-complete="true">
    </web-app>
    

    2、将Maven的结构搭建完整

  • 编写一个Servlet程序

    一个Servlet程序一定要实现一个Servlet接口。方法如下

    1、编写一个普通类

    2、实现Servlet接口,我们可以直接继承HttpServlet

    package com.louis.servlet;
    
    		import javax.servlet.ServletException;
    		import javax.servlet.ServletOutputStream;
    		import javax.servlet.http.HttpServlet;
    		import javax.servlet.http.HttpServletRequest;
    		import javax.servlet.http.HttpServletResponse;
    		import java.io.IOException;
    		import java.io.PrintWriter;
    
    		/**
    		 * @author XRY
    		 * @date 2023年04月29日20:18
    		 */
    		public class HelloServlet extends HttpServlet {
    		    //由于get和post只是请求实现的方式不同,可以相互调用,业务逻辑都一样。
    		    @Override
    		    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		//        ServletOutputStream outputStream = resp.getOutputStream();
    		        PrintWriter writer = resp.getWriter();
    		        writer.println("Hello Servlet!");
    		    }
    
    		    @Override
    		    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		        super.doPost(req, resp);
    		    }
    		}
    
  • 编写Servlet的映射

    由于我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0"
             metadata-complete="true">
    <!--    注册Servlet-->
        <servlet>
            <servlet-name>hello</servlet-name>
            <servlet-class>com.louis.servlet.HelloServlet</servlet-class>
        </servlet>
    <!--    Servlet的请求路径-->
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • 配置Tomcat

  • 启动测试

web.xml中Mapping问题

  • 一个Servlet可以指定一个映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  • 一个Servlet可以指定多个路径

    <!--Servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    
  • 一个Servlet可以指定通用映射路径(默认请求路径)

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    
  • 可以指定一个后缀或者前缀等

    <!--    Servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.louis</url-pattern>
    </servlet-mapping>
    

    在这里插入图片描述

​ *注意:前面不能加项目映射到的路径。

  • 优先级问题

    制定了固有的映射路径,优先级最高,如果找不到就会走默认的处理请求。

ServletContext

web容器启动的时候,它会为每一个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用,可以用来实现数据共享。

共享数据

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

  • 存放数据类
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    System.out.println("你好!");

//        this.getInitParameter()   初始化参数
//        this.getServletConfig()   Servlet配置
//        this.getServletContext()  Servlet上下文

    ServletContext servletContext = this.getServletContext();
    String name = "louis";
    servletContext.setAttribute("name",name);//将一个数据保存在ServletContest中,名字为name,值为name

}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    super.doPost(req, resp);
}
}
  • 取数据的类
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html");
    ServletContext servletContext = this.getServletContext();
    String name = (String)servletContext.getAttribute("name");
    resp.getWriter().println("名字"+ name);
    System.out.println();
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    super.doPost(req, resp);
}
}
  • 配置web.xml
<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>khan.louis.test.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/test</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>getc</servlet-name>
    <servlet-class>khan.louis.test.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>getc</servlet-name>
    <url-pattern>/getc</url-pattern>
</servlet-mapping> 

数据转发

ServletContext还可以实现数据的转发功能。

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    System.out.println("进入了Demo01");
//        RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/getc");//转发的请求路径
//        requestDispatcher.forward(req,resp);//调用forward实现请求转发
    servletContext.getRequestDispatcher("/getc").forward(req,resp);
}

读取资源文件

Properties
在resources目录下新建properties(如果不存在,可能就是maven出现资源导出失败的问题,为了解决这个我问题,我们可以在build中配置resources。)
发现:他们都被打包到了classes路径下,我们俗称这个路径为classpath

package khan.louis.test;


import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * @author XRY
 * @date 2023年05月02日16:53
 */
public class PropertiesServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties properties = new Properties();
        properties.load(resourceAsStream);
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        resp.getWriter().print(username + "<>" + password);

    }

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

HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表这个请求的HttpServletRequest对象,代表响应的HttpServletResponse对象;
如果要获取客户端请求过来的参数需要找HttpServletRequest,
如果给客户端响应一些信息使用HttpServletResponse

类中方法的简单分类

负责向浏览器发送数据的方法
public ServletOutputStream getOutputStream() throws IOException;//写平常的流使用
public PrintWriter getWriter() throws IOException;//写中文使用
负责向浏览器发送响应头的方法
public void setCharacterEncoding(String charset);
public void setContentLength(int len);
public void setContentLengthLong(long len);
public void setContentType(String type);
public void setDateHeader(String name, long date);
public void addDateHeader(String name, long date);
public void setHeader(String name, String value);
public void addHeader(String name, String value);
public void setIntHeader(String name, int value);
public void addIntHeader(String name, int value);
响应状态码
public int getStatus();

常见应用

  1. 向浏览器输出信息

  2. 下载文件

    ①要获取下载文件的路径

    ②下载的文件名

    ③设置让浏览器能够支持下载问哦们需要的东西

    ④获取下载文件的输入流

    ⑤创建缓冲区

    ⑥获取OutputStream对象

    ⑦将FileOutStream流写到buffer缓冲区,使用OutputStream将缓冲区数据输出到客户端。

package khan.louis.test;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author XRY
 * @date 2023年05月02日17:43
 */
public class TestResponse extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //①要获取下载文件的路径
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        String realPath = "servlet-02\\src\\main\\resources\\图片1.png";
    //        G:\练习库\coding\JAVAIDEA\javaweb\kuang\servlet-02\src\main\resources\图片1.png
        System.out.println("下载的文件路径为:" + realPath);
    //		②下载的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
    //		③设置让浏览器能够支持"Content-Disposition"下载我们需要的东西
        resp.setHeader("Content-Disposition","attachment;filename=" + fileName);
    //		④获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
    //		⑤创建缓冲区
        int len = 0;
        byte[] buffer = new byte[1024];
    //		⑥获得OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
    //		⑦将FileOutStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
        while((len = in.read(buffer))>0){
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
    }

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

验证码功能

验证码怎么来的?
前端实现
后端实现: 需要用到java的图片类,生成一个图片

package khan.louis.test;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * @author XRY
 * @date 2023年05月03日15:50
 */
public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //如何让浏览器5秒自动刷新一次
        resp.setHeader("refresh", "3");
        //在内存中创建图片
        BufferedImage bufferedImage = new BufferedImage(100,20,BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();//画笔
        //设置图片的背景颜色
        graphics.setColor(Color.white);
        graphics.fillRect(0,0,100,20);
        //给图片写数据
        graphics.setColor(Color.BLUE);
        graphics.setFont(new Font(null, Font.BOLD, 20));
        graphics.drawString(makeNum(),0, 20);
        //告诉浏览器这个请求使用图片的方式打开
        resp.setContentType("image/jpeg");
        //网站存在缓存,不让浏览器缓存
        resp.setDateHeader("expires", -1);
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("Pragma", "no-cache");

        //把图片写给浏览器
        ImageIO.write(bufferedImage,"jpg",resp.getOutputStream());
    }
    //生成随机数
    private String makeNum(){
        Random random = new Random();
        String s = random.nextInt(99999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7-s.length(); i++) {
            sb.append("0");
        }
        s = sb.toString() + s;
        return s;
    }

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

重定向

一个web资源收到客户端请求后,它会通知客户端去访问另一个web资源,这个过程叫做重定向
常见场景:
用户登录

package khan.louis.test;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author XRY
 * @date 2023年05月03日16:32
 */
public class TestRedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("/servlet/image");
    }

}
重定向实现步骤

重定向resp.sendRedirect(“”);主要实现了下面的两个步骤:

resp.setHeader("Location", "/servlet/image");
resp.setStatus(302);
实例
<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径,需要找到项目的路径--%>
<%--${pageContext.request.contextPath}代表当前的项目--%>
<meta charset="UTF-8">
<form action="${pageContext.request.contextPath}/login" method="get">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit">
</form>
</body>
</html>
    
package khan.louis.test;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author XRY
 * @date 2023年05月03日16:47
 */
public class RequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //处理请求
       String username = req.getParameter("username");
       String pwd = req.getParameter("password");
        System.out.println(username + " \n" + pwd);
        //重定向一定要注意路径问题,否则404
        resp.sendRedirect("/servlet/success.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}
<%--
  Created by IntelliJ IDEA.
  User: XRY
  Date: 2023/5/3
  Time: 17:04
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>success</h1>
</body>
</html>

HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息。

在这里插入图片描述

在这里插入图片描述

获取前端传递的参数、请求转发

在这里插入图片描述

getParameter(String s);//返回单个
getParameterValues(String s);//返回多个

示例

<%@ page contentType="text/html; charset=gb2312"%>
<html>
<head>登录</head>
<body>
<h2>登录</h2>
<%--表单表示的意思:以post方式提交表单,提交到我们的login请求--%>

<form action="${pageContext.request.contextPath}/login" method="post">
    <meta charset="UTF-8">
    <div style="text-align: center">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        爱好:
        <input type="checkbox" name="hobby">女孩
        <input type="checkbox" name="hobby">代码
        <input type="checkbox" name="hobby">唱歌
        <input type="checkbox" name="hobby">电影
        <br>
        <input type="submit">
    </div>
</form>
</body>
</html>
package khan;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

/**
 * @author XRY
 * @date 2023年05月03日19:10
 */
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] parameterValues = req.getParameterValues("hobby");
        System.out.println("===================================");
        System.out.println(username + "\t" + password);
        System.out.println(Arrays.toString(parameterValues));
//        resp.sendRedirect("/request/success.jsp");
        //通过请求转发
        //这里的 / 代表类当前的web应用
        req.getRequestDispatcher("/success.jsp").forward(req, resp);
        req.setCharacterEncoding("UTF-8");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
//success.jsp
<%--
  Created by IntelliJ IDEA.
  User: XRY
  Date: 2023/5/3
  Time: 19:25
  To change this template use File | Settings | File Templates.
--%>
<%@ page  language="java" contentType="text/html;charset=utf-8" pageEncoding="utf-8"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>

面试题:请你聊聊重定向和转发的区别?
相同点:
两者都会实现页面的跳转
不同点:
请求转发的时候,url不会产生变化 307
重定向的时候,url地址栏会发生变化 302

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值