Servlet入门到入坟 一站式基础及进阶——SpringMVC没它都不行 你确定不来看看——囊括初学基础以及进阶

📖本篇内容:Servlet入门到进阶 一站式基础及进阶——囊括面试点与初学基础

📑 文章专栏:SSM入门到入坟——一站式基础以及进阶栏目

📆 更新周期:2022年1月9日起~2022年1月17日

🎬​最近更新:2022年1月14日 Spring入门到入坟 一站式基础及进阶——囊括面试点与初学基础——源码分析——从0到1

🙊个人简介:一只二本院校在读的大三程序猿,本着注重基础,打卡算法,分享技术作为个人的经验总结性的博文博主,虽然可能有时会犯懒,但是还是会坚持下去的,如果你很喜欢博文的话,建议看下面一行~(疯狂暗示QwQ)

🌇 点赞 👍 收藏 ⭐留言 📝 一键三连 关爱程序猿,从你我做起

🙊Servlet入门到进阶🙊

写在前面

哇咔咔,小付又来更新了哦~这次更新的是有关于JavaWeb中的Servlet这一块,为什么会花费一个星期左右的时间来从头到尾巴在学一下这个技术呢,因为在SpringMVC当中的底层绝大部分都是依靠Servlet来进行实现的,本着知其然并知其所以然的缘故,所以就有了本篇文章,本文有两个实战小案例,一个是关于Spring+Mybatis+Servlet如何认证用户登录,另一个就是关于用户验证码如何从后台生成传输到浏览器页面,希望大家喜欢,如果喜欢不要忘记收藏关注和点赞哦!!!

📖1、Servlet简介📖

1.1、什么是Servlet

什么是Servlet?

Servlet 是 Server + Applet的缩写

我们可以理解为Servlet就是一个运行在服务端的小程序,也被我们称之为服务器应用

当我们开发一个Servlet的小程序时,实际只需要进行如下两步:

  • 编写一个类,实现Servlet接口
  • 开发完成的Java类部署到服务器上即可

📖2、快速上手Servlet📖

2.1、HelloServlet

步骤1:导入相关依赖

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

步骤2:编写一个Servlet程序

  • 编写一个类
  • 实现Servlet接口,也可以直接继承接口的实现类HttpServlet

HelloServlet.java

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.print("Hello,Serlvet");
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

步骤3:配置web部署项目服务

IDEA ——> File ——> Project Structure ——> Modules

在对应的Modules 中 新建 web工程

在这里插入图片描述

创建的同时也要部署构建Artifact

在这里插入图片描述

此时你的项目下会多出来一个web工程项目以及web.xml配置文件。

步骤4:配置我们的Tomcat

如果对Tomcat基本配置以及面试常问有疑问:请转移至 Tomcat入门到快速上手——一站式基础以及相关配置控制——囊括面试题

在这里插入图片描述

步骤5:配置web.xml文件进行映射访问

为什么这里需要映射呢?

  • 因为我们写的是HelloServlet.java程序,但是想要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们写的Servlet,以及浏览器通过服务器能访问的路径地址
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.alascanfu.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

步骤6:启动Tomcat服务器进行测试

点击绿色三角形启动Tomcat服务器

在这里插入图片描述

启动成功后通过网页进行访问

在这里插入图片描述

2.2、Servlet工作原理

在这里插入图片描述

Servlet是由Web服务器调用,web服务器会在收到请求之后,会有如下一系列步骤

  • 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的映射路径

  • 查找web.xml文件,是否有对应资源名字的映射资源路径

  • 如果有,则在找到对应映射Servlet的全类名

  • tomcat会将字节码文件加载进内存,并且创建其对象

  • 调用其方法

2.3 Mapping的映射路径问题

1、一个Servlet可以指定一个映射的路径

<servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.alascanfu.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
</servlet-mapping>

2、一个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>

3、一个Servlet可以指定通配映射路径

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

4、指定默认请求的路径

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

📖3、Servlet接口详解📖

既然前文提到编写一个Java类 之后要实现Servlet接口,那么Servlet接口具体是什么样子的呢?

Servlet.java源码

//javax.servlet.Servlet
public interface Servlet {

    public void init(ServletConfig config) throws ServletException;

    public ServletConfig getServletConfig();
    
    public void service(ServletRequest req, ServletResponse res)
	throws ServletException, IOException;
	
