目录
Servlet 就是 Sun 公司开发动态 Web 的一门技术
Sun 在这些 API (Application Programming Interface,应用程序接口)中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
编写一个类,实现Servlet接口。
把开发好的Java类部署到web服务器中。
把实现了 Servlet 接口的 Java 程序叫做,Servlet
1)Serlvet 接口 Sun 公司有两个默认的实现类:HttpServlet,GenericServlet
构建一个普通的Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就是Maven主工程(建一个WebApp Maven项目,勾选模板);
2)关于Maven父子工程的理解:
父项目中会有:
- <modules>
- <module>lesson01module>
- <module>lesson01module>
- modules>
子项目中会有:
- <parent>
- <artifactId>JavaWeb_studyartifactId>
- <groupId>org.examplegroupId>
- <version>1.0-SNAPSHOTversion>
- parent>
父项目中的 Java 子项目可以直接使用
son extends father
3)Maven 环境优化
修改 web.xml 为最新的
将 maven 的结构搭建完整
4)编写一个servlet程序
S1:编写一个普通类
S2:实现 Servlet 接口,这里我们直接继承 HttpServlet
- 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 HelloServlet extends HttpServlet {
- //由于get和post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- PrintWriter writer=resp.getWriter();//响应流
- writer.print("hello,servlet");
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req, resp);
- }
- }
5)编写servlet的映射
为什么需要映射:我们写的是 Java 程序,但是要通过浏览器访问,而浏览器需要连接 Web 服务器,所以我们需要再 Web 服务中注册我们写的 Servlet,还需给他一个浏览器能够访问的路径;
6)配置 Tomcat
点击编辑,+ 号,选择本地的 Tomcat
7)启动测试!
Servlet 是由 Web 服务器调用,Web 服务器在收到浏览器请求之后,会:

1)一个 Servlet 可以指定一个映射路径
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/hellourl-pattern>
- servlet-mapping>
2)一个 Servlet 可以指定多个映射路径
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/hellourl-pattern>
- servlet-mapping>
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/hello2url-pattern>
- servlet-mapping>
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/hello3url-pattern>
- servlet-mapping>
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/hello4url-pattern>
- servlet-mapping>
3)一个 Servlet 可以指定通用映射路径
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/hello/*url-pattern>
- servlet-mapping>
4)默认请求路径
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/*url-pattern>
- servlet-mapping>
5)指定一些后缀或者前缀等等
可以自定义后缀实现请求映射
注意:‘*’ 前面不能加映射的路径
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>*.biuurl-pattern>
- servlet-mapping>
6)优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
- 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 ErrorServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- resp.setContentType("text/html");
- resp.setCharacterEncoding("utf-8");
-
- PrintWriter writer = resp.getWriter();
- writer.print("
404
"); - }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- super.doPost(req, resp);
- }
- }
-
配置文件:
- <servlet>
- <servlet-name>errorservlet-name>
- <servlet-class>com.lwy.servlet.ErrorServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>errorservlet-name>
- <url-pattern>/*url-pattern>
- servlet-mapping>
Web 容器在启动的时候,它会为每个 Web 程序都创建一个对应的 ServletContext 对象,它代表了当前的 Web 应用;
共享数据
在一个 servlet 中保存的数据,可以在另一个 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;
-
- public class HelloServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // this.getInitParameter() 初始化参数
- // this.getServletConfig() servlet配置
- // this.getServletContext() servlet上下文
- ServletContext servletContext = this.getServletContext();
- String username="biubiu";//数据
- servletContext.setAttribute("username",username);//将一个数据保存在了servletContext中 (键值对形式)
- System.out.println("hello");
- }
- }
获取数据的类:
- 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 GetServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- ServletContext servletContext = this.getServletContext();
- String username =(String) servletContext.getAttribute("username");
-
- resp.setContentType("text/html");
- resp.setCharacterEncoding("utf-8");
- resp.getWriter().print("名字:"+username);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- super.doPost(req, resp);
- }
- }
配置servlet:
- web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
-
- <web-app>
- <display-name>Archetype Created Web Applicationdisplay-name>
-
- <servlet>
- <servlet-name>helloservlet-name>
- <servlet-class>com.lwy.servlet.HelloServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>helloservlet-name>
- <url-pattern>/hellourl-pattern>
- servlet-mapping>
-
- <servlet>
- <servlet-name>getcservlet-name>
- <servlet-class>com.lwy.servlet.GetServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>getcservlet-name>
- <url-pattern>/getcurl-pattern>
- servlet-mapping>
-
- web-app>
测试访问结果:

获取初始化参数
- 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 ServletDemo03 extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //上下文
- ServletContext servletContext = this.getServletContext();
- String url = servletContext.getInitParameter("url");
- resp.getWriter().print(url);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- super.doPost(req, resp);
- }
- }
配置文件:
-
gp -
com.lwy.servlet.ServletDemo03 -
-
-
gp -
/gp -


- 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 ServletDemo04 extends HttpServlet {
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{
- //获取上下文
- ServletContext servletContext = this.getServletContext();
- //调用forward方法实现请求转发
- servletContext.getRequestDispatcher("/gp").forward(req,resp);
- }
-
- protected void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{
- doGet(req, resp);
- }
- }
读取资源文件
Properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath:
思路:需要一个文件流;
资源文件中存放的信息(db.properties):
- username=root
- password=root
- 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;
-
- public class ServletDemo05 extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
- Properties prop = new Properties();
- prop.load(is);
- String user = prop.getProperty("username");
- String pwd = prop.getProperty("password");
-
- resp.getWriter().print(user+":"+pwd);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- super.doPost(req, resp);
- }
- }
映射路径:
- <servlet>
- <servlet-name>s5servlet-name>
- <servlet-class>com.lwy.servlet.ServletDemo05servlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>s5servlet-name>
- <url-pattern>/s5url-pattern>
- servlet-mapping>

Web 服务器接收到客户端的 http 请求,针对这个请求,分别创建一个代表请求的 HttpServletRequest 对象,代表响应的一个 HttpServletResponse;
简单分类
负责向浏览器发送数据的方法
- ServletOutputStream getOutputStream() throws IOException;
- PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
- void setCharacterEncoding(String var1);
-
- void setContentLength(int var1);
-
- void setContentLengthLong(long var1);
-
- void setContentType(String var1);
-
- void setDateHeader(String var1, long var2);
-
- void addDateHeader(String var1, long var2);
-
- void setHeader(String var1, String var2);
-
- void addHeader(String var1, String var2);
-
- void setIntHeader(String var1, int var2);
-
- void addIntHeader(String var1, int var2);
-
响应的状态码
- int SC_CONTINUE = 100;
- int SC_SWITCHING_PROTOCOLS = 101;
- int SC_OK = 200;
- int SC_CREATED = 201;
- int SC_ACCEPTED = 202;
- int SC_NON_AUTHORITATIVE_INFORMATION = 203;
- int SC_NO_CONTENT = 204;
- int SC_RESET_CONTENT = 205;
- int SC_PARTIAL_CONTENT = 206;
- int SC_MULTIPLE_CHOICES = 300;
- int SC_MOVED_PERMANENTLY = 301;
- int SC_MOVED_TEMPORARILY = 302;
- int SC_FOUND = 302;
- int SC_SEE_OTHER = 303;
- int SC_NOT_MODIFIED = 304;
- int SC_USE_PROXY = 305;
- int SC_TEMPORARY_REDIRECT = 307;
- int SC_BAD_REQUEST = 400;
- int SC_UNAUTHORIZED = 401;
- int SC_PAYMENT_REQUIRED = 402;
- int SC_FORBIDDEN = 403;
- int SC_NOT_FOUND = 404;
- int SC_METHOD_NOT_ALLOWED = 405;
- int SC_NOT_ACCEPTABLE = 406;
- int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
- int SC_REQUEST_TIMEOUT = 408;
- int SC_CONFLICT = 409;
- int SC_GONE = 410;
- int SC_LENGTH_REQUIRED = 411;
- int SC_PRECONDITION_FAILED = 412;
- int SC_REQUEST_ENTITY_TOO_LARGE = 413;
- int SC_REQUEST_URI_TOO_LONG = 414;
- int SC_UNSUPPORTED_MEDIA_TYPE = 415;
- int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
- int SC_EXPECTATION_FAILED = 417;
- int SC_INTERNAL_SERVER_ERROR = 500;
- int SC_NOT_IMPLEMENTED = 501;
- int SC_BAD_GATEWAY = 502;
- int SC_SERVICE_UNAVAILABLE = 503;
- int SC_GATEWAY_TIMEOUT = 504;
- int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
-
常见应用
1)向浏览器输出信息
2)下载文件
演示:使用response实现文件的下载
- 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 FileServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // 1.要获取下载文件的路径
- String realPath = "D:\\Java\\JavaWeb_study\\lesson03\\src\\main\\resources\\1.PNG";
- System.out.println("下载的文件的路径:"+realPath);
- // 2.下载的文件名是什么
- String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
- // 3.设置,想办法让浏览器能够支持下载我们需要的东西,中文文件名使用URLEncoder.encode(fileName,"utf-8")编码
- resp.setHeader("Content-Disposition","attachment;filename="+fileName+ URLEncoder.encode(fileName,"utf-8"));
- // 4.获取下载文件的输入流
- FileInputStream in = new FileInputStream(realPath);
- // 5.创建缓冲区
- int len=0;
- byte[] buffer = new byte[1024];//缓冲区
- // 6.获取OutputStream对象
- ServletOutputStream out = resp.getOutputStream();
- // 7.将FileOutputStream流写入到缓冲区
- // 8.使用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);
- }
- }
路径映射:
- <servlet>
- <servlet-name>filedownservlet-name>
- <servlet-class>com.lwy.servlet.FileServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>filedownservlet-name>
- <url-pattern>/downurl-pattern>
- servlet-mapping>
网页中的效果:

验证码怎么来的?
- 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 ImageServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //如何让浏览器3秒自动刷新一次
- resp.setHeader("refresh","3");
- //在内存中创建图片
- BufferedImage bufferedImage = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
- //得到图片
- Graphics2D graphics = (Graphics2D)bufferedImage.getGraphics();//画笔
- //设置图片的背景颜色
- graphics.setColor(Color.WHITE);//画背景
- graphics.fillRect(0,0,80,20);
- //给图片写数据
- graphics.setColor(Color.BLUE);//写东西
- graphics.setFont(new Font(null,Font.BOLD,20));
- graphics.drawString(makeNum(),0,20);
- //告诉浏览器这个请求用图片的方式打开
- resp.setContentType("image/PNG");
- //网站存在缓冲,需要解决
- resp.setDateHeader("expires",-1);
- resp.setHeader("Cache-Control","no-cache");
- resp.setHeader("Pragma","no-cache");
-
- //把图片写给浏览器
- ImageIO.write(bufferedImage,"jpg",resp.getOutputStream());
-
- }
-
- //生成随机数
- public String makeNum(){
- Random random = new Random();
- String num=random.nextInt(9999999)+"";
- StringBuffer stringBuffer = new StringBuffer();
- for(int i=0;i<7-num.length();i++){
- stringBuffer.append(0);
- }
- String s=stringBuffer.toString() + num;
- return num;
- }
-
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req, resp);
- }
- }
映射路径:
- <servlet>
- <servlet-name>ImageServletservlet-name>
- <servlet-class>com.lwy.servlet.ImageServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>ImageServletservlet-name>
- <url-pattern>/imgurl-pattern>
- servlet-mapping>
页面效果(页面每3秒中自动刷新一次):


Web 资源 B 收到客户端 A 请求后,通知 A 访问另一个 Web 资源 C ,这个过程叫做重定向
常见场景:
void sendRedirect(String var1) throws IOException;
测试重定向:
- 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 RedirectServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- resp.sendRedirect("/lesson03/img");
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- super.doPost(req, resp);
- }
- }
映射路径:
- <servlet>
- <servlet-name>RedirectServletservlet-name>
- <servlet-class>com.lwy.servlet.RedirectServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>RedirectServletservlet-name>
- <url-pattern>/redurl-pattern>
- servlet-mapping>
面试题:
重定向和转发的区别
相同点:
不同点:
原理图:

简单实现登录重定向(模拟用户登录):
前端页面:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%--这里提交的路径,需要寻找到项目的路径--%>
- <%--pageContext.request.contextPath :表示当前项目--%>
- 用户名:"text" name="username">
- 密码:"password" name="password">
- "submit">
-
Java代码:
- 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 RequestTest 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("/lesson03/success.jsp");
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req, resp);
- }
- }
路径映射:
- <servlet>
- <servlet-name>requestservlet-name>
- <servlet-class>com.lwy.servlet.RequestTestservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>requestservlet-name>
- <url-pattern>/loginurl-pattern>
- servlet-mapping>
跳转页面:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
-
Title Success
代表客户端的请求,用户通过HTTP协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest的方法,获得客户端的所有信息
可以获取前端传递的参数
测试代码:
- 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 LoginServlet 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[] hobbys = req.getParameterValues("hobbys");
- System.out.println("==================================");
- //后台接收中文乱码问题
- System.out.println(username);
- System.out.println(password);
- System.out.println(Arrays.toString(hobbys));
- System.out.println("==================================");
- //通过请求转发
- req.getRequestDispatcher("success.jsp").forward(req,resp);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req, resp);
- }
- }
前端页面:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>登录title>
- head>
- <body>
- <h1>登录h1>
- <div style="text-align: center">
- <form action="login" method="post">
- 用户名:<input type="text" name="username"><br>
- 密码:<input type="password" name="password"><br>
- 爱好:
- <input type="checkbox" name="hobbys" value="音乐">音乐
- <input type="checkbox" name="hobbys" value="代码">代码
- <input type="checkbox" name="hobbys" value="电影">电影
- <input type="checkbox" name="hobbys" value="唱歌">唱歌
- <br>
- <input type="submit">
- form>
- div>
-
- body>
- html>
跳转页面:
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <h1>登录成功h1>
- body>
- html>
控制台打印输出:
