Servlet原理及用法解析
1.Servlet原理
不管servlet和http怎么交互,实际上我们要知道sevlet只是java中的一个接口,和普通的java接口没什么区别,他只是规定了处理http请求和响应的规范。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类
1.1 Servlet处理浏览器请求过程
完整过程包括以下三个步骤
- 客户端发送请求至服务器
- 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
- 服务器将响应返回客户端
1.2 tomcat和servlet关系
Tomcat 是Web应用服务器,是一个Servlet/JSP容器. Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户。
-
Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到。
-
Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器
1.3 详解创建servlet的原理
1.3.1 servlet的生命周期是什么?
-
init( ),当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化(web.xml中配置load-on-startup=1,默认为0)。
-
service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。
-
destory,当要销毁Servlet时,Servlet容器就会调用这个方法.在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。
1.3.2 为什么GenericServlet类中init方法有两个,一个是带有参数ServletConfig的,一个有无参的方法?
当我们需要在init方法中做一点别的事情时,通常需要继承GenericServlet并且重写了init(ServletConfig config)方法。但这样会就破坏了原本在GenericServlet类中init(ServletConfig config)写的代码,也就是在GenericServlet类中的成员变量config会一直是null,无法得到赋值,要想赋值,就必须在重写的init(ServletConfig config)方法中调用父类的init(ServletConfig config)方法,也就是super.init(ServletConfig config),非常不方便。
设计者怕程序员会忘了写这句代码,所以在GenericServlet类中增加一个init()方法,以后需要在init方法中需要初始化别的数据,只需要重写init()这个方法,而不需要去覆盖init(ServletConfig config)这个方法。
1.3.3 四个重点对象:ServletConfig、ServletContext,request、response
-
ServletConfig对象
包括四个内容
getServletName(); //获取servlet的名称,也就是我们在web.xml中配置的servlet-name
getServletContext(); //获取ServletContext对象,该对象的作用看下面讲解
getInitParameter(String); //获取在servlet中初始化参数的值。这里注意与全局初始化参数的区分。这个获取的只是在该servlet下的初始化参数
getInitParameterNames(); //获取在Servlet中所有初始化参数的名字,也就是key值,可以通过key值,来找到各个初始化参数的value值。注意返回的是枚举类型 -
ServletContext对象
web项目中共享数据,getAttribute(String name)、setAttribute(String name, Object obj)、removeAttribute(String name)
setAttribute(String name, Object obj) 在web项目范围内存放内容,以便让在web项目中所有的servlet读能访问到 getAttribute(String name) 通过指定名称获得内容 removeAttribute(String name) 通过指定名称移除内容
整个web项目初始化参数
getInitPatameter(String name) //通过指定名称获取初始化值 getInitParameterNames() //获得枚举类型
获取web项目资源
获取web项目下指定资源的路径:getServletContext().getRealPath("/WEB-INF/web.xml") 获取web项目下指定资源的内容,返回的是字节输入流。InputStream getResourceAsStream(java.lang.String path)
getResourcePaths(java.lang.String path) (指定路径下的所有内容)
-
request对象
请求行内容的获取请求头的获取
请求体的获取 – 请求参数的获取
get请求参数:http://localhost:8080/test01/MyServlet?username=jack&password=1234 post请求参数: <form method="post"><input type="text" name="username">
String request.getParameter(String) 获得指定名称,一个请求参数值。
String[] request.getParameterValues(String) 获得指定名称,所有请求参数值。例如:checkbox、select等
Map<String , String[]> request.getParameterMap() 获得所有的请求参数
-
请求转发
request.getRequestDispatcher(String path).forward(request,response); //path:转发后跳转的页面,这里不管用不用"/"开头,都是以web项目根开始,因为这是请求转发,请求转发只局限与在同一个web项目下使用,所以这里一直都是从web项目根下开始的。 -
response对象
response.setHeader(java.lang.String name, java.lang.String value) 设置指定的头。
例如:设置每隔3秒就自动刷新一次 response.setHeader("Refresh",3);
重定向(页面跳转)
方式一:手动方案
response.setStatus(302); //状态码302就代表重定向
response.setHeader(“location”,“http://www.baidu.com”);
方式二:使用封装好的,通过response.sendRedirect(“http://www.baidu.com”);
注意:response.sendRedirect(path);
第一种:
response.sendRedirect("/test01/MyServlet01"); //使用了"/"开头,说明是从web站点根开始,所以需要写test01/MyServlet01
第二种:
response.sendRedirect(“MyServlet01”); //没有使用"/"开头,说明是从web项目根开始,那么就无需写test01了。
用法解析(实例)
HTTP部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/form" method="get">
<span>用户名</span><input type="text" name="username"><br>
<span>密码</span><input type="password" name="password"><br>
<input type="submit" name="submit">
</form>
</body>
</html>
Servlet部分
public class FormServlet extends HttpServlet {
private static final long serialVersionUID = -4186928407001085733L;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应的编码格式为UTF-8编码,否则发生中文乱码现象
response.setContentType("text/html;charset=UTF-8");
//1.获得请求方式
String method = request.getMethod();
//2.获得请求的资源相关的内容
String requestURI = request.getRequestURI();//获得请求URI
StringBuffer requestURL = request.getRequestURL();
String webName = request.getContextPath();//获得应用路径(应用名称)
String querryString = request.getQueryString();//获得查询字符串
response.getWriter().write("<h1>下面是获得的字符串</h1>");
response.getWriter().write("<h1>method(HTTP方法):<h1>");
response.getWriter().write("<h1>"+method+"</h1><br>");
response.getWriter().write("<h1>requestURi(请求URI):</h1>");
response.getWriter().write("<h1>" + requestURI + "</h1><br>");
response.getWriter().write("<h1>webname(应用名称):</h1>");
response.getWriter().write("<h1>" + webName + "</h1><br>");
response.getWriter().write("<h1>querrystring(查询字符串):</h1>");
response.getWriter().write("<h1>" + querryString + "</h1>");
}
}
XML部分
</servlet-mapping>
<servlet>
<servlet-name>FormServlet</servlet-name>
<servlet-class>com.javaee.util.FormServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FormServlet</servlet-name>
<url-pattern>/form</url-pattern>
</servlet-mapping>