servlet学习笔记
Servlet简介
Servlet 是运行在服务器上的程序。它的作用是充当HTTP客户端请求与数据库之间的中间层。服务器通过servlet来响应HTTP客户端的请求。
在java中指定了servlet的规范(接口)。在使用时,我们需要通过自定义类或者HttpServer类来实现servlet接口。
生命周期
servlet的生命周期由servlet容器即服务器控制,常用的服务器如Tomcat。生命周期主要分为四个阶段:
- 实例化 ,默认情况是当servlet第一次被访问的时候,由服务器创建servlet对象;当然也可通过设置loadOnStartup 来进行预加载,即在服务器启动时便创建。
@WebServlet(urlPatterns = "/", loadOnStartup=0)
。其中loadOnStartup 大于等于0生效。数字越小,优先级越高。 - 初始化,当Servlet实例化之后,服务器会调用Servlet的
init()
来初始化对象,完成一些初始化工作,只调用一次。 - 请求处理,每次请求Servlet时,服务器都会调用Servlet的
service()
来处理请求 - 服务终止,当需要释放内存或服务器关闭时,服务器会调用Servlet的
destroy()
来完成资源释放,在destroy()
执行完成后,Servlet实例会被服务器释放,并最终被java垃圾收集器回收。
Servlet的实现
J2EE标准中定义了Servlet接口,当我们想要使用Servlet时,需要定义类来实现Servlet接口的方法。
Servlet方法
- 初始化方法
void init(ServletConfig config)
- 服务方法,响应Http请求
void service(ServletRequest req, ServletResponse res)
- 销毁方法,内存释放或服务器关闭时调用
void destroy()
- 获取ServletConfig对象(少见)
ServletConfig getServletConfig()
- 获取Servlet信息(少见)
String getServletInfo()
HttpServlet
HttpServlet 是对HTTP协议封装的Servlet实现类,同时也是抽象类,需要重写doGet()
和doPost
。B/S架构的web项目,都是使用HTTP协议。因此,我们会使用HttpServlet来自定义Servlet。
简单实现代码如下:
@WebServlet("/demo")
public class ServletDemo extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
//Get 请求处理
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
//Post请求处理
}
}
urlPattern配置
- 精准匹配
@WebServlet(urlPattern = {"/demo","demo1"})
//访问路径:localhost/demo 或者localhost/demo1
//web端口:80
- 目录匹配
@WebServlet(urlPattern ="/demo/*")
//访问路径:localhost/demo/xxx
//web端口:80
- 扩展名匹配
@WebServlet(urlPattern ="*.do")
//访问路径:localhost/xxx.do
// /*会报错
//web端口:80
- 任意匹配
@WebServlet(urlPattern ="/")
or
@WebServlet(urlPattern ="/*")
//访问路径:localhost/xxx.do
// /*会报错
//web端口:80
- 优先级,精准>目录>扩展名>/* > /
Request & Response
Request和Response是浏览器和服务器之间沟通的桥梁,浏览器通过Request向服务器发送请求信息并请求服务,而Response则可以帮助服务器向浏览器发送响应信息。
Request
在Servlet中使用的是ServletRequest 接口,而在HttpServlet中使用的是HttpServletRequest接口。这些接口也将由服务器创建类来实现。当浏览器向服务器发送请求时,服务器会实例化一个Request对象来接受请求信息。比如Tomcat中定义了RequestFacade类来实现HttpServletRequest接口。
获取请求数据
请求数据可以分为四部分:
- 请求行
方法 | 效果 |
---|---|
String getMethod() | 获取请求方式 如:GET,POST |
String getContextPath() | 获取虚拟目录(即url根目录) |
StringBuffer getRequestURL() | 获取URL |
String getRequestURI() | 获取URI,即url端口号后面的部分 |
String getQueryString() | 获取请求参数 例如: username=zhangsan&password=123 |
- 请求头
方法 | 效果 |
---|---|
String getHeader(String name) | 获取头中对应name的值 |
- 请求体(post)
方法 | 效果 |
---|---|
String getInputStream() | 获取字节输入流 |
String getReader() | 获取字符输入流 |
- 通用
方法 | 效果 |
---|---|
Map<String, String[]>getParameterMap() | 获取所有参数的Map集合 |
String[] getParameterValues(String name) | 根据name获取对应参数值(数组) |
String getParameter(String name) | 根据name获取对应参数值 |
Enumeration getParameterNames(String name) | 获取form表单中控件的name(枚举) |
中文乱码问题
- 中文乱码
原因:GET浏览器和服务器端的编码方式不同(tomcat8之后的不会出现)
解决方法:对字符串重新编码。
post方式传输的可以通过request.setCharacterEncoding("编码方式")
来设置字符读入流的编码方式
请求转发
服务器内部的资源间转发。请求转发是服务器行为,因此客户端不会察觉即客户端的地址栏不会改变。
实现方式
request.getRequestDispatcher("资源b").forward(request,response);
参数共享
方法 | 作用 |
---|---|
void setAttribute(String name, Object obj) | 以键值对形式,在request域中存储数据 |
Object getAttribute(String name) | 获取name对应的数据 |
void removeAttribute(String name) | 根据 name 删除键值对 |
Response
Response的体系结构和Resquest类似
响应数据
响应数据分为三部分
- 响应行
HTTP/1.1 200 OK
void setStatus(int sc): 设置状态码,常用的200(ok),302(重定向),404(请求资源找不到)500(服务器端出错) - 响应头
Content-Type: text/html
void setHeader(String name, String value): 设置响应头 - 响应体
<html>hello<html/>
- PrintWriter getWriter(): 字符输出流
//设置编码,浏览器解析html时采用utf-8, //而解析文字时使用系统编码字符集,即windows一般使用GBK。 resp.setContentType("text/html;charset=utf-8");//让浏览器以html来解析响应数据 resp.setCharacterEncoding("gbk"); PrintWriter writer = resp.getWriter(); writer.write("你好");
- ServletOutputStream getOutputStream(): 字节输出流
InputStream fis = this.getClass().getResourceAsStream("/a.jpg"); ServletOutputStream ops = resp.getOutputStream(); IOUtils.copy(fis,ops);
- PrintWriter getWriter(): 字符输出流
重定向
浏览器端的资源跳转,可以跳转到任何可以跳转到的资源。重定向后浏览器地址会发生改变
代码实现:
方法一:自己设置状态码302,并告知浏览器重定向的目标资源位置
resp.setStatus(302);
resp.setHeader("Location","https:www.baidu.com");
方法二:直接调用重定向方法,底层实现过程就是方法一
resp.sendRedirect("/demo/login.html");
注意:当访问内部资源时需要加虚拟目录即:/demo
,而访问外部资源时加https: