JavaWeb-Servlet

Servlet是和平台无关的服务器端组件,运行在Servlet容器中。Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,Servlet和客户的通信采用“请求/响应”的模式。

Servlet可完成的功能:

  • 创建并返回基于客户请求的动态HTML页面
  • 创建可嵌入到现有HTML页面中的部分HTML页面
  • 与其他服务器资源进行通信

Tomcat就是Servlet容器

  • 可以用来创建Servlet,并调用Servlet的相关生命周期方法

Servlet生命周期方法:

  • 构造器方法:第一次请求Servlet时,创建Servlet的实例,调用构造器(只被调用一次)
  • init方法:只被调用一次,创建好实例后立即被调用,用于初始化当前Servlet
  • service方法:被多次调用,每次请求都会调用service方法,实际用于响应请求的
  • destroy方法:只被嗲用一次,在当前Servlet所在的web应用被卸载前调用,用于释放当前Servlet所占用的资源

<load-on-startup>1</load-on-startup>
这个标签参数可以指定Servlet被创建的时机

  • 配置在Servlet节点中
  • 若为负数,则在第一次请求时被创建,若为0或正数,则在当前web应用被Servlet容器加载时创建实例,且数越小越早被创建

ServletConfig:保存了Servlet的各项配置,并且可以获取ServletContex对象

ServletContext:

  • 可以由ServletConfig获取
  • 代表当前web应用,可以认为ServletCOntext是当前web应用的一个大管家
  • 获取当前web应用的某一个文件的绝对路径,文件在服务器上的路径,而不是部署前的路径
    getRealPath()
  • 获取当前web应用名称
    getContextPath()
  • 获取当前web应用的某一个文件对应的输入流
    getResourceAsStream(String path):path的/为当前应用的根目录

HTTP的会话方式:

  • 建立连接
  • 发出请求信息
  • 回送响应信息
  • 断开连接

Get请求和Post请求

  • 在浏览器地址栏输入某个URL地址或单继网页上的一个超链接时,浏览器发出的HTTP请求为GET
  • 如果网页中的form表单元素的method属性被设置为GET,浏览器提交这个form表单时生成的HTTP请求为GET
  • 使用GET方式传送的数据量一般限制在1kb以下

Post方式传递参数

  • post请求方式主要用于向web服务器端程序提交form表单中的数据,form表单的mehtod设置为post
  • post方式将各个表单字段元素及其数据作为http消息的实体内容发送给web服务器,传送的数据量要比使用get方式传送的数据量大得多
    响应状态码含义:
  • 200:请求成功
  • 302:请求重定向
  • 304:请求资源没有改变,访问本地缓存
  • 404:请求资源不存在,通常是用户路径编写错误,也可能是服务器资源已经删除
  • 500:服务器内部错误,通常程序抛异常

Java反射机制

  • 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
  • 对于任意一个对象,都能够调用他的任意一个方法和属性
  • 想要使用反射,必须获取字节码文件

获取字节码文件的方式

  • Object类的getClass方法
  • 静态属性 class
  • class类中静态方法forName

反射中获取私有属性

  • getDeclaredField()
  • setAccessable(true)

反射中获取私有方法

  • getDeclaredMethod()
  • setAccessable(true)

Servlet中的init()方法和destroy()方法

  • init()方法:在Servlet创建的时候调用,也可以通过配置在服务器一启动就开始调用。具体方法是:在web.xml中配置选项,<load-on-startup>标签可以设置优先级,填写数字代表优先级
  • service方法():每一次请求的的时候进行调用,每次发送请求都会调用service方法();
  • destroy()方法:当servlet被销毁的时候调用,当服务器关闭的时候调用

Servlet访问流程


image.png

init()方法参数介绍

public void init(ServletConfig servletConfig) throws ServletException {
}

servletConfig 可以获取一些配置信息
1.可以获取Servlet名称 web.xml
2.获取web.xml中的初始化参数
3.获取ServletContext

url-patten匹配形式

  • 完全匹配
    就是在web.xml中的url-patten必须跟要在地址栏写的完全一致才可以

目录匹配
类似于导包时候的 .
*,只要在前面写好目录,不管具体的文件是什么,最终都能访问到目录下的servlet

  • 扩展名匹配
    // *.myxq
    只要扩展名是.myxq结尾的都可以被访问到

url-patten缺省值与静态资源的访问流程

  • 如果都没有匹配到url-patten,就会找缺省,缺省的名称就是<servletname>对应的Servlet。<url-pattern>/</url-pattern>

静态资源加载过程

  • 在path后面写的静态资源名称index.html或者其他的.html他都是会找url-pattern当中有没有匹配的内容
  • 如果有,就加载对应的servlet,如果没有就自己到配置当中找缺省的url-pattern
  • 如果自己配置文件当中没有缺省的,就会找全局配置缺省的url-pattern
  • 在全局配置当中有一个缺省的url-pattern, 对应的default的Servlet
  • defaultServlet内部会到当前访问的工程根目录当中去找对应的名称的静态资源,如果有,就把里面的内容逐行输出,响应给浏览器
  • 如果没有,就会报404错误

