Servlet
第一个HelloServlet项目
1. 创建一个空的Maven项目
- 在Pom.xml中导入依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
- 删除src目录
- 创建一个新的Model子项目**
2. Maven父子工程(Pom.xml中)
- 父项目中有:
<modules>
<module>Servlet01</module>
</modules>
- 子项目中有:
<parent>
<artifactId>2021-0203-Servelt01</artifactId>
<groupId>zy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
3. Maven环境搭建
- 修改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>
- 在main下创建java和resources目录
4.编写一个Servlet程序
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("=============进入doGet方法=============");
PrintWriter writer = resp.getWriter();
writer.print("Hello ServletDemo!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5. 在web.xml中编写Servlet映射————浏览器连接Web服务器,在Web服务器中注册我们写的Servlet,给浏览器一个能够访问的路径
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
6. 配置Tomcat
- 注意配置项目发布路径(Deployment)——————小加号
7. 测试启动
Mapping问题
- 一个Servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定多个映射路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello01</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello02</url-pattern>
</servlet-mapping>
- 一个Servlet可以指通用映射路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
- 默认请求路径
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定后缀或者前缀
- 注意:*前不能有项目映射路径——/
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
- 优先级问题
- 先走指定的固有映射路径,若没有则会走默认处理
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
ServletContext
- 作用:共享数据 初始化参数 请求转发 读取资源文件
作用一:共享数据
步骤:
- 创建一个web项目Servlet02
- 编写两个servlet程序
放置数据
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.PrintWriter;
public class ServletContext01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String Username = "张三";
context.setAttribute("Username",Username);
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.print("==================数据已插入==================");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
读取数据
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.PrintWriter;
public class ServletContext02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
Object username = context.getAttribute("Username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.print("用户名:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 在web.xml中编写两个Servlet映射
<servlet>
<servlet-name>context01</servlet-name>
<servlet-class>ServletContext01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>context01</servlet-name>
<url-pattern>/context01</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>context02</servlet-name>
<servlet-class>ServletContext02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>context02</servlet-name>
<url-pattern>/context02</url-pattern>
</servlet-mapping>
- 配置Tomcat,删除原来的Servlet01
- 发布项目
作用二:获取初始化参数
- 在web.xml中配置参数信息
<context-param>
<param-name>URL</param-name>
<param-value>jdbc:mysql://localhost:3306/Mybatis</param-value>
</context-param>
- 编写Servlet程序获取参数
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.PrintWriter;
public class ServletGetParameter01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("URL");
PrintWriter writer = resp.getWriter();
writer.print("URL:"+url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 编写Servlet映射
<servlet>
<servlet-name>contextgetP</servlet-name>
<servlet-class>ServletGetParameter01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>contextgetP</servlet-name>
<url-pattern>/contextgetP</url-pattern>
</servlet-mapping>
作用三:请求转发
import javax.servlet.RequestDispatcher;
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 ServletGetReqDispatcher01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/contextgetP").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 记得编写servlet映射
作用四:读取资源文件
- 1.创建一个db.properties
- 若db.properties在resources目录下,则直接导出
- 若db.properties在java目录下,因为Maven约定大于配置,导致资源无法被导出或生效
- ——————解决方法:需要在子项目的Pom.xml中的build中配置resources
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
- 2.编写一个Servlet程序
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.io.PrintWriter;
import java.util.Properties;
public class ServletGetResourceAsStream01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db02.properties");
Properties properties = new Properties();
properties.load(is);
String username = properties.getProperty("username");
String pwd = properties.getProperty("password");
PrintWriter writer = resp.getWriter();
writer.print("Username:"+username+" password:"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 3.编写servlet映射
当Web服务器接收到http的请求时,分别创建一个代表请求的对象HttpServletRequest和一个代表响应的对象HttpServletReponse
HttpServletReponse
- 要给客户端响应一些信息,使用HttpServletReponse
1. 下载文件——创建一个新的子项目
- 要获取下载文件的路径
- 下载的文件名是啥?
- 设置想办法让浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区 使用OutputStream将缓冲区中的数据输出到客户端!
- 关闭流
- 注意:配置Tomcat
- 注意:注册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.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
public class DownLoadDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
String photoPath = "E:\\D-JAVA学习\\20210203-JavaWeb-Servlet\\HttpServlet\\src\\main\\resources\\蜡笔小新.png";
// 2. 下载的文件名是啥?
String fileName = photoPath.substring(photoPath.lastIndexOf("\\")+ 1);
// 3. 设置想办法让浏览器能够支持下载我们需要的东西
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(photoPath);
// 5. 创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6. 获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
// 7. 将FileOutputStream流写入到buffer缓冲区 使用OutputStream将缓冲区中的数据输出到客户端!
while ((len = in.read(buffer))>0){
out.write(buffer,0,len);
}
// 8. 关闭流
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2. 验证码功能
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;
public class ImageRandomServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().print("123456");// 1. 让浏览器2秒刷新一次
resp.setHeader("refresh","2");
// 2. 在内存中创建一个图片
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
// 3. 得到图片中的画笔
Graphics2D g = (Graphics2D) image.getGraphics();
// 4. 设置图片背景颜色
g.setColor(Color.pink);
g.fillRect(0,0,80,20);
// 5. 给图片写数据
g.setColor(Color.CYAN);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
// 6. 告诉浏览器,请求用图片的方式打开
resp.setContentType("image/jepg");
// 7. 网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
// 8. 把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
// 生成6位的随机数
private String makeNum() {
Random random = new Random();
String num = random.nextInt(999999)+"";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i <6-num.length() ; i++) {
buffer.append("0");
}
num = buffer.toString()+num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3. 实现重定向
当客户端A访问服务器Web资源B时,B告诉A去访问Web资源C
- 在主页面登录
<html>
<body>
<h2>Hello World!</h2>
<form action="${pageContext.request.contextPath}/login" method="get">
Username:<input type="text" name="username"> <br>
Password:<input type="password" name="password"> <br>
<input type="submit"> <br>
</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 ResponseRedirect extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
resp.sendRedirect("/h/LoginSuccess.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 配置Servlet映射
<servlet>
<servlet-name>responseRedirect</servlet-name>
<servlet-class>ResponseRedirect</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>responseRedirect</servlet-name>
<url-pattern>/response</url-pattern>
</servlet-mapping>
- 编写登录成功界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆成功!</title>
</head>
<body>
<h1>恭喜您!登录成功!</h1>
</body>
</html>
HttpServletRequest
- 要获取客户端传来的数据,使用HttpServletRequest
获取参数 请求转发
- 编写登录页面
注意:第一行用来设置中文字符集
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
<form action="${pageContext.request.contextPath}/request" method="get">
Username:<input type="text" name="username"> <br>
Password:<input type="password" name="password"> <br>
Hobby:
<input type="checkbox" name="hobbies" value="sing">唱歌
<input type="checkbox" name="hobbies" value="dance">跳舞
<input type="checkbox" name="hobbies" value="swim">游泳
<input type="checkbox" name="hobbies" value="play">玩耍
<input type="submit"><br>
</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.util.Arrays;
public class RequestDispatcher extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8"); // 设置后台字符集
resp.setCharacterEncoding("utf-8");// 设置页面字符集
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobbies");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
// 带上获取的数据 请求转发
req.getRequestDispatcher("/LoginSuccess.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 编写servlet映射
<servlet>
<servlet-name>requestDispatcher</servlet-name>
<servlet-class>RequestDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>requestDispatcher</servlet-name>
<url-pattern>/request</url-pattern>
</servlet-mapping>
- 编写登录成功跳转的页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆成功!</title>
</head>
<body>
<h1>恭喜您!登录成功!</h1>
</body>
</html>
重定向和请求转发的区别
重定向: resp.sendRedirect("/h/LoginSuccess.jsp");
- URL地址栏会发生变化
请求转发:req.getRequestDispatcher("/LoginSuccess.jsp").forward(req,resp);
- URL地址栏不会发生变化