写目录
一、继承HttpServlet
1.1 使用HttpServlet创建Servlet的步骤
第一步:定义一个Java类,继承HttpServlet。
第二步:重写doGet或doPost方法。
- doGet方法:接收Get请求;
- doPost方法:接收Post请求;
public class Demo01Servlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().write("doPost...");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
1.2 Servlet的访问过程
- 当浏览器请求服务器的时候,浏览器会根据url地址的ip和端口号找到对应的服务器。
- 服务器接收到浏览器发送过来的请求后,会根据url地址的上下文路径查找webapps目录下是否存在与上下文名称相同的文件夹
- 如果存在,那么服务器就会在文件夹下查找web.xml文件,然后在该文件中查找所有的url-pattern节点。
- 如果url-pattern节点内容与url地址的访问路径相匹配,那么就通过servlet-name节点找到对应的Servlet-class节点。
- 获取Servlet-class节点内容,使用反射技术创建Servlet对象,并调用service方法。
二、Http请求详解
如果一个资源里面还要加载其他资源,那么每个资源都会向服务器发起一次请求。
Http请求的组成:请求行、请求头和请求正文。
2.1 请求行
请求行包含请求的基本信息。比如请求地址、请求方式等等。
Request对象提供了获取请求行信息的方法:
- getMethod: 获取请求方式
- getRequestUrl:获取请求的URL地址
@Override
public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
String method = request.getMethod().toString();
System.out.println("请求的方法为:"+method);
String url = request.getRequestURL().toString();
System.out.println("请求的路径为:"+url);
}
2.2 请求头
浏览器向服务器发起请求,浏览器会把相关信息通过请求头发送给服务器。
Accept:浏览器支持的文本格式;
Accept-Encoding:浏览器支持文本压缩格式;
Accept-Language:浏览器所支持的语言环境;
Cache-Control:跟浏览器缓存相关的请求头;
Connection:请求的连接方式;
Host:请求的主机名和端口号;
Request提供了获取请求头的方法:
- String getHeader(String headerName):获取指定名称的请求头
- Enumeration getHeaderNames():获取所有的请求头的名字
Enumeration是一个比较老旧的迭代器。它的功能与Iterator的功能相同。它的内部也维护了一个指针。
- hasMoreElement:判断指针是否指向元素,如果有就返回true,否则返回false。
- nextElement:获取指针指向的数据。
//获取浏览器支持的文本格式
String accept = request.getHeader("Accept");
System.out.println(accept);
//获取所有的请求头
Enumeration<String> headNames = request.getHeaderNames();
while (headNames.hasMoreElements()){
String headName=headNames.nextElement();
String headValue = request.getHeader(headName);
System.out.println(headName+":"+headValue);
}
2.3 请求正文
请求正文中存放了Post请求提交的数据。
Request对象提供了获取请求正文数据的方法:
String getParameter(String name): 获取指定名字的请求参数,name参数就是表单项的name属性值;
String[] getParameterValues(String name):获取指定名字的参数,返回一个字符串数组;
void setCharacterEncoding(String charsetName):设置请求对象中的默认字符集,保证浏览器发送数据前对数据编码所使用的的字符集与服务器接收到参数后进行解码操作所使用的的字符集一致
//设置字符集
request.setCharacterEncoding("UTF-8");
//获取请求中的参数
String name = request.getParameter("name");
System.out.println(name);
2.4 请求转发
请求转发用来实现Servlet之间的数据通信
注意:请求转发不能够与response.getWriter().write()方法一起使用。
//创建请求分发器对象
RequestDispatcher rd = request.getRequestDispatcher("User");
//调用请求分发器对象的forward方法;
rd.forward(request,response);
三、Http响应详解
Http响应就是服务器给浏览器发送数据的过程。
Http响应的主要组成:响应状态、响应头、响应正文。
3.1 响应状态
200:服务器响应成功
302:告诉浏览器重新发起请求(重定向)
304:告诉浏览器从本地缓存目录中读取资源文件
404:没有找到该资源
406:服务器返回浏览器无法解析的结果。(了解)
500:服务器发生异常
3.2 响应正文
请求正文就是服务器给浏览器发送的数据。
setCharacterEncoding(String charsetName):修改Response对象默认的字符集
3.3 响应头
Response对象提供了setHeader()方法,用于设置响应头。
3.3.1 Content-Type
告诉浏览器使用指定的字符集显示网页内容。
setContentType():resposne对象提供的方法,用于修改response对象的字符键,并且设置Content-Type响应头。
// 修改response对象的字符集,并且告诉浏览器使用utf-8显示网页的内容
reponse.setContentType("text/html;charset=utf-8");
3.3.2 Content-Encoding
告诉浏览器使用指定的压缩格式对数据进行压缩处理。
// 设置Content-Encoding响应头
response.setHeader("Content-Encoding", "gzip");
3.3.3 Content-Disposition
告诉浏览器以文件下载的方式打开资源。
// 设置Content-Disposition头
response.setHeader("Content-Disposition", "attachment;filename=" + filename);
3.3.4 Location
Location头设置重定向的地址。一般会结合302状态码一起使用。
// 设置响应状态302
response.setStatus(302);
// 设置重定向的地址
response.setHeader("Location","http://baidu.com");
3.3.4 refresh
作用:1)刷新页面;2)实现指定时间后跳转页面;
// refresh头设置每隔1s刷新页面一次
response.setHeader("refresh", "1");
// 指定多少秒后跳转其他页面
response.setHeader("refresh", "3;url=http://baidu.com");
四、ServletConfig对象
作用:获取Servlet中的配置参数。
如果要使用ServletConfig对象,需要重写Servlet的init(ServletConfig config)方法。例如:
public class UserServlet extends HttpServlet {
String uploadPath;
String imageType;
@Override
public void init(ServletConfig servletConfig) throws ServletException{
uploadPath = servletConfig.getInitParameter(" uploadPath");
imageType = servletConfig.getInitParameter("imageType");
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
System.out.println("uploadPath = " + uploadPath);
System.out.println("imageType = " + imageType);
}
}
在实际开发中,如果一些数据可能会发生变化,那么这些数据建议在配置文件中进行定义,尽量不要写死在代码中。比如:项目所使用的字符集,文件上传路径、上传文件类型等等。
五、实现不同Servlet之间的数据传递
5.1 Request对象实现Servlet之间数据传递
Request提供了用于实现Servlet之间数据传递的方法:
void setAttribute(String name, Object value):把数据存放在Request对象的name属性中;
Object getAttribute(String name):从Request对象中获取指定name属性的值;
@WebServlet("/Hello")
public class HelloServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException{
System.out.println("当前请求进入到Hello中");
//设置请求的字符集
request.setCharacterEncoding("UTF-8");
//设置请求的属性
request.setAttribute("name","四宫辉夜");
//重定向
RequestDispatcher rd = request.getRequestDispatcher("User");
rd.forward(request,response);
}
}
@WebServlet("/User")
public class UserServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//获取请求属性
String name = (String) request.getAttribute("name");
System.out.println("name:"+name);
}
}
5.2 域对象
Servlet的四大域对象:
- PageContext:在一个JSP页面中有效。
- Request:在一次请求中有效。(实现Servlet之间数据传递)
- Session:在一次会话中有效,与浏览器相关的。(存储用户相关的数据)
- ServletContext:在整个Web应用范围内有效。(存储项目相关的数据,比如项目所使用的字符集)
域对象都有的方法:
-
void setAttribute(String name, Object value):把数据存放在域对象的name属性中;
-
Object getAttribute(String name):从域对象中获取指定name属性的值;
-
void removeAttribute(String name):从域对象中删除指定属性;
5.2.1 Session对象的使用
在实际开发中,使用Session对象存储用户相关的数据。
//获取Session
HttpSession session = request.getSession();
因为Session对象的作用范围与浏览器相关。所以理论上,只要浏览器关闭,Session中的数据就会被清空。
5.2.2 ServletContext对象的使用
在实际开发中,使用ServletContext对象存储与Web项目相关的数据。
//获取ServletContext对象
ServletContext context = request.getServletContext();
当Web应用被卸载的时候,由于ServletContext对象会被卸载,所以保存在ServletContext对象中的数据也会被清空。
六、请求转发和重定向的区别
- 请求转发地址栏不会发生变化,请求重定向的地址栏会发生变化。
- 如果是请求转发,浏览器只会发起一次请求,而请求重定向浏览器会发起两次请求。
- 请求转发的地址不需要指定上下文路径,而请求重定向的地址需要指定上下文路径。
- 请求转发可以通过Request对象实现数据的传递,而请求重定向不可以通过Request对象实现数据传递。
一般情况,如果需要把数据从一个Servlet传递到另外一个Servlet中,建议使用请求转发。
七、Get和Post请求的区别
- Get请求参数显示在地址栏,而Post请求参数通过请求正文发送给服务器;
- Get请求会保存在浏览器历史记录中,而Post请求的数据默认不会保存浏览器历史记录,Get请求的安全性相对较低;
- Get请求发送数据的长度不超过2Kb,Post请求发送的数据大小没有限制;
- 浏览器默认会缓存Get请求的数据,Post请求没有缓存;
如果浏览器请求服务器静态资源,当第一次请求的时候,服务器会把资源文件发送给浏览器,浏览器接收到文件后会保存在本地缓存目录中。下一次再请求服务器的时候,浏览器就会先检查本地缓存目录是否存在该文件,如果存在就会请求服务器。
如果浏览器请求服务器动态资源,默认情况下,因此Servlet的getLastModified方法总是返回-1,所以每次都会调用doGet方法获取服务器的资源文件,浏览器不会访问本地缓存文件。所以,如果让浏览器访问本地缓存的文件,需要重写getLastModifed方法,该方法返回服务器资源文件的最后修改时间即可。
八、Servlet生命周期方法
init():Servlet被创建时候自动调用该方法,只会调用一次。
service():每次请求的时候都会调用该方法。
destroy():Servlet被销毁的时候自动调用该方法,只会调用一次。
Servlet是一个单例对象,在服务器中一个Servlet类只会被创建一次。该Servlet对象被多个用户所共享。因此,不能够把用户相关的信息保存Servlet成员属性中。否则会出现安全问题。
九、零配置(注解)
作用:@WebServlet配置Servlet。
@WebServlet注解的属性:
- value:配置url-pattern。如果只有一个value属性,可以不写value属性名。
- urlPatterns:同上,不能够与value共存。
- loadOnStartup:指定Servlet的加载顺序,值越小,越先加载。但是该属性必须要指定urlPatterns或value属性一起使用;
- initParams: 指定servlet配置参数。它是一个数组,数组元素是@WebInitParam类型。
@WebInitParam: 指定一个配置参数,它有两个属性:
- name:参数名
- value:参数值
@WebServlet(value={"/load1", "/load2"}, loadOnStartup=1, initParams={
@WebInitParam(name = "name", value = "jacky"),
@WebInitParam(name = "age", value = "20")
})
public class LoadOnStartUpServlet extends HttpServlet {
}