使用注解创建Servlet
@WebServlet("/myServlet)

  • 这个相当于一个注解
  • 相当于在代码上添加了一个小插件
  • 贴上这个注解以后,就不用再去做配置文件,系统自动做
  • 括号当中的内容就是url-pattern的内容,要在地址栏当中path后面跟的内容

doGet()方法

  • 当get请求时会调用该方法

doPost()方法

  • 当post请求时会调用该方法

当一个Servlet类继承自HttpServlet时,如果复写了父类的Service方法,那么不管是通过post方式提交请求还是get方式提交请求,都会直接调用Service方法。即,一旦写了Service方法,就不会调用doPost和doGet方法。


image.png
image.png

ServletContext对象

  • 代表web应用的上下文对象,一个web应用只有一个ServletContext对象
  • 里面封装的都是web应用信息
  • 一个ServletContext对应一个应用
    生命周期
  • 服务器启动就会被创建
  • 服务器关闭销毁

如何获得上下文

  • 通过init()方法当中一个参数ServletConfig来获取

    @Override
    public void init(ServletConfig config) throws ServletException {
        ServletContext servletContext=config.getServletContext();
        System.out.println(servletContext);
    }

ServletContext 获取文件路径

ServletContext context=this.getServletContext();
String realPath =context.getRealPath("WEB-INF/b.txt");
System.out.println(realpath);

//使用类加载器,获取字节码的路径
//到字节码目录中加载资源

String path=OneServlet.class.getClassLoader().getResource("");
System.out.println(path);

ServletContext是一个域对象,是指能够存储数据

  • 作用范围:整个web应用,所有的web资源都i可以进行存取数据,数据是可以共享的
    如何王ServletContext里面写数据:
  • contex.setAttribute(String name,Object object)

取数据

  • context.getAttribute(String name)

删除指定值

  • context.removeAttribute(String name)

只要是一个域对象,里面都有这几个方法

Response对象
学习response主要就是学习通过response设置响应行,响应头,响应体

response响应过程:

  • 发送一个请求时,会找到tomcat引擎
  • 引擎会找到相应的web应用,并且会创建request对象和response对象
  • 找到应用后,会执行应用的web.xml再去根据url-pattern的内容创建Servlet对象
  • 并且会调用Servlet对象的service方法,并且把创建的request对象和response对象传入到方法当中
  • 拿到response对象后,可以往响应当中写入一些自己给客户端的内容
  • 写的内容是存到一个response缓冲区当中
  • 当方法执行结束之后,tomcat就会从response缓冲区当中取出数据

设置响应行

  • response.setState(int code) 设置状态码

设置响应头

  • 主要有add和set两个方法


    image.png

response重定向

  • 访问两次服务器,第一次是人为的去访问,第二次是自动访问
  • 浏览器地址两次发生了变化

设置重定向
response.setHeader("location","另一个servlet");
另一种重定向方法
response.sendRedirect("另一个servlet");
定时刷新也是一种重定向
response.setHeader("refresh","另一个servlet")

设置响应体

  • 通过write方法
    response.getWrite().write(要写的内容)

默认情况下写的中文内容会乱码,因为写的内容在存到缓冲区中使用的是ISO8859编码,不支持中文。

如何解决中文乱码问题

在存之前设置存放的编码,response.setCharacterEncoding
告知浏览器使用的是utf-8编码
缓冲区及浏览器都有自己的编码格式,当更改了缓冲区编码方式仍然出现中文乱码时,应该更改浏览器的编码方式。

//设置缓冲区的编码格式
        resp.setCharacterEncoding("utf-8");
        //在响应中主动告诉浏览器通过什么样的编码格式接受
        resp.setHeader("Content-Type","text/html;charset=UTF-8");

上述两行代码可以通过如下一行代码替换

response.setContentType("text/html;charset=UTF-8");

设置编码格式要在设置内容之前完成,

image.png
  • 通过outputstream方法可以完成读取图片等媒体资源
    主要就是文件读取操作,需要注意的一点就是对文件的访问操作,通过文件名访问文件时,文件的路径在idea中需要注意,通过idea做动态网站,文件位置并非放置在tomcat浏览器中,而是在下图中的左侧out文件夹下,也就是说,通过getRealPath获取到的路径是E:\project\javaproject\ThirdWeb\out\artifacts\ThirdWeb_war_exploded
    所以通过getRealPath获取路径之后,想直接访问静态资源,可以把资源直接放在_war_exploded根目录下面
image.png

getWrite()和outputstream不能同时存在。


下载文件

  • 通过a标签
    直接使用a标签可以下载文件,但是下载的文件只能是压缩文件等,图片和mp4等类型的文件是不能够下载下来的,当点击下载这些文件时,浏览器会去解析这些文件。

  • 通过发送请求的方式下载文件

该方式不能识别出所有的文件类型,因此需要设置文件类型。


设置下载文件类型

  1. 设置mimeType
  2. 告诉浏览器以附件的形式打开
@WebServlet("/DownloadServlet2")
public class DownloadServlet2 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String name=req.getParameter("filename");
        String path = this.getServletContext().getRealPath(name);
        System.out.println(path);

        String mimeType = this.getServletContext().getMimeType(name);
        //设置mimetype
        resp.setContentType(mimeType);
        //告诉浏览器以附件的形式打开
        resp.setHeader("Content-Disposition","attachment;filename="+name);
        //根据path加载文件

        FileInputStream in = new FileInputStream(path);
        ServletOutputStream servletOutputStream = resp.getOutputStream();
        byte[] buffer = new byte[1024];
        int len=0;
        while ((len=in.read(buffer))!=-1) {
            servletOutputStream.write(buffer);
        }
        in.close();
    }
    }


