Servlet学习笔记

Servlet

  • 概念:运行在服务器端的小程序
    • Servlet就是一个接口,定义了java类被浏览器访问到(tomcat识别)的规则
    • 我们自定义一个类,实现Servelet接口,复写方法

快速上手

1.创建JavaEE项目

  • 注意:创建过程中不要有中文路径

  • 步骤

    1.启动IDEA

    2.新建一个工程

    3.选择JavaEnterprise

    4.勾选Web Application,勾选Create web.xml

    5.然后下一步,输入项目名和路径(不要中文路径)

2.定义一个类,实现Servlet接口

package cn.zqq.web.servlet;

import javax.servlet.*;
import java.io.IOException;

public class ServletDemo1  implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("这是一个开始");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

3.实现接口中的抽象方法

由于要快速上手,所以只需要在service方法里写一个输出就行

 System.out.print("快速上手Servlet。");

4.配置Servlet

注意:项目有中文路径的话这一步可能没法实现

(1)在web–>WEB-INFO中,找到web.xml

(2)在里面添加如下内容

  • servlet-name标签中的值自己填
  • servlet-class标签中的值是全路径(包名+类名)
  • servlet-mapping中的servlet-name和上面的相同
  • servlet-mapping中的url-pattern 可以自己随便写,前面必须加/
<?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">
    <servlet>
        <servlet-name>test</servlet-name>
        <servlet-class>cn.zqq.web.servlet.ServletDemo</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>test</servlet-name>
        <url-pattern>/demo</url-pattern>
    </servlet-mapping>
</web-app>

(3)运行tomcat服务器

​ 直接输入网址http://localhost:8080/demo访问(demo是刚才的url-pattern)

​ 运行成功 会在IDEA控制台输出"快速上手Servlet。"

  • 注意:可能输入网址后会显示404

    • 解决方法

      点击IDEA菜单栏里的Run菜单,找到Edit Configurations

      查看Tomcat的Server菜单中 URL的配置是否为http://localhost:8080/

      以及Tomcat的Deployment菜单中的Application context是否为/

      如果不是,需要修改成这个就可以通过http://localhost:8080/demo访问了(也可以根据自己的需要进行设置)
      在这里插入图片描述在这里插入图片描述

