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访问流程
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方法。
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两个方法
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");
设置编码格式要在设置内容之前完成,
- 通过outputstream方法可以完成读取图片等媒体资源
主要就是文件读取操作,需要注意的一点就是对文件的访问操作,通过文件名访问文件时,文件的路径在idea中需要注意,通过idea做动态网站,文件位置并非放置在tomcat浏览器中,而是在下图中的左侧out文件夹下,也就是说,通过getRealPath获取到的路径是E:\project\javaproject\ThirdWeb\out\artifacts\ThirdWeb_war_exploded
所以通过getRealPath获取路径之后,想直接访问静态资源,可以把资源直接放在_war_exploded根目录下面
getWrite()和outputstream不能同时存在。
下载文件
通过a标签
直接使用a标签可以下载文件,但是下载的文件只能是压缩文件等,图片和mp4等类型的文件是不能够下载下来的,当点击下载这些文件时,浏览器会去解析这些文件。通过发送请求的方式下载文件
该方式不能识别出所有的文件类型,因此需要设置文件类型。
设置下载文件类型
- 设置mimeType
- 告诉浏览器以附件的形式打开
@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
-
请求行
1.获取请求方式
request.getMethod();
2.请求资源url uri
request.getRequestURL();
request.getRequestURI();
下图中第一个是URL
第二个是URI
3.获取get请求参数
request.getQueryString();
这里获取到的都是请求的参数信息
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请求转发
请求转发跟重定向的区别在于,请求转发是直接通过一个找另一个,不需要返回再重新找。
实现转发
1.通过请求对象获取一个转发器request.getRequestDispatcher(String path)
返回一个RequestDispatcher
2.通过转发器进行转发
调用转发器的forward()方法进行转发
disp.forward(req,rep)
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
服务器如何把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
- 进行遍历,找出自己名称的那一个