一、Servlet概述:
servlet是由sun公司提供的一门用于开发动态web资源的技术。sun公司在其API中提供了一个servlet接口,用户若想发一个web资源(即就是开发一个java程序向浏览器输出数据),需要完成以下的两个步骤:
1、编写一个java类,实现servlet接口。
2、把开发好的java类部署到web服务器中。按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为servlet。
Servlet是一种基于java技术的web组件,是一种基于java的且与第三方平台无关的类。通常,它可以被web服务器编译、加载和运行,最后生成动态的资源内容。
二、编写第一个Servlet:
1、编写java类,继承HttpServlet类
2、重新构建doGet方法和doPost方法
3、在web.xml文件中进行配置
4、servlet程序交给tomcat服务器运行
三、HttpServeltRequest获取请求行和请求头:
获取请求行相关信息的相关方法:
1.getMethod()方法:返回请求方法,请求方法通常是GET或POST,也有可能是HEAD、 PUT或DELETE
2.getRequestURI()方法:返回URI
3.getRemoteAddr()方法:获取请求客户端的IP地址
4.getRemoteport()方法:获取请求客户端的端口号
5.getLocalAddr():获取服务器当前接收的IP地址
6.getContextPath():用于获取URL中属于web应用程序的路径
7.getProtocol():用于获取请求行中的协议名和版本
//获取请求行 System.out.println("接收到get请求"); System.out.println("请求方式:"+request.getMethod()); System.out.println("URI:"+request.getRequestURI()); System.out.println("发出请求客户端IP地址:"+request.getRemoteAddr()); System.out.println("服务点接收请求的IP地址:"+request.getLocalAddr()); System.out.println("访问客户端的端口号:"+request.getRemotePort()); System.out.println("web应用路径:"+request.getContextPath()); System.out.println("http协议和版本:"+request.getProtocol());
四、获取请求头的相关方法:
1.getHeader(String name):该方法返回一个 Enumeration 集合对象,该集合对象由请求消息中出现的某个指定名称的所有头字段值组成。在多数情况下,一个头字段名在请求消息中只出现一次,但有时可能会出现多次
2.getIntHeader(String name):该方法用于获取指定名称的头字段,并且将其值转为 int 类型。需要注意的是,如果指定名称的头字段不存在,则返回值为 -1;如果获取到的头字段的值不能转为 int 类型,则将发生 NumberFormatException 异常
3.getDateHeaders(String name):该方法用于获取指定头字段的值,并将其按 GMT 时间格式转换为一个代表日期/时间的长整数,该长整数是自 1970 年 1 月 1 日 0 时 0 分 0 秒算起的以毫秒为单位的时间值
4.getHeaderNames():获取所有包含请求头字段Enumberation
5.getCharacterEncoding():该方法用于返回请求消息的实体部分的字符集编码,通常是从 Content-Type 头字段中进行提取,结果为 String 类型
//获取请求头 Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()){ String element = headerNames.nextElement(); System.out.println(element+":"+request.getHeader(element)); }
五、获取请求参数:
1.getParameter(String name):该方法用于获取某个指定名称的参数值,如果请求消息中没有包含指定名称的参数,getParameter()方法返回null;如果指定名称的参数存在但没有设置值,则返回一个空串;如果请求消息中包含有多个该指定名称的参数,getParameter()方法返回第一个出现的参数值
2.getParameterNames():该方法用于返回一个包含请求消息中所有参数名的Enumeration对象,在此基础上,可以对请求消息中的所有参数进行遍历处理
3.getParameterMap():个体Parameter Map()方法用于将请求消息中的所有参数名和值装入进一个Map对象中返回
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("用户名:" + username); System.out.println("密码:" + password);
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> </body> <center> <h2>发起HTTP get请求</h2> <form action="hi" method="get"> <p>账号: <input type="text" name="name" /></p> <p>密码: <input type="text" name="passWord" /></p> <input type="submit" value="提交" /> </form> </center> </html>
六、Response对象发送响应行和响应头和响应消息体:
发送响应行:
1.setStatus(int status):当Servlet向客户端回送响应消息时,需要设置一个状态码,该方法用于设置HTTP响应消息的状态码,并生成响应状态行,由于响应状态行中的描述直接和状态码相关,因此只需要设置该方法,就可以发送一个响应行,正常情况下,web服务器会默认发送一个200的状态码
2.sendError(int code):该方法用于发送表示错误信息的状态码,例如404找不到访问资源,还有一种重载形式sendError(int code,String errorMessage),errorMessage可以以文本形式显示在客户端浏览器
发送响应头:
1.addHeader(String name,String value):用于设置HTTP协议的响应头字段,其中Name时响应头字段,Value是响应字段的值
2.setHeader(String name,String value):同上,唯一区别在于可以重复添加同名的响应头字段,会覆盖之前添加的同名的响应头
3.setContentLength():设置HTTP响应消息的内容大小,单位是字节
4.setContentType()L设置Servlet输出内容的类型
5.setCharacterEncoding(String charset)
发送响应消息体:
1.getOutputStream()方法:获取字节流输出对象为ServletOutputStream类型,
2.getWrite()方法:获得的字符输出流对象是PrintWriter类型由于它可以直接输出文本类型,因此需要输出网页文档,需要使用这个方法
String result="恭喜您登录成功"; ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(result.getBytes()); response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.write(result); request.setAttribute("name","123"); request.getRequestDispatcher("/index.jsp").forward(request,response);
七、Servlet的生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
init(ServletConfig)方法:init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
service() 方法:是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
destory()方法:只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。
HttpServlet方法接口:javax.servlet.http:
继承自Servlet接口,并重新实现了service方法,根据不同请求方式调用不同的处理方法。
service(HttpServletRequest,HttpServletResponse)方法,获取请求方式,分别调用deGet(),或者doPost()方法
当服务器关闭或者项目被移出服务器,destory方法会执行,生命周期结束
架构图:
代码块:
package net.zixue.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name = "LifeServlet",urlPatterns = "/life") public class LifeServlet extends HttpServlet { @Override public void init() throws ServletException { System.out.println("init 被执行了"); super.init(); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("service 被执行了"); super.service(req, resp); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("do get被执行了"); } @Override public void destroy() { System.out.println("destroy被执行了"); super.destroy(); } }
八、ServletConfig对象
ServletConfig对象是它所对应的Servlet对象的相关配置信息
特点:
每一个servlet对象都有一个ServletConfig对象和它相对应
ServletConfig对象在多个Servlet对象之间是不能共享的
常见的ServletConfig对象的方法:
1、getInitParameter(String name):获取指定参数名的初始化参数
2、getInitParameterNames():返回servlet初始化参数的所有名称
3、getServletContext():返回一个Servlet的上下文对象
4、getServletName():获取Servlet的name配置值
web.xml页面展示
<servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.cn.test</servlet-class> <!--配置Servlet的初始化参数信息,并且该节点必须在load-on-startup节点之前--> <init-param> <!--初始化参数名--> <param-name>user</param-name> <!--初始化参数值--> <param-value>root</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>123456</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
九、ServletContext-获取项目初始值
ServletContext定义
即Servlet上下文环境,该对象表示当前web应用环境信息
获取ServletContext对象
1、通过ServletConfig的getServletContext()方法可以得到ServletContext对象
2、HttpServelt中直接通过this.getServletConext()获取
域对象
域对象就是在不同资源之前来共享数据,保存数据,获取数据,ServletContext对象通常称为Context域对象。ServletContext是我们学习的第一个域对象
使用SevletContext获取整个项目web初始化参数
<context-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </context-param>
●String getIni tParameter (String name) ;根据名称获取初始化参数
●Enumeration get Ini tParameterNames O) ;获取所有初始化的参数名称
2.使用ServletContext在多个Servlet中共享数据
●void setAttribute(String name, Object object) ;存放数据
●Object getAttribute(String name) ;获取数据
package zyt.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name = "ServletTest3",urlPatterns = "/test3") public class ServletTest3 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String encoding=this.getServletContext().getInitParameter("encoding"); System.out.println("encoding="+encoding); } }
十、ServletContext对象——在多个sevlet之间共享数据
Enumeration getAtributeNames():返迥-个Enumeration对象,该对象包含了所有存放在ServletContext中的所有域属性名
Object getAttibute(String name):根据参数指定的属性名返回一一个与之匹配的域属性值
void removeAttribute(String name):根据指定的域属性名,从ServletContex中删除匹配的域属性
void stAtribute(String name,Object obj):设置ServletContext的域属性,其中name是域属性名,obj是域属性值
public class TestServlet04 extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context=this.getServletContext(); //通过setAttribute()方法设置属性值 context.setAttribute("data", "this servlet save data"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub this.doGet(request, response); } //浏览器测试网址 http://localhost:8080/chapter03/TestServlet04 }
十一、ServletContext——读取项目的资源文件
package net.zixue.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.Properties; @WebServlet(name = "ServletTest4",urlPatterns = "/test4") public class ServletTest4 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/db.properties");//读取文件的路径,返回文件流 Properties properties = new Properties(); properties.load(resourceAsStream); String name = properties.getProperty("name"); String pass = properties.getProperty("passWord"); String url = properties.getProperty("url"); System.out.println(url); System.out.println(pass); System.out.println(name); } }
十二、请求转发
在Servlet中请求转发是大量要使用的,因为当我们访问一一个Servlet的时候通常会执行一些后台的业务逻辑,然后跳转到一个结果页面,那么跳转到结果页面的这个过程就是请求转发,举个例子我们做登录的功能,我们填写用户名密码然后提交到一个负责登录的Servlet, Servlet 为我们做用户名和密码的校验,如果我们都正确的话,我们就要跳转到登录的提示页面,如果错误就要跳转到登录失败的页面。Request的请求转发也可以叫做服务器端的跳转,虽然有页面的跳转但是我们会发现地址栏是不会有变化的。
请求转发的相关方法:
RequestDispatcher对象,可以通过request.getRequestDisptcher()方法获取调用这个对象的forward方法就可以实现请求转发
转发过程中携带数据:
request本身也是一个域对象,request可以携带数据传递给其他web资源
setAttribute方法:
getAttriubute 方法:
removeAttribute方法:
getAttributeNames方法:
重定向:
重定向是根据服务器返回的状态码来实现的。客户端浏览器在请求服务器的时候,服务端会返回一个状态码,服务器通过HttpServletResponse的setStatus(int status)方法来设置状态码。如果服务器这个时候返回的状态码是301或者是302,则浏览器就会到新的网址重新请求该资源。服务的响应中会带着这个新资源的地址。
请求转发和重定向的区别:
1.可以理解为是客户端行为,客户端发起一次请求,服务器端给出一次响应,但这个响应包含下一次客户端需要访问的服务器端处理程序的地址,客户端再次发起请求,将会得到处理结果,也就意味...
2.使用当前后两个页面有数据传递时,例如查询了数据需要在页面显示时,用请求转发 当没有数据传递,例如做了更新操作跳转到其他页面,就用重定向。
十三、网页自动刷新
在遇到页面乱码问题时的解决办法:
在方法体内插入这段话即可解决乱码问题
response.setContentType("text/html;charset=utf-8");
package net.zixue.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name = "RefreshServlet",urlPatterns = "/refresh") public class RefreshServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String message="<meta http-equiv='refresh' content='3;url=/hello/home.html'>3秒后会自动跳回首页</meta>"; request.setAttribute("message",message); request.getRequestDispatcher("/index.jsp").forward(request,response); } private void RefreshDemol(HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=utf-8"); response.setHeader("refresh","3;url='/hello/home.html"); response.getWriter().print("3秒钟自动刷新"); } }
十四、Servlet线程安全
当多个客户端并发访问一个Servlet时,web服务器会为每一个客户端的访问创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内部如果访问了同一个资源的话,就可能引发线程安全问题
package net.zixue.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet(name = "ThreadServlet",urlPatterns = "/thread") public class ThreadServlet extends HttpServlet { int i=0; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { synchronized (this) { i++;//第一次访问i已经是1,第二次访问i=2 try{ Thread.sleep(5*1000); }catch(InterruptedException e) { e.printStackTrace(); } response.setContentType("text/html;charset=utf-8"); response.getWriter().write(i+""); } } }