一、servlet
1、servlet的运行过程
- servlet调用图...
- 覆写init() destroy()
访问http://localhost:8080/day05/xxx,对象创建;package cn.itcast; import javax.servlet.GenericServlet; import javax.servlet.ServletResponse; import javax.servlet.ServletRequest; import javax.servlet.ServletException; import java.io.OutputStream; import javax.servlet.ServletConfig; public class FirstServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException { String data = "Hello servlet!"; OutputStream out = res.getOutputStream(); out.write(data.getBytes()); } public void init(ServletConfig config) throws ServletException { System.out.println("对象创建"); } public void destroy() { System.out.println("对象被销毁"); } }
移除web应用day05或者关闭web服务器(tomcat),对象被销毁。
2、用eclipse开发servlet
3、servlet接口实现类
- GenericServlet、HttpServlet。
- HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
4、servlet的一些细节(web.xml)
-
在 Servlet 映射到的 URL 中也可以使用*通配符,但是只能有 两种固定的格式 :一种格式是“* . 扩展名”,另一种格式是以正斜杠( / )开头并以“ /*” 结尾。
/开头的优先级高些。
在学到框架的时候,会用到这些通配 符。 -
如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。(而不是在servlet第一次访问才创建)。
如果你想让框架在服务器启动的时候就启动起来,就可以把这个框架写到init()里面去。 -
如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。
凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。
在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。
在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。
5、servlet的一些细节(线程安全)
-
servletDemo4.java int i = 1; i++;(并发访问这个servlet,存在线程安全问题)
package cn.itcast; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/ServletDemo4") public class ServletDemo4 extends HttpServlet { int i = 1; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { i++; try { Thread.sleep(1000 * 5); } catch (InterruptedException e) { e.printStackTrace(); } //response.getOutputStream().write(i); //为什么这句话无法显示int型变量i呢? response.getWriter().write(i + ""); //为什么后面要加上"",浏览器才会显示i的值呢? } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
-
synchronized。但是在互联网上不能这样做,因为这样就变成单线程的了,比如每天有成千上万的人访问新浪,如果有一个人在访问了,其它人就访问不了了。我们要知道的是servlet是线程不安全的。
package cn.itcast; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/ServletDemo4") public class ServletDemo4 extends HttpServlet { int i = 1; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { synchronized (this) { i++; try { Thread.sleep(1000 * 5); } catch (InterruptedException e) { e.printStackTrace(); } //response.getOutputStream().write(i); //为什么这句话无法显示int型变量i呢? response.getWriter().write(i + ""); //为什么后面要加上"",浏览器才会显示i的值呢? } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
-
SingleThreadModel接口(Deprecated过时的):
如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。 -
子类不能抛比父类更多的异常。
二、ServletConfig对象
1、初始化参数
-
init-param初始化参数(封装到servletconfig中,这是服务器自己做的);覆盖init方法。
web.xml:
ConfigServletDemo1.java:<servlet> <servlet-name>/ConfigServletDemo1</servlet-name> <servlet-class>cn.itcast.servletConfig.ConfigServletDemo1</servlet-class> <init-param> <param-name>xx</param-name> <param-value>yyyy</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>/ConfigServletDemo1</servlet-name> <url-pattern>/servletConfig/ConfigServletDemo1</url-pattern> </servlet-mapping>
在控制台得到xx的value:yyyy。@Override public void init(ServletConfig config) throws ServletException { String value = config.getInitParameter("xx"); System.out.println(value); }
-
在浏览器中得到xx的value,ConfigServletDemo1.java:
package cn.itcast.servletConfig; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ConfigServletDemo1 extends HttpServlet { private ServletConfig config; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String value = config.getInitParameter("xx"); response.getOutputStream().write(value.getBytes()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override public void init(ServletConfig config) throws ServletException { this.config = config; } }
- getInitParameterNames() 获取所有的初始化参数。迭代:
web.xml:
ConfigServletDemo1.java:<servlet> <servlet-name>/ConfigServletDemo1</servlet-name> <servlet-class>cn.itcast.servletConfig.ConfigServletDemo1</servlet-class> <init-param> <param-name>xx</param-name> <param-value>yyyy</param-value> </init-param> <init-param> <param-name>mm</param-name> <param-value>nnnn</param-value> </init-param> <init-param> <param-name>pp</param-name> <param-value>qqqq</param-value> </init-param> </servlet>
package cn.itcast.servletConfig; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ConfigServletDemo1 extends HttpServlet { private ServletConfig config; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Enumeration e = config.getInitParameterNames(); while(e.hasMoreElements()) { String name = (String) e.nextElement(); String value = config.getInitParameter(name); response.getOutputStream().write((name + "-" + value + "<br/>").getBytes()); //怎么在浏览器中换行? } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override public void init(ServletConfig config) throws ServletException { this.config = config; } }
2、应用:
- 获得字符集编码:
web.xml:
.java:doGet方法里面:<init-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </init-param>
String charset = config.getInitParameter("charset"); //从配置文件获取这个值。
-
获得数据库连接信息:
web.xml:
.java:doGet方法里面:<init-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </init-param> <init-param> <param-name>username</param-name> <param-value>root</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>root</param-value> </init-param>
String url = this.config.getInitParameter("url"); String username = this.config.getInitParameter("username"); String password = this.config.getInitParameter("password");
- 获得配置文件:查看struts案例的web.xml文件...
- 在实际开发中,不用写init方法,可以这么写:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletConfig config = this.getServletConfig(); System.out.println(config.getInitParameter("xx")); }
三、ServletContext对象
1、ServletContext
- 这个对象代表的是一个web应用。
- 多个servlet之间可以通过其共享数据。
2、应用
- 多个Servlet通过ServletContext对象实现数据共享:
ServletContext1.java:
ServletContext2.java:package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletContext1 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "abcdefg"; ServletContext context = this.getServletConfig().getServletContext(); context.setAttribute("data", data); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
web.xml:package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletContext2 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = this.getServletContext(); String data = (String) context.getAttribute("data"); response.getOutputStream().write(data.getBytes()); System.out.print(data); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
先访问 http://localhost:8080/fanglixun_day05/context/ServletContext1<servlet> <servlet-name>ServletContext1</servlet-name> <servlet-class>cn.itcast.context.ServletContext1</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletContext1</servlet-name> <url-pattern>/context/ServletContext1</url-pattern> </servlet-mapping> <servlet> <servlet-name>ServletContext2</servlet-name> <servlet-class>cn.itcast.context.ServletContext2</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletContext2</servlet-name> <url-pattern>/context/ServletContext2</url-pattern> </servlet-mapping>
再访问 http://localhost:8080/fanglixun_day05/context/ServletContext2
就可以显示data的内容abcdefg了。 - 获取WEB应用的初始化参数:
web.xml:(获取整个web站点的初始化参数)
ServletContext3.java:<context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </context-param>
访问http://localhost:8080/fanglixun_day05/context/ServletContext3,会显示url的value。package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletContext3 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = this.getServletContext(); String url = context.getInitParameter("url"); response.getOutputStream().write(url.getBytes()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
- 实现Servlet的转发:
ServletContext4和ServletContext5是用的同一个request和response。
ServletContext4.java:
ServletContext5.java:protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = this.getServletContext(); RequestDispatcher rd = context.getRequestDispatcher("/context/ServletContext5"); rd.forward(request, response); }
访问http://localhost:8080/fanglixun_day05/context/ServletContext4,protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getOutputStream().write("ServletContext5".getBytes()); }
显示ServletContext5。