📖本篇内容: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字
请食客们慢慢食用~
最后
每天进步点 每天收获点
愿诸君 事业有成 学有所获
如果觉得不错 别忘啦一键三连哦~