    public String getServletInfo();
    
    public void destroy();
}

3.1、创建:执行init方法

init方法在容器启动时候会被容器调用,只会被调用一次

Servlet何时会被创建?

默认情况,当一次访问时就会被创建。

  • 若要第一次被访问时,创建则的值为负数
  • 若要在服务器启动时,创建则的值为0或正整数。
<servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.alascanfu.HelloServlet</servlet-class>
        <load-on-startup>-1</load-on-startup>
</servlet>

注意:因为上文提到Servlet的init方法只会执行一次,故其在内存当中只存在一个对象,多线程访问会出现安全问题。

3.2、 服务:执行service方法

Service方法用于具体处理一个请求每次用户访问Servlet程序时,该Service方法都会被调用执行一次

3.3、销毁:执行destory方法

Destory方法用于Servlet销毁(通常指的是在服务器关闭的时候释放资源),一般只会调用一次

📖4、注解配置Servlet📖

Servlet3.0起开始支持注解配置,可以无需再配置web.xml文件 注解对应的属性就是在web.xml中Servlet配置的属性 以及映射.

在这里插入图片描述

步骤1:定义一个类,实现Servlet接口

@WebServlet(urlPatterns = "/hello")public class HelloServlet extends HttpServlet {}

或者简写为

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {}

并且也需要在Edit configuration 中 设置 Application context

在这里插入图片描述

📖5、Servlet 结构📖

5.1、Servlet体系结构图

Servlet结构图

在这里插入图片描述

5.2、 GenericServlet 实现类

GenericServlet 实现类

Servlet接口中的其他三个方法都做了默认空实现,将service方法作为抽象。当用户需要创建Servlet程序的时候可以通过继承GenericServlet类 ,实现service这个抽象方法。

@WebServlet(urlPatterns = "/hello")
public class HelloServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        PrintWriter printWriter = res.getWriter();
        printWriter.write("HelloServlet");
    }
}

5.3、HttpServlet实现类

HttpServlet实现类

对http协议进行了封装,便于操作

  • 构建一个类继承 HttpServlet 重写doGet/doPost方法。
@WebServlet(urlPatterns = "/hello")
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.print("Hello,Serlvet");
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

📖6、Request 与 Response📖

6.1 Request 与 Response 在Servlet中如何工作

  • 当用户进行请求服务器时,会发送一段请求信息
  • Tomcat服务器,会在此时创建request 和 response 两个对象传入 service方法当中,并且执行service方法
  • 我们可以通过request 获取 用户的请求信息然后通过response 设置服务器的 响应请求数据
  • Tomcat 服务器会根据response中的数据响应设置数据 给浏览器做出对应的响应。

重点:

  • request 与 response 都是由服务器创建而来,我们负责使用
  • request 是获取用户的消息请求、response是用来设置服务器响应给用户的响应信息。

⭐6.2、Request⭐

在这里插入图片描述

上图是Request对象的体系结构。

1、获取请求行数据

获取请求行数据

  • 获取请求方式:
writer.println("请求方式为:"+req.getMethod());
  • 获取虚拟目录
writer.println("请求方式为:"+req.getContextPath());
  • 获取Servlet路径
writer.println("请求方式为:"+req.getServletPath());
  • 获取get方式的请求参数
writer.println("获取get方式请求的参数:"+req.getQueryString());
  • 获取请求的URL地址
writer.println("获取请求的URL:"+req.getRequestURL());
  • 获取请求的协议
writer.println("获取请求的网际协议版本:"+req.getProtocol());
  • 获取客户机的IP地址
writer.println("获取客户机的IP地址:"+req.getRemoteAddr());

在这里插入图片描述

2、获取请求头数据

获取请求头数据