Request


image.png
  • 请求行
    1.获取请求方式
    request.getMethod();
    2.请求资源url uri
    request.getRequestURL();
    request.getRequestURI();
    下图中第一个是URL
    第二个是URI


    image.png

    3.获取get请求参数
    request.getQueryString();
    这里获取到的都是请求的参数信息


    image.png

    4.获取当前web应用名称
    request.getContentPath();
    获取到的是当前工程的名字

请求头
1.获取所有请求头名称

Enumeration<String> headerNames=request.getHeaderNames();
while(headerNames.hasMoreElements())
System.out.println("name="+headerNames.nextElements());

请求体
1.获取一个值
request.getParameterValue();
2.获取多个值
request.getParameterValues();
3.获取所有请求参数名称
request.getParameterNames();
4.获取所有请求参数
request.getParameterMap();


get和post方式如何选择
1.发送的参数不需要写到数据库用get方式
2.发送的参数需要保存到数据库用post


renquest请求转发
请求转发跟重定向的区别在于,请求转发是直接通过一个找另一个,不需要返回再重新找。


image.png

实现转发
1.通过请求对象获取一个转发器request.getRequestDispatcher(String path)
返回一个RequestDispatcher
2.通过转发器进行转发
调用转发器的forward()方法进行转发
disp.forward(req,rep)


image.png

request域对象
1.在一次请求过程当中存在的且共享


客户端地址与服务器端地址

  • 客户端地址
    客户端访问服务器使用的地址
    服务器外部地址
    写的时候要写上web应用的名称/应用名称/资源
  • 服务器地址
    服务内部当中使用的地址
    不需要写web应用名称/资源名称

cookie与Session

会话技术

什么是会话

  • 用户点开一个浏览器
  • 点击多个超链接,访问多个web资源
  • 再关闭浏览器,整个过程称之为一个会话

解决什么问题

  • 保持各个客户端自己的数据
  • 存临时数据

Session技术

Session域当一个浏览器访问服务器创建,关闭服务器或过期时,销毁Session域对象。
将数据存储到服务器,安全性相对好,增加服务器压力
会为每个客户端都创建一块内存空间存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间。所以说Sesssion的实现是基于Cookie。Session需要借助于Cookie存储客户的唯一性标识JSESSIONID。

获取Session对象

//方法内部判断该客户端是否在服务器端已经存在Session
//有则不创建,否则新创建session对象
HttpSession session=request.getSession();
String id=session.getId();

Session对象生命周期

创建:第一次执行request.getSession()时创建
销毁:

  • 服务器关闭时
  • session过期或者失效(默认30分钟) ,从不操作服务器端的资源开始计时
  • 手动销毁session(session.invalidate())

cookie技术

数据存储在客户端本地,减少服务器端压力,安全性不好,客户端可以清除cookie


image.png

服务器如何把cookie写给客户端

  • 创建cookie(会以响应头的形式发送给客户端;只能存储非中文的字符串)
    Cookie cookie=new Cookie(String cookieName,String cookieValue)
  • 向客户端发送cookie
    response.addCookie(cookie名称)
  • 访问
  • cookie默认存储时间
  • 设置cookie的携带路径
  • 删除cookie

默认cookie的生命周期是会话级别,打开浏览器和关闭浏览器为一次会话,如果不设置持久化时间,cookie会存储在浏览器内存,浏览器关闭,cookie信息销毁

设置cookie的持久化时间需要在发送cookie之前进行。cookie.setMaxAge(60); 单位时间是秒,过期cookie自动销毁

  • 设置cookie的携带路径
    意思是在访问某一个资源时,要不要先携带cookie信息
    如果不设置携带路径,默认情况下会在访问创建cookie的web资源相同的路径都携带cookie信息(比如创建cookie的servlet文件在一个目录下,那么在servlet的上级文件目录中的所有web资源都会存在该cookie信息)
    设置路径方式
    cookie.setPath(String path);
  • cookie.setPath("/CookiePro/cookieServlet") 只有访问该servlet才携带cookie信息
  • cookie.setPath("/CookiePao") 只要在该工程下,都会携带cookie信息
  • cookie.setPath("/"); 只要访问该服务器,都会携带cookie信息

删除cookie:创建一个重名的cookie,设置cookie的存活时间为0

服务器如何获取客户端携带的cookie

  • 通过request对象的getCookie()方法
  • 获取的是所有的cookie
  • 进行遍历,找出自己名称的那一个
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容