servlet是我们学习的第一个动态资源
1、servlet干什么用的? 处理请求,生成响应 2、我们如何创建一个servlet呢? 1>我们只需实现servlet接口即可 2>继承javax.servlet.http.HttpServlet 3>继承javax.servlet.http.HttpServlet 3、Servlet的生命周期的方法 生命周期指的是,必须要经历的过程 1、出生===>init方法,在构造方法调用之后 调用 2、使命===>service方法,当请求发来时,处理请求使用 3、销毁===>destroy方法,当服务器关闭时,会小会servlet,在销毁之前调用该方法释放资源 生命周期: 1、浏览器发送请求 2、服务器分析请求,请求哪个主机哪个项目 3、查找项目下的web.xml是否存在 比如AServlet.java 4、如果是第一次访问,创建servlet实例 5、调用servlet中的init方法,将sevlet实例存储到内存中 6、调用service方法处理请求,将request和respons传递 7、将request和response还给服务器 8、服务器将response组装成http响应协议 9、将http响应协议发送给客户端 servlet中的其他方法 getServletInfo 4.Servlet中的其他方法. getServletInfo ==> 获得servlet的信息(版本,作者,版权..),没用. getServletConfig ==> 返回servletConfig对象. 5.ServletConfig对象是什么? 封装了servlet在web.xml中的配置. 方法: 1>getServletName ==> 获得配置文件中 <servlet-name> 元素的内容 2>getInitParameter ==> 根据 <init-param>中的 <param-name> 获得 </param-value> <init-param> <param-name>name</param-name> <param-value>tom</param-value> </init-param> 3>getInitParameterNames 返回所有<param-name> . 4>getServletContext(下午讲) 6.其他实现server的方式 GenericServlet: 1.帮我们妥善的保管ServletConfig对象 2.实现了ServletConfig接口 ==> 为调用方便 注意: 不要重写servlet接口中的 init方法. 不然 第一步优化就白做了. 我们要做初始化的动作,需要去重写GenericServlet提供的空参init方法. HTTPServlet: 1.因为我们web项目基于HTTP协议,所以Service方法中传过来的request,response对象都是 基于HTTP协议的. 也就是HttpServletReueqst,也就是HttpServletResponse. 它帮我们进行了强转. 2.我们有可能在不同的请求方式时做不同的事情. 根据请求方式不同,调用不同的方法 例如 GET --> doGet() POST ==> doPost(); 7、Servlet中的其他细节 1>关于Servlet线程安全问题 因为在servlet运行期间只有一个servlet实例存在,可能会同时处理多个请求 那么我们在servlet中声明成员变量来存储用户数据是有线程安全问题的 我们应该如何解决呢? 1、实现SingleThroadModel(不推荐了) 2、使用局部变量保存用户数据(推荐使用) 2>关于servlet随着项目的启动而创建 使用<load-on-startup>配置来实现 例如: <servlet> <servlet-name>FServlet</servlet-name> <servlet-class>my.servletlearn.thread.FServlet</servlet-class> <load-on-startup>这里填写一个整数</load-on-startup> </servlet> 整数越小优先级越高,启动顺序按照配置顺序,如果优先级一样,启动顺序按照配置顺序 3>关于Servlet路径配置问题详解 <url-pattern> 路径匹配: /AServlet http://localhost:8080/MyWeb/FServlet /ABC/AServlet http://localhost:8080/MyWeb/ABC/FServlet /ABC/ABC/* http://localhost:8080/MyWeb/ABC/ABC/默认 /* http://localhost:8080/MyWeb/默认 /相当于/* 后缀名匹配: *.do==>structs 1 *.action ==>structs 2 *.html==> 注意:1、关于路径。配置的路径范围越大优先级越低 2、两种匹配模式不能混用,例如错误的例子: /*.do 4>关于tomcat目录下的web.xml 1、default servlet的配置 404 2、jsp servlet的配置 3、<session-config> <session-timeout>30</session-timeout> </session-config> 4、互联网中所有的mime类型 5、欢迎页面配置 ----------------------------------------------------------------------- 相关对象之------ServletContext 1、获得:servletConfig======>getServletContext 2、servletContext封装了web.xml中的配置 1> servletContext 封装了web.xml 中的配置 <context-param> <param-name>name</param-name> <param-value>jerry</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>1234</param-value> </context-param> getInitParameterNames(); ==> 获得所有键 getInitParameter(key); ==> 根据键获得对应的值 2>serlet技术中3大域对象之一 ServletContext对应着Application(应用)域.利用了一个项目中只有一个ServletContext实例的特点.在servletContext中放置了一个map用作数据通信. 这个Map就是所谓域. 关于域的操作,有4个. 放入键值对 setAttribute(key,value) 通过键取值 getAttribute(key) 通过键删除 removeAttribute(key) 遍历所有键 getAttributeNames() application ==> servletContext session ==> request ==> 3>获得项目中资源 3、servlet技术中对象的范围 servlet ==>项目启动期间一个servlet只有一个servlet实例 request===>项目启动期间,request对象的数量,要看当前有多少个请求正在处理 response ===>同上 servletConfig ===>一个servlet实例对应一个servletConfig对象 servletContext===>整个项目中,永远只有一个servletContext实例存在 servlet ==> server applet ==> 服务器端的小程序 1.作用是用来处理请求(request),完成响应(response)的. 2.如何创建一个servlet *实现servlet接口 *继承GenericServlet *继承HttpServlet 3.servlet接口中的方法 *init (ServletConfig ) *service (ServletRequest , servletResponse ) *destory () //======= *getServletConfig *getServletInfo 4.ServletConfig 的 作用. *getServletName *getInitParameter() *getInitParameterNames() *getServletContext() 5.servlet线程是不安全的. 因为在服务器中,一个servlet只存在一个实例.所以当有多个请求同时访问的时候,如果使用成员变量接受线程参数,就会有问题. 解决办法: 使用局部变量接受线程参数. 6.url-pattern 路径匹配: "/"开头 例如: /AServlet 后缀名匹配: "*"开头 例如: *.do 注意: 1.匹配范围越广优先级越低 2.两种匹配方式不能同时使用. 7.load on startup 该配置可以让servlet在服务器启动时加载. 填入的数字表示优先级.数字越小,优先级越高. 优先级一样,按配置顺序加载. 8.servletContext 范围: 一个项目对应一个servletContext. 获取: 通过servletConfig获取 作用: 1.获得配置文件(web.xml根下的)中的参数 *getInitParameter() *getInitParameterNames() 2.域的功能 => application 增加一个:setAttribute 删除一个:removeAttribute 获得一个: getAttribute 获得所有键: getAttributeNames 3.获得项目内资源 getResourceAsStream getRealPath *以上两个方法都是填写相对路径. "/" ==> 项目的根下(WebRoot) package my.servletlearn.context.resource; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class KServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub /*// 获得资源的其他方式 // 使用class方法 // "/" ===>代表classes目录 InputStream is2=this.getClass().getResourceAsStream("Student.xml"); // "" ===> 不加 "/",代表当前文件所在目录 InputStream is3=this.getClass().getResourceAsStream("student/xml"); System.out.println(is2); System.out.println(is3);*/ //--------------------------------------------------------------------------- InputStream is4=this.getClass().getClassLoader().getResourceAsStream(""); // 区别就是不加"/" 还是相对于classes目录 InputStream is5=this.getClass().getClassLoader().getResourceAsStream("/"); System.out.println(is4); System.out.println(is5); // 获得路径 String path=this.getClass().getResource("student.xml").getPath(); System.out.println(path+"path"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } } package my.servletlearn.context; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sun.xml.internal.ws.api.policy.PolicyResolver.ServerContext; public class GServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub // 获得全局init param设置 // 1、获得ServletContext ServletContext sContext= getServletContext(); // 调用getXXX方法 Enumeration<String> enumeration=sContext.getInitParameterNames(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); String value=sContext.getInitParameter(key); resp.getWriter().print(key+"===>"+value+"<br/>"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } } package my.servletlearn.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 HServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub Constant.str="Hello"; // 向静态变量赋值 // resp.getWriter().print(Constant.str); // 向女神送包 Constant.obj="Lv"; // resp.getWriter().print(Constant.obj); Constant.map.put("bag", "Lv"); Constant.map.put("car", "QQ"); Constant.map.put("phone", "ventu"); // 使用ServletContext完成通信 // 1、获得ServletContext对象 ServletContext sc=getServletContext(); // 操作map sc.setAttribute("ck", "calkin"); sc.setAttribute("eat", "jinqiangyu"); sc.setAttribute("car", "BMW"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } } package my.servletlearn.context; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sun.xml.internal.ws.api.policy.PolicyResolver.ServerContext; public class IServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub // 取值 String str=Constant.str; // Object bao=Constant.obj; String bao=(String) Constant.map.get("bag"); // 输出到客户端 resp.getWriter().print(str+"<br>"); resp.getWriter().print(bao+"<br>"); Constant.map.remove("car"); // 通过servletContext取值 // 获得servletContext对象 ServletContext sContext=getServletContext(); // 操作map String bag=(String) sContext.getAttribute("ck"); // 输出到客户端 resp.getWriter().print(bag); // 不喜欢就扔掉(删除) sContext.removeAttribute("ck"); //遍历 Enumeration<String> enumeration=sContext.getAttributeNames(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); Object value=sContext.getAttribute(key); System.out.println(key+"====>"+value); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } } package my.servletlearn.context.resource; import java.io.File; import java.io.IOException; import java.io.InputStream; 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 JServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub // 获得WEB-InF下的student.xml File file=new File("D:\\java\\workspace\\MyWeb\\WebContent\\WEB-INF\\student.xml"); // 以上获得student.xml的代码不正确 // 不正确,因为这样获得的tudent.xml指的是Eclipse工程下的文件,而我们真正要操作的是部署到tomcat下的资源 File file2=new File("student.xml"); System.out.println(file2.exists()); // 结论:file的相对路径行不通 // 解决方案:使用servletContext ServletContext sc=getServletContext(); // "/" ===>代表项目下 InputStream iStream=sc.getResourceAsStream("/WEB-INF/student.xml"); System.out.println(iStream); // 获得资源的绝对路径 String realPath=sc.getRealPath("/WEB-INF/student.xml"); System.out.println(realPath); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } } package my.servletlearn.context.resource; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class KServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub /*// 获得资源的其他方式 // 使用class方法 // "/" ===>代表classes目录 InputStream is2=this.getClass().getResourceAsStream("Student.xml"); // "" ===> 不加 "/",代表当前文件所在目录 InputStream is3=this.getClass().getResourceAsStream("student/xml"); System.out.println(is2); System.out.println(is3);*/ //--------------------------------------------------------------------------- InputStream is4=this.getClass().getClassLoader().getResourceAsStream(""); // 区别就是不加"/" 还是相对于classes目录 InputStream is5=this.getClass().getClassLoader().getResourceAsStream("/"); System.out.println(is4); System.out.println(is5); // 获得路径 String path=this.getClass().getResource("student.xml").getPath(); System.out.println(path+"path"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } } package my.servletlearn.demo; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class AServlet implements Servlet { @Override public void init(ServletConfig arg0) throws ServletException { // TODO Auto-generated method stub // init 是在第一次请求Aservlet时调用 ===>Servlet实例的创建是在第一次访问的时候 // servlet在多次访问时,发现只调用了1次init方法,在多次访问,只创建了一个实例 System.out.println("ASerlet的init方法被调用!"); } // 当客户端请求的时候调用service,参数1 request对象封装了请求信息,参数2 response 中填入信息生成的响应 @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { // TODO Auto-generated method stub arg1.getWriter().print("hello world!"); System.out.println("ASerlet的service方法被调用le!"); } @Override // 在服务器将要关闭时,会小会内存中的servlet实例,在真正小会之前会调用destroy方法 public void destroy() { // TODO Auto-generated method stub System.out.println("ASerlet方法被调用了!"); } @Override public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } @Override // 这个方法没有用 public String getServletInfo() { // TODO Auto-generated method stub return null; } } package my.servletlearn.generic; import java.io.IOException; import java.util.Enumeration; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public abstract class MyGenericServlet implements Servlet,ServletConfig{ private ServletConfig config; @Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub this.config=config; } @Override //不要忘记抽象方法不需要被实现 public abstract void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException; @Override public void destroy() { // TODO Auto-generated method stub } @Override public ServletConfig getServletConfig() { // TODO Auto-generated method stub return config; } @Override public String getServletInfo() { // TODO Auto-generated method stub return null; } public String getInitParameter(String arg0) { return config.getInitParameter(arg0); } public Enumeration<String> getInitParameterNames() { return getServletConfig().getInitParameterNames(); } public ServletContext getServletContext() { return getServletConfig().getServletContext(); } public String getServletName() { return getServletConfig().getServletName(); } /*public String getServletName() { return getServletConfig().getServletName(); } public String getInitParameter(String args0) { return getServletConfig().getInitParameter(args0); } public Enumeration getInitParameterNames() { return getServletConfig().getInitParameterNames(); } public ServletContext getServletContext() { return getServletConfig().getServletContext(); }*/ } package my.servletlearn.generic; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class CServlet extends MyGenericServlet{ @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { // TODO Auto-generated method stub // String servletName=getServletConfig().getServletName(); String servletName=getServletName(); // String param=getInitParameter("name"); arg1.getWriter().print(servletName); } // 重新init方法 public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub System.out.println("C"); super.init(config); } } package my.servletlearn.http; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import my.servletlearn.generic.MyGenericServlet; public abstract class MyHttpServlet extends MyGenericServlet{ public static final String Method_Get="GET"; public static final String Method_Post="POST"; @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub // 优化:我们开发项目都是基于http协议的,而且服务器在service方法中传给ServletRequest // 所以我们把request和response强转成HTTP的 HttpServletRequest request=null; HttpServletResponse response=null; try { request=(HttpServletRequest) req; response=(HttpServletResponse) res; service(request, response); } catch (Exception e) { // TODO: handle exception } } public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // 优化2:我想根据请求方式的不同,做不同的事情 // 获得客户端的请求方式 String method=req.getMethod();// Get/Post // 根据请求方式的不同,调用不同的方法 if (method.equals(Method_Get)) { doGet(res,req); }else if(method.equals(Method_Post)){ doPost(res,req); } } public void doPost(HttpServletResponse res, HttpServletRequest req) { // TODO Auto-generated method stub } public void doGet(HttpServletResponse res, HttpServletRequest req) { // TODO Auto-generated method stub } } package my.servletlearn.http; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DServlet extends MyHttpServlet{ @Override public void doPost(HttpServletResponse res, HttpServletRequest req) { // TODO Auto-generated method stub System.out.println("您现在使用的是POST访问方式"); } @Override public void doGet(HttpServletResponse res, HttpServletRequest req) { // TODO Auto-generated method stub System.out.println("您现在使用的是GET访问方式"); } } package my.servletlearn.thread; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class FServlet extends HttpServlet { private String name; private int i=0; public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub System.out.println("F "); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub // name=req.getParameter("name"); i++; try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } resp.getWriter().print("The number is:"+i); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } } package my.servletlearn2.demo; import java.io.IOException; import java.util.Enumeration; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class BServlet implements Servlet{ private ServletConfig config; @Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub this.config=config; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub // 获得servlet的name String servletName=getServletConfig().getServletName(); // 将字符串输出到客户端(浏览器) res.getWriter().print(servletName+"<br>"); /** * String getInitParameter(String name) * Enumeration getInitParameterNames() * webxml配置里面的init-param的信息 */ Enumeration<String> enumeration=getServletConfig().getInitParameterNames(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); String value=getServletConfig().getInitParameter(key); res.getWriter().print(key+"===>"+value+"<br>"); } } @Override public void destroy() { // TODO Auto-generated method stub } @Override public ServletConfig getServletConfig() { // TODO Auto-generated method stub return config; } @Override public String getServletInfo() { // TODO Auto-generated method stub return null; } }