Enumeration<String> headerNames = req.getHeaderNames();        while(headerNames.hasMoreElements()){            String name = headerNames.nextElement();            //根据请求头名称获取对应的请求头的数据            String value = req.getHeader(name);            writer.println(name+"===>"+value);        }

在这里插入图片描述

3、获取请求体数据

获取请求体数据

只在POST方法中有效

resp.setCharacterEncoding("GBK");BufferedReader br = req.getReader();String line = null;while((line = br.readLine()) != null){    System.out.println(line);}
4、获取请求参数数据

获取请求参数的通用方式

  • 根据参数名称获取参数值
String username = request.getParameter("username");
  • 获取所有请求的参数名称
Enumeration<String> parameterNames = request.getParameterNames();

获取方式与获取请求参数的方式相通 这里就不再赘述了.

  • 根据参数名称获取参数值的数组
String[] hobbies = request.getParameterValues("games");
  • 获取参数的map集合
Map<String, String[]> parameterMap = request.getParameterMap();
  • Test

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: Alascanfu
  Date: 2022/1/16
  Time: 22:57
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>

<form action="/hello/helloRequest" method="get">
    <input type="text" placeholder="请输入用户名" name="username"><br>
    <input type="text" placeholder="请输入密码" name="password"><br>

    <input type="checkbox" name="games" value="LOL">英雄联盟
    <input type="checkbox" name="games" value="CSGO">CSGO
    <input type="checkbox" name="games" value="PUBG">PUBG
    <br>

    <input type="submit" value="注册">

</form>

</body>
</html>

如果上述页面出现了乱码则需要对response进行设置响应的字符编码方式为GBK或者UTF-8

HelloServlet

@WebServlet(urlPatterns = "/helloRequest")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
        
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // post获取请求参数
        //直接获取参数名为username的值
        String username = request.getParameter("username");
        //通过参数名games获取参数数组
        String[] hobbies = request.getParameterValues("games");
        //获取所有的参数名称
        Enumeration<String> parameterNames = request.getParameterNames();
        //如果当前参数还有元素的话就遍历
        while (parameterNames.hasMoreElements()){
            //参数名就为下一个元素
            String name = parameterNames.nextElement();
            System.out.println(name);
            //通过参数名获取参数值
            String value = request.getParameter(name);
            System.out.println(value);
        }
        
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<String> keySet = parameterMap.keySet();
        for (String name : keySet) {
            // 根据参数名获取值
            String[] values = parameterMap.get(name);
            System.out.println(name);
            for (String value : values) {
                System.out.println(value);
            }
            System.out.println("----------------------");
        }
        
    }
}

5、通过请求转发器进行请求转发
  • 通过resquest 获取请求转发器的对象
RequestDispatcher helloB = req.getRequestDispatcher("HelloB");
  • 通过RequestDispatcher 的forwar方法进行请求转发
helloB.forward(req,resp);

Test

HelloAServlet.java

@WebServlet("/HelloA")
public class HelloAServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        PrintWriter writer = resp.getWriter();
        System.out.println("HelloA.ForwarToB");
        RequestDispatcher helloB = req.getRequestDispatcher("HelloB");
        helloB.forward(req,resp);
    }
}

HelloBServlet.java

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

已经创建好了两个Servlet程序,此时启动服务器,我们可以通过访问/HelloA将请求转发到/HelloB 页面输出的是HellBServlet的内容,控制台可以查看到HelloAServlet的请求过程。

在这里插入图片描述

在这里插入图片描述

工作流程大致如下:

在这里插入图片描述

6、通过request作用域进行共享数据
  • 域对象:作为有作用范围的一个对象,可以在范围内共享数据
  • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

如何实现呢?

设置request域中的数据。

req.setAttribute("msg","这是HelloA的数据资源,将有转发器转至HelloB");

通过路由转发能共享到由ServletA的request作用域下的共享数据

RequestDispatcher helloB = req.getRequestDispatcher("HelloB");
helloB.forward(req,resp);

通过HelloBServlet来获取共享资源

Object msg = req.getAttribute("msg");
writer.println("HelloB获取了由HelloA中request域中的数据:"+msg);

结果演示:

在这里插入图片描述

7、📝 用户登录示例📝 (采用的Spring+Servlet+Mybatis)

目录结构如下:

在这里插入图片描述

步骤1:添加对应依赖到Maven工程当中并且配置好pom.xml文件

<dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.8.M1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
</dependencies>

为了防止打包生成测试时无法生成对应xml与properties文件,需要在pom.xml文件末尾添加build标签,用来过滤拦截配置

<build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
</build>

步骤2:编写数据库并且添加对应的数据

CREATE DATABASE servlettest;

USE servlettest;

CREATE TABLE user(
	`id` int not null PRIMARY KEY,
	`username` varchar(32) not null,
	`password` varchar(32) not null
)ENGINE=INNODB DEFAULT charset=utf8;