Servlet执行原理

  • 在浏览器中输入一个url地址(http://localhost:8080/demo)时

  • 通过 ip端口号 (localhost:8080)可以准确定位到主机上的应用程序

  • 我们在Tomcat的Edit Configurations中将项目部署(Deployment)的路径设置成了/

  • tomcat内部会查找配置文件web.xml,定位到资源文件/demo

  • 然后tomcat就能通过/demo找到servlet-name为demo的cn.zqq.web.servlet.ServletDemo这个类

    这边tomcat将全类名对应的字节码文件加载进内存,然后创建其对象,调用这个类里的方法,所以service方法就被成功的执行了(即tomcat进行了反射操作)

  • service方法被执行后,我们就看到了在控制台中输出的结果

Servlet生命周期

1.被创建

​ 被创建时,会自动执行初始化方法init,只会执行一次

  • 什么时候被创建?

    根据配置文件web.xml中的<load-on-startup>的值来定(默认值为-1)

<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>cn.zqq.web.servlet.ServletDemo</servlet-class>
    <load-on-start-up></load-on-start-up>
</servlet>
  • <load-on-start-up>的值为负数,就在第一次被访问时创建

  • <load-on-start-up>的值为0或正整数,就在服务器启动时创建

  • Servlet的init方法只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的

    • 多个用户同时访问时,可能存在线程安全问题
    • 解决: 尽量不要在Servlet中定义成员变量。即使定义了成员变量也不要修改它的值

2.提供服务

​ 在每次被访问时,会自动执行提供服务的方法service,可以执行多次

3.被销毁

​ 在服务器正常关闭时,会自动执行销毁方法destory,只会执行一次

​ 但是,如果服务器没有正常关闭,就不会执行destory方法

​ destory是在Servlet被销毁之前执行

  • Servlet还有两个方法

    • 获取ServletConfig对象的方法: getServletConfig() (不常用)
    • 获取Servlet的信息的方法(版本、作者等信息):getServletInfo() (不常用)

Servlet注解配置

  • 注意:注解配置需要在Servlet版本3.0以上才可以(要求 Java EE6版本及其以上)

  • 好处

    ​ 使用注解配置,就可以不用创建web.xml了,写起来会更加方便

  • 步骤

    1.创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml

    2.定义一个类,实现Servlet接口

    3.复写方法

    4.在类上使用@WebServlet注解,进行配置@WebServlet("资源路径")

    说明:相当于刚才tomcat通过url中的/demo找到web.xml定位到我们实现Servlet的那个类的这个过程,用一个注解来实现了(因为注解直接写在类上面了,所以就直接定位到这个类)

package cn.zqq.web.servlet;

import javax.jws.WebService;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet("/demo")
public class ServletDemo1 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("快速上手Servlet。");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

Servlet的体系结构

Servlet --接口

GenericServlet --抽象类 是Servlet的实现类

HttpServlet --抽象类 是GenericServlet的子类

  • GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
    • 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
  • HttpServlet:对http协议的一种封装,简化操作
    • 定义类继承HttpServlet
    • 复写doGet/doPost方法

Servlet相关配置

1.urlpartten:Servlet访问路径

  • 一个Servlet可以定义多个访问路径:@WebServlet({"/demo","/demo2","/demo3"})

  • 路径定义规则:

    • /xxx:一层路径

    • /xxx/xxx:两层路径,以后访问的时候就需要写两层路径

      • 使用*通配符时,不管写什么都能访问到 /*
    • *.do这种不需要加/,但是需要以.do结尾,.do也可以换成其他自己定义的后缀

HTTP

HTTP概述

概念:Hyper Text Transfer Protocol 超文本传输协议

  • 传输协议:定义了客户端和服务器端通信时,发送数据的格式

  • 特点

    1.基于TCP/IP的高级协议

    2.默认端口号:80

    3.基于请求/响应模型:一次请求对应一次响应

    4.无状态:每次请求之间相互独立,不能交互数据

  • 历史版本

    • 1.0:每一次请求响应都会建立新的连接
    • 1.1:复用连接

请求消息:客户端发送给浏览器发送的数据

1.请求行

​ 格式:请求方式 请求url 请求协议/版本

​ 示例:GET /login.html HTTP/1.1

  • 请求方式

    • HTTP协议有7种请求方式,常用的有2种

      • GET

        1.请求参数在请求行中,在url后

        http://localhost/demo?username=zhangsan

        2.请求的url长度有限制的

        3.相对不太安全(参数在url后面,容易被看到)

      • POST

        1.请求参数在请求体中

        2.请求的url长度没有限制

        3.相对安全(如果请求被拦截也是可以被看到的)

2.请求头

​ 客户端浏览器告诉服务器一些信息

​ 格式: 请求头名称:请求头值

  • 常见的请求头

    • User-Agent:浏览器告诉服务器,访问服务器所用的浏览器版本信息

      可以在服务器端获取该头的信息,解决浏览器的兼容性问题

      在服务器端,获取浏览器的版本,响应对应版本的页面给服务器

    • Referer:告诉服务器,当前请求从哪里来

      • 作用

        1.防盗链(判断请求从哪来,如果是自己网站来的,就可以访问,如果是别人的网站,就不让访问,不把资源响应过去,防止自己的资源被通过链接的方式盗用)

        2.统计( )

3.请求空行

​ 用于分割POST请求的请求头和请求体

4.请求体(正文)

​ 拥有封装POST请求消息的请求参数

响应消息:服务器端发送给客户端的数据

1.响应行
  • 组成:协议/版本 响应状态码 状态码描述
  • 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
    • 状态码都是3位数字
    • 分类:
      • 1xx: 服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx多状态码
      • 2xx: 成功 代表: 200
      • 3xx: 重定向 代表: 302(重定向) 304 (访问缓存)
      • 4xx: 客户端错误
        • 代表:
          • 404 (请求路径没有对应的资源)
          • 405 (请求方式没有对应的doGet/doPost方法)
      • 5xx: 服务器端错误。代表:500 (服务器内部出现异常)
2.响应头
  • 格式: 头名称: 值

  • 常见的响应头

Content-Type :服务器告诉客户端本次响应体数据格式以及编码格式
Content-disposition:服务器告诉客户端以什么格式打开响应体数据
值:
	1.in-line:默认值,在当前页面内打开
	2.attachment;filename=xxx:以附件形式打开响应体。文件下载
3.响应空行
4.响应体:真实传输的数据

Request

1.Request对象和Response对象原理

  • 原理
1.tomcat服务器会根据url中的资源路径,创建对应的ServletDemo对象
2.tomcat服务器,会创建request和response对象,request对象中封装请求消息数据
3.tomcat将request和response两个对象传递给service方法,并调用service方法
4.开发者在service中通过request对象获取请求消息数据,通过response对象设置响应消息数据
  • 注意

    1.request对象和response对象是由服务器创建的,我们来使用它们

    2.request对象是来获取请求消息,response对象是来设置响应消息

2.request对象继承体系结构

  • ServletRequest–接口

  • HttpServletRequest --接口 继承于ServletRequest

  • org.apache.catalina.connector.RequestFacade --类(tomcat)

    实现了HttpServletRequest接口

3.request功能

  • 获取请求消息

    • 获取请求行数据

      方法:

      • 获取请求方式: getMethod() 返回值:String类型

      • 获取虚拟目录:getContextPath() 返回值:String类型

      • 获取Servlet路径:getServletPath() 返回值:String类型

      • 获取get方式请求参数:getQueryString() 返回值:String类型

      • 获取请求URI:

        1.getRequestURI() 返回值:String类型

        2.getRequestURL() 返回值:StringBuffer类型

      • 获取协议及版本:getProtocol() 返回值:String类型

    • 获取请求头数据

      方法:

      • 通过请求头的名称获取请求头的值:getHeader(String name)返回值:String类型
      • 获取所有的请求头名称:getHeaderNames() 返回值类型:Enumeration<String>
    • 获取请求体数据

      • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

      • 步骤

        1.获取流对象(有两个方法)

        方法1:getReader() 返回值:BufferedReader类型:获取字符输入流,只能操作字符数据

        方法2:getInputStream() 返回值:ServletInputStream类型:获取字节输入流,可以操作所有数据

        2.再从流对象中拿数据

  • 其他功能(常用)

    • 获取请求参数通用方式(get post都可以用)
1.String getParameter(String name):根据参数名称获取参数值 
2.String[] getParameterValues(String name):根据参数名称获取参数值的数组
3.Enumeration<String> getOarameterNames():获取所有请求的参数名称
4.Map<String,Stringp[]> getPrameterMap():获取所有参数的map集合
中文数据乱码问题解决

get方式:tomcat 8 及以上版本 已经将get方式乱码问题解决了

post方式:设置流的编码:`setCharacterEncoding("utf-8");`
  • 请求转发

  • 共享数据

  • 获取ServletContext

  • request请求转发

    一种在服务器内部的资源跳转方式

    步骤

1.通过request对象获取请求转发器对象:
RequestDispatcher getRequestDispatcher(String Path)
2.使用RequestDispatcher对象来进行转发:
forward(ServletRequest request,ServletResponse response)
3.特点:
(1)浏览器地址栏路径没有发生变化
(2)只能转发到当前服务器内部的资源中
(3)转发是一次请求
  • request共享数据

    域对象:一个有作用范围的对象,可以在范围内共享

    request的域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

    方法:

1.setAttritube(String name,Object obj):存储数据(在转发之前)
2.Object getAttritube(String name):通过键值获取
3.void removeAttribute(String name):通过键值对移除
  • request获取ServletContext

    方法:ServletContex getServletContext()

Response

1.response 功能:设置响应消息

1.设置响应行
(1)格式:HTTP/1.1 200 OK
(2)设置状态码:setStatus(int sc)
2.设置响应头setHeader(String name,String value)
3.设置响应体
使用步骤:
(1)获取输出流  
-字符输出流: printWriter getWriter()
-字节输出流: ServletOutputStream getOutputStream
(2)使用输出流,将数据输出到输出流

2.重定向

当浏览器访问A资源时,A资源告诉浏览器,需要访问B资源

1.告诉浏览器重定向:  状态码302
2.告诉浏览器B资源的路径: 响应头location:B资源的路径
response.setStatus(302);
response.setHeader("location","这里写B资源路径");
也可以用简单的重定向方法: response.sendRedirect("这里写B资源路径")
  • 重定向的特点

    1. 地址栏发生变化

    2. 重定向可以访问其他站点的资源

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

  • 路径写法

    • 相对路径

      • 如: ./index.html

      • 不以/开头,以.开头的路径 (./可以省略不写)

      • 规则:找到当前资源和目标资源之间的相对位置关系

        • 当前目录: ./

        • 后退一级目录 ../

    • 绝对路径:通过绝对路径可以确定唯一资源

      • 如:http://localhost/img/test.jpg /img/test.jpg

      • /开头的路径

      • 规则:判断定义的路径是给谁用的, 判断请求将来从哪发出

        • 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
          • 建议虚拟目录动态获取: request.getContextPath()
        • 给服务器使用:不需要加虚拟目击了
      • 说明

        • 转发,就不需要写虚拟目录,直接写资源目录
        • 重定向是客户端路径,需要写虚拟目录

3.服务器输出字符数据到浏览器

  • 步骤:(需要解决乱码)
//获取流对象之前,获取流的默认编码:  ISO-8859-1   比如 设置为:utf-8
//	response.setCharacterEncoding("utf-8");
//告诉浏览器,服务器发送的消息体数据的编码,建议使用该编码解码
//	response.setHeader("content-type","text/html;charset=utf-8");
//简单的方式设置编码
response.setContentType("text/html;charset=utf-8");
//获取字符输出流
PrintWriter pw = response.getWriter();
//输出数据
pw.write("<h1>测试输出</h1>");

4.服务器输出字节数据到浏览器

  • 步骤
//设置编码
response.setContentType("text/html;charset=utf-8");
//获取字符输出流
ServletOutputStream ss= response.getOutputStream();
//输出数据(字节流输出字符串要用getBytes方法)
ss.write("hello response".getBytes("utf-8"));

5.验证码

  • 本质:图片

  • 目的:防止恶意表单注册

  • 步骤

int width = 100;
int height = 50;
//1.创建一个对象,在内存中图片
BufferedImage image = new BufferedImage(width,height,BufferedImage.Type_INT_RGB)
//2.美化图片
//2.1填充背景色
Graphics g = image.getGraphics(); //画笔对象
g.setColor(Color.PINK);//画笔颜色
g.fillRect(0,0,width,height);
2.2画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width-1,height-1)

//2.3随机生成验证码   
    
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
//生成随机角标
Random ran = new Random();
for(int i = 1;i<=4;i++){
    int index = ran.nextInt(str.length());
    char ch = str.charAt(index)//随机字符
    g.drawString(ch+"",width/5*i,height/2);
}

//2.4画干扰线
g.setColor(Color.GREEN);
//随机生成坐标点
for(int i = 1;i<=10;i++){
    int x1 = ran.nextInt(width);
    int x2 = ran.nextInt(width);
    int y1 = ran.nextInt(height);
    int y2 = ran.nextInt(height);
    g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",response.getOutputStream());
  • 点击切换图片,只需要在图片的点击事件中修改url地址
 var img = document.getElementById("checkCode");
 img.onclick = function(){
 	//加时间戳是为了图片能不断刷新,避开浏览器的内存
 	var date = new Data().getTime();
 	img.src = "/test/checkCodeServlet?"+date;
 }

ServletContext对象

  • 概念:代表整个web应用,可以和程序的容器(服务器)来通信

  • 获取:

    1. 通过request对象获取

      request.getServletContext();

    2. 通过HttpServlet获取

      this.getServletContext();

  • 功能

    1. 获取MIME类型

      • MIME类型:在互联网通信过程中定义的一种文件数据类型
      • 格式: 大类型/小类型 text/html image/jpeg
      • 获取:String getMimeType(String file);
    2. 域对象:共享数据

      • setAttribute(String name,Object value)
      • getAttribute(String name)
      • removeAttribute(String name)
      • ServletContext对象范围:所有用户所有请求的数据
    3. 获取文件的真实(服务器)路径

      方法:String getRealPath()

//通过HttpServlet获取
ServletContext context = this.getServletContext();
//获取文件的服务器路径
String realPath = context.getRealPath("/b.txt");//web目录下访问资源
String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问

文件下载

文件下载需求

  1. 页面显示超链接
  2. 点击超链接后弹出下载提示框
  3. 完成图片文件下载

分析

  1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示(比如图片),如果不能解析,则弹出下载提示,不满足需求

  2. 我们需要任何资源都必须弹出下载提示

  3. 解决: 使用响应头设置资源的打开方式

content-disposition:attachment;filename = xxx

步骤

  1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename

  2. 定义Servlet

    1. 获取文件名称
    2. 使用字节输入流加载文件进内存
    3. 指定response的响应头:content-disposition:attachment;filename = xxx
    4. 将数据写出到response输出流
//1.获取文件名称
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/"+filename);
//2.2使用字节流关联
FileInputStream fis = new FileInputStream(realPath);
//2.3将输入流的数据写出到输出流中
//3.指定response的响应头:content-disposition:attachment;filename = xxx
//3.1设置响应头 content-type
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将数据写出到response输出流
ServletOutoutStream ss = response.getOutPutStream();
byte[] buff = new byte[1024*8];
int len = 0;
while((len = fis.read(buff))!=-1){
ss.write(buff,0,len);
}

3.中文文件乱码问题

  • 解决思路

    1. 获取客户端使用的浏览器版本信息
    2. 根据不同的浏览器版本信息,设置不同的编码信息,响应不同的数据
String agent = request.getHeader("user-agent");
//工具类DownLoadUtils  可以去网上找,随便找一个都可以
filename = DownLoadUtils.getFileName(agent,filename);
response.setHeader("content-disposition","attachment;filename="+filename);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

棋小仙

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

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

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

打赏作者

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

抵扣说明:

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

余额充值