JavaWeb-3、Servlet

1、Servlet简介

Servlet(Server Applet),全称Java Servlet。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

2、HelloServlet

好了,废话不多说,我们先写一个简单的小DEMO看看Servlet如何使用!

首先我们创建maven一个项目,模板选择webapp模板。

在这里插入图片描述

稍微标记一下各个文件夹!
在这里插入图片描述
导入一下jsp和servlet的相关依赖。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.1</version>
</dependency>

现在我们创建一个类,此类继承一下HttpServlet类。

在上文中我们提到,一个类实现servlet接口即可成为一个广义的Servlet类。

我们点开httpservlet的源码康康,我们可以发现httpservlet又继承了GenericServlet,GenericServlet又实现了servlet接口。

在这里插入图片描述

所以我们的类结构是这样的:
在这里插入图片描述

我们在我们的实现类上实现下doget和dopost方法。

一般表单是使用post方法进行提交,这里我们使用doget方法即可!

以下是具体代码。

public class helloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //拿一下输出流
        PrintWriter writer = resp.getWriter();
        //在网页上打一个hello servlet!
        writer.println("hello servlet!");
    }
    
    
//这个暂时不用
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

之后我们要在相关的web.xml上配置servlet

<servlet>
<!--    名字-->
    <servlet-name>hello-servlet</servlet-name>
    <!--    servlet对应的类-->
    <servlet-class>helloServlet</servlet-class>
</servlet>
<!--    映射标签-->
<servlet-mapping>
<!--    对应的servlet名字-->
    <servlet-name>hello-servlet</servlet-name>
<!--    项目url-->
    <url-pattern>/jj</url-pattern>
</servlet-mapping>

这里我们把这个servlet类命名为hello-servlet,他要访问项目下的jj来访问。

配置下tomcat,把项目访问目录设为/jj,启动运行下!

在这里插入图片描述

完美无瑕!

3、servlet原理

下面引用b站狂神老师的一张图结合着聊一聊
在这里插入图片描述

当我们的浏览器给web容器发送请求时,主要进行了以下的步骤操作:

  1. 判断是否为首次访问,如是首次访问则创建相关servlet类
  2. 将网页的请求以及相应交给我们编写的servlet类
  3. 执行类中的方法
  4. web容器读取响应的信息,然后返回给客户端。

4、mapping问题

在这里我们可以创建以下几种映射

1、单映射

这种就是我们平时最常用的,一个页面对应一个映射的写法

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

2、多映射

我们可以为一个页面设置多个映射,比如说我们把/jj2也设置为hello-servlet的映射,这种方式也是可以的。

<servlet-mapping>
    <servlet-name>hello-servlet</servlet-name>
    <url-pattern>/jj</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello-servlet</servlet-name>
    <url-pattern>/jj2</url-pattern>
</servlet-mapping>   

3、全局映射

我们可以通过正则表达式设置全局映射。

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

4、后缀映射

<servlet-mapping>
    <servlet-name>hello-servlet</servlet-name>
    <url-pattern>*.jj</url-pattern>
</servlet-mapping>

我们可以以.jj结尾的方式映射hello–servlet,注意这种写法前面不能加路径,比如说不能/*.jj这种写法。

5、servletContext

​ ServletContext官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。

也就是说,不管我们项目里拥有多少servlet的类,但是项目中却只有一个servletContext,servletContext一般可以用来执行以下操作。

(1)数据共享

我们平常可以使用servletContext进行数据共享的操作,下面我们来举一个例子。

首先先写两个servlet类,并将其注册到web.xml中。

public class FirstServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取servletContext
        ServletContext servletContext = this.getServletContext();
//        在其中设置username属性
        servletContext.setAttribute("username","dirtyLily");
        System.out.println("设置ok");
    }
}
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;

public class SecondServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ServletContext servletContext = this.getServletContext();
        //获取servletContext中的username属性
        String username = (String) servletContext.getAttribute("username");
        //设置一下页面格式以及编码等信息
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().println("名字是:"+username);

    }
}

配置tomcat,依次运行二者。
在这里插入图片描述

最后发现第二个servlet可以调取第一个servlet中设置的属性,这就是二者传值的一些操作。

(2)获取初始参数

这里我们先在web.xml中定义一个参数

<context-param>
    <param-name>user</param-name>
    <param-value>zjj</param-value>
</context-param>

之后编写一个servlet类

public class ThirdServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        //获取名字叫user的初始化参数
        String user = servletContext.getInitParameter("user");
        resp.getWriter().println(user);
    }
}

注册下servlet,我们运行一下发现,可以取到相关参数。
在这里插入图片描述
(3)请求转发

在servlet中如果我们希望在访问一个界面时自动跳转到另一个界面,我们可以使用servlet中请求转发的功能。

我们可以使用servlet中的getRequestDispatcher方法来定义转发的地址,之后调用forward完成跳转,具体代码如下:

public class FourthServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        //跳转到third
        servletContext.getRequestDispatcher("/third").forward(req,resp);

    }
}

注册下,运行结果为
在这里插入图片描述
我们发现上面的url地址依然是fourth,但是内容是third的内容。

(4)获取资源文件

我们首先在resource文件夹里定义一个properties文件,里面写一个属性。

handSomeboy=zjj

编写一个servlet类来读取这个properties

public class FifthServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        //读取流文件
        InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/jj.properties");
        Properties prop = new Properties();
        //载入
        prop.load(resourceAsStream);
        String handSomeboy = prop.getProperty("handSomeboy");
        resp.getWriter().println(handSomeboy);
    }
}

最后输出的结果

在这里插入图片描述

ok的!

6、HttpServletResponse

在servlet中主要分为请求HttpServletRequest,以及HttpServletResponse两种。

在Response中,我们在其中执行一些操作。

(1)使用response下载文件

使用response可以对我们电脑中的资源进行下载。主要步骤以及代码如下:

首先先创建一个servlet类

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
//        1、获取下载文件路径
        String path = "E:\\code\\servlet\\3Responce\\src\\main\\resource\\xjn.jpg";
        System.out.println(path);
        //2、获取文件名
        //最后一个\后面开始就是文件名
        String name = path.substring(path.lastIndexOf("\\") + 1);
        //3、设置浏览器支持
        resp.setHeader("Content-Disposition", "attachment;filename="+name);
        //4、获取输入流
        FileInputStream inputStream = new FileInputStream(path);
        //5、创建缓冲区
        byte[] buffer = new byte[1024];
        //6、获取outputstream
        ServletOutputStream os = resp.getOutputStream();
        //7、写入
        int len;
        while((len=(inputStream.read(buffer)))!=-1){
            os.write(buffer,0,len);
        }
        inputStream.close();
        os.close();
    }

在这里插入图片描述

弹出了下载窗口!

下载出来还真是小俊男!

在这里插入图片描述

太猛了!!

(2)使用response实现验证码功能

我们平常在进行登录的时候,经常需要输入相关的验证码,我们使用response也可以大概模拟出这种效果,来写一下看看:

还是新创建一个servlet类,命名为imageservlet,代码及相关注释如下:

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //让浏览器每三秒刷新一次
        resp.setHeader("refresh","3");
        //初始化图片
         BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        //画个白背景
        g.setColor(Color.white);

        g.fillRect(0,0,80,20);
        g.setColor(Color.black);
        //画字体
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(getString(),0,20);
        //请求使用图片方式打开
        resp.setContentType("image/jpeg");
        //不让网站使用缓存机制
        resp.setDateHeader("expire",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");
        //把图片写给浏览器
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }
//获取随机数的类
    private String getString() {
        Random random = new Random();
        int i = random.nextInt(9999999);
        String num = String.valueOf(i);
        StringBuilder stringBuilder = new StringBuilder(i);
        //保持获取数字的位数为7位
        for(int q =0;q<7-num.length();q++){
            stringBuilder.append(0);

        }
       num = num+stringBuilder.toString();
        return num;
    }

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

注册后运行看一下:
在这里插入图片描述
浏览器还真是每三秒刷新一组新数字啊!

(3)实现重定向

实现重定向主要要使用response中的sendRedirect方法,这里我们写一个登录的小demo看看。

这里我们还是创建一个servlet。

首先我们把index界面改成一个表单

<html>
<body>
<h2>Hello World!</h2>
<%--action中语句的意思是拿到当前目录,以后会学到--%>
<form action="${pageContext.request.contextPath}/l" method="get">
    用户名:<input name="username" type="text">
    密码:<input name="password" type="password">
    <button type="submit">提交</button>

</form>
</body>
</html>

在servlet类中处理相关请求

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

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入了方法");
        //拿到两个属性
        System.out.println(req.getParameter("username"));
        System.out.println(req.getParameter("password"));.
        //重定向到一个新写的success界面
        resp.sendRedirect("/r/success.jsp");

    }
}

注册,部署运行下!我们可以发现方法成功拿到了我们设置的类,并且重定向到了相关页面
在这里插入图片描述
所以说转发和重定向的异同在哪儿呢?

相同点:

  • 都实现了页面的跳转

不同点:

  • 转发的页面url没有变化,而重定向的页面url会产生改变
7、HttpServletRequest

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。

这里我们还是还是通过一个小demo来看看如何使用他!!

我们先修改下之前的index页面,使其中添加相关的多选框,然后把action修改下,这次我们使用post方式进行接收,所以方法也变成post

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

<html>
<body>
<h2>Hello World!</h2>
<%--action中语句的意思是拿到当前目录,以后会学到--%>
<form action="${pageContext.request.contextPath}/t" method="post">
    用户名:<input name="username" type="text">
    密码:<input name="password" type="password">
    <input name="hobby" type="checkbox" value="学习">学习
    <input name="hobby" type="checkbox" value="游泳">游泳
    <input name="hobby" type="checkbox" value="吃饭">吃饭
    <input name="hobby" type="checkbox" value="打游戏">打游戏


    <button type="submit">提交</button>

</form>
</body>
</html>

这里我们创建一个servlet类,代码和相关注释如下:

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.lang.reflect.Array;
import java.util.Arrays;

public class RequestTest extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        //获取相关属性
        System.out.println(req.getParameter("username"));
        System.out.println(req.getParameter("password"));
        //这个getParameterValues可以获取多个值,返回String类型数组
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println(Arrays.toString(hobbies));
        //使用req转发
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
    }
}

注册,启动tomcat看下。

发现可以正常取得相关参数,页面也完成跳转。

在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