并为表中添加对应的数据:
在这里插入图片描述

步骤3:编写User类以及对应的Mapper接口、映射文件和Service服务类

User.java

public class User {
    private int id;
    private String username;
    private String password;
    
    public User() {
    }
    
    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    @Override
    public String toString() {
        return "User{" +
            "id=" + id +
            ", username='" + username + '\'' +
            ", password='" + password + '\'' +
            '}';
    }
}

UserMapper.java以及UserMapper.xml

public interface UserMapper {
    User checkLogin(User user);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.alascanfu.pojo.mapper.UserMapper">

    <select id="checkLogin" resultType="com.alascanfu.pojo.User">
        select * from USER where username = #{username} and password = #{password}
    </select>
</mapper>

UserService.java

@Service
public class UserService {
    @Autowired
    UserMapper userMapper;
    public User checkLogin(User user){
        return userMapper.checkLogin(user);
    }
}

步骤4:编写配置文件application.xml 、spring-mybatis.xml文件、log4j.properties、mybatis-config.xml以及用于测试报错的WEB-INF/classes/logging.properties

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
">
    <context:component-scan base-package="com.alascanfu"/>
    <context:annotation-config/>

    <import resource="classpath:spring-mybatis.xml"/>
</beans>

spring-mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
       http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
">
    <context:component-scan base-package="com.alascanfu"/>
    <context:annotation-config/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">

        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>

        <property name="url" value="jdbc:mysql://localhost:3306/servlettest?characterEncoding=utf-8"/>

        <property name="username" value="root"/>

        <property name="password" value="123456"/>

    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>

        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/alascanfu/pojo/mapper/*.xml"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.alascanfu.pojo.mapper"/>
    </bean>

    <bean id="txAdvice" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>

logging.properties

org.apache.catalina.core.ContainerBase.[Catalina].level=INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers=java.util.logging.ConsoleHandler

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">
    <!--指定配置文件的名称路径-->
    <context-param>
        <!--固定 name-->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--配置启动spring框架的监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

步骤5:定义login.jsp 与 Servlet

<%--
  Created by IntelliJ IDEA.
  User: 帝白灬黎墨
  Date: 2022/1/17
  Time: 11:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/hello/loginServlet" method="post">
    用户名:<input type="text" name="username"> <br>
    密码:<input type="password" name="password"><br>

    <input type="submit" value="登录">

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

LoginServlet.java

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("GBK");
        req.setCharacterEncoding("GBK");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
        UserService userService = (UserService) context.getBean("userService", UserService.class);
    
        User check = userService.checkLogin(user);
        resp.getWriter().print("Hello servlet!");
        if (check == null){
            req.getRequestDispatcher("/failServlet").forward(req,resp);
//            resp.getWriter().print("没有找到用户");
    
        }else{
            req.setAttribute("user",check);
            req.getRequestDispatcher("/successServlet").forward(req,resp);
//            resp.getWriter().print("找到用户正在跳转界面");
        }
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

SuccessServlet.java

@WebServlet("/successServlet")
public class SuccessServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取request域中共享的user对象
        User user = (User) request.getAttribute("user");
    
        if (user != null){
            // 设置编码
            response.setContentType("text/html;charset=utf-8");
            // 输出
            response.getWriter().write("登录成功" + user.getUsername() + "欢迎您!");
        }
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

FailServlet.java

@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置编码
        response.setContentType("text/html;charset=utf-8");
        // 输出
        response.getWriter().write("登录失败,用户名或密码错误");
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

步骤6:开启服务器进行测试

如图所示即为成功:

登录界面

在这里插入图片描述

登陆成功后会由request进行请求转发到/successServlet

在这里插入图片描述

登录失败后会由request进行请求转发到/failServlet

在这里插入图片描述

⭐6.3、Response⭐

1、设置响应行

设置状态码

response.setStatus(200);
2、设置响应头
setHeader(String name, String value) 
3、设置响应体

步骤1:获取输出流

  • 字符输出流:
response.getWriter()
  • 字节输出流:
ServletOutputStream getOutputStream()

步骤2:使用输出流,将数据输出到客户端或者浏览器

4、项目实例1(重定向)

本示例应用的是用户登录示例中的错误登录后重定向

if (check == null){
            resp.setStatus(302);
            resp.sendRedirect("/hello/failServlet");
        }else{
           resp.sendRedirect("/hello/successServlet");
        }
  • 方式一:设置状态码并且重定向
resp.setStatus(302);
resp.sendRedirect("/hello/failServlet");
  • 方式二:简单的重定向方法
req.setAttribute("user",check);
resp.sendRedirect("/hello/successServlet");

重定向的特点:redirect

​ 1. 地址栏发生变化

​ 2. 重定向可以访问其他站点(服务器)的资源

​ 3. 重定向是两次请求不能使用request对象来共享数据

转发的特点:forward

​ 1. 转发地址栏路径不变

​ 2. 转发只能访问当前服务器下的资源

​ 3. 转发是一次请求,可以使用request对象来共享数据

在这里插入图片描述

5、将服务器输出的数据打印在服务器上
resp.getWriter().print("找到用户正在跳转界面");

需要注意乱码问题:这里需要将请求与相应都要编码

resp.setCharacterEncoding("GBK");
req.setCharacterEncoding("GBK");

或者

// 设置编码
response.setContentType("text/html;charset=utf-8");
6、📝在浏览器页面随机生成验证码📝

步骤1:编写对应的生成验证码的Servlet程序

Case4CheckCode.java

@WebServlet("/checkCodeServlet")
public class Case4CheckCode extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.创建一对象,在内存中图片(验证码图片对象)
        int width = 100;
        int height = 50;
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //画笔
        Graphics graphics = bufferedImage.getGraphics();
        graphics.setColor(Color.PINK);
        graphics.fillRect(0,0,width,height);
    
        //2.2画边框
        graphics.setColor(Color.BLACK);
        graphics.drawRect(0,0,width-1,height-1);
    
        //2.3写字母
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
        //生成随机字符
        Random ran = new Random();
        for (int i = 1;i<= 4 ;i++){
            int index = ran.nextInt(str.length());
            char ch = str.charAt(index);
            graphics.drawString(ch+"",width/5*i,height/2);
        }
    
        //2.4扰乱
        graphics.setColor(Color.BLACK);
        //随机生成坐标点
    
        for (int i = 0; i < 10; i++) {
            int x1 = ran.nextInt(width);
            int x2 = ran.nextInt(width);
        
            int y1 = ran.nextInt(height);
            int y2 = ran.nextInt(height);
            graphics.drawLine(x1,y1,x2,y2);
        }
    
        //3.将图片输出到页面展示
        ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
    }
}

login.jsp

<%--
  Created by IntelliJ IDEA.
  User: 帝白灬黎墨
  Date: 2022/1/17
  Time: 11:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script>
    // 点击超链接或图片切换验证码
    // 1.给超链接和图片绑定单击事件
    // 2.重新设置图片的src属性值实现切换

    window.onload = function () {
        function changeCheckCode() {
            //加时间戳
            var date = new Date().getTime();
            //加时间戳,防止src相同了使得浏览器缓存影响图片的切换
            img.src = "/hello/checkCodeServlet?" + date;
        }

        var img = document.getElementById("checkCode");
        img.onclick = changeCheckCode;

        var a = document.getElementById("change");
        a.onclick = changeCheckCode;
    }

</script>
<body>
<form action="/hello/loginServlet" method="post">
    用户名:<input type="text" name="username"> <br>
    密码:<input type="password" name="password"><br>
    验证码:<input type="password" name="password"><br>
    <img id="checkCode" src="/hello/checkCodeServlet" /><br>
    <a id="change" href="javascript:void(0)">看不清,换一张</a><br>
    <input type="submit" value="登录">


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

示例演示:

在这里插入图片描述

📖7、ServletContext📖

ServletContext

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用。

ServletContext servletContext = request.getServletContext();

ServletContext servletContext = this.getServletContext();

上述两种方式获取Servlet上下文。

它可以用来共享整个web应用下的数据,也可以获取参数同样也可以请求转发,也能读取外部文件信息数据。这里不再细讲。

写在最后

哇咔咔,一寸光阴一寸金

一个星期这么快就过去了,也只是加深了Servlet的二次学习

时间还很长 路还很远呢

加油啊 各位

本文共计22500字

请食客们慢慢食用~

最后

每天进步点 每天收获点

愿诸君 事业有成 学有所获

如果觉得不错 别忘啦一键三连哦~

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alascanfu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值