15、Servlet
servlet 是运行在 Web 服务器中的小型 Java 程序 ( 服务器端的小应用程序 ) 。servlet 通常通过 HTTP(超文本传输协议) 接收和响应来自 Web 客户端的请求
三大作用:
1、获取表单数据
2、处理业务逻辑
3、分发转向
注意:
修改了类名之后要在web.xml中修改一下servlet-name标签中的完整类名
<url-pattern >/ servlet/demo4 </ url-pattern>:第一个/代表当前应用根目录
每次修改完之后要重新运行服务器或者redeploy
在Windows下复制的目录为反斜杠\,正反都支持,但是\需要转义,故一般使用正斜杠/
一、编写一个servlet程序
(1)写一个java类,实现servlet接口
1 public class ServletTest implements Servlet{ 2 // 接收用户请求并作出相应 3 public void service(ServletRequest req, ServletResponse res) 4 throws ServletException, IOException { 5 // TODO Auto-generated method stub 6 res.getWriter().write("hello"); 7 } 8 }
(2)修改web.xml文件,给servlet提供一个可访问的URI地址
1 <!-- 创建一个servlet实例 --> 2 <servlet> 3 <servlet-name>servletDemo</servlet-name> 4 <servlet-class>cn.guojie.servlet.ServletTest</servlet-class> 5 </servlet> 6 7 <!-- 给servlet提供(映射)一个可访问的URI地址 --> 8 <servlet-mapping> 9 <servlet-name>servletDemo</servlet-name> 10 <url-pattern>/demo1</url-pattern> 11 </servlet-mapping>
servletDemo:servlet的名字,自定义,和mapping中要相同
url-pattern:/demo1代表测试的时候用的
(3)部署应用到tomcat服务器
(4)测试:http://locahost:8080/servlet/demo1 --> servlet-mapping标签中的/demo1,通过servlet名servletDemo --> servlet标签中servletDemo的servlet名 -->cn.guojie.servlet.ServletTest相当于实例化cn.guojie.servlet.ServletTest类,类是服务器实例化的,service方法也是服务器调用的
javax是javaEE的,以后不再是Swing的
二、执行过程
三、Servlet生命周期
实例化(构造)-->初始化(init)-->服务(service,多线程)->销毁(destory)
实例化-->初始化:第一次访问Servlet就出生(默认情况下)
服务:应用活着,servlet就活着(每次访问都被调用)
销毁:应用卸载了servlet就销毁
deploy部署
undeploy卸载
让servlet在服务器启动时就创建
1 <servlet> 2 <servlet-name>servletDemo</servlet-name> 3 <servlet-class>cn.guojie.servlet.ServletTest</servlet-class> 4 <load-on-startup>2</load-on-startup> <!-- 数值越高,优先级越高,不要写0,让servlet在服务器启动时就创建 --> 5 </servlet>
四、Servlet的三种创建方式
1、实现javax.servlet.Servlet接口
2、继承javax.servet.GenericServlet类(适配器模式)插座,实现多个接口,重写了多个方法
3、继承javax.servlet.http.HttpServlet类(模板方法设计模式)(开发中常用方式)
1 // 不要在重写父类的service方法 2 @Override 3 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 4 throws ServletException, IOException { 5 System.out.println("doget"); 6 } 7 8 @Override 9 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 10 throws ServletException, IOException { 11 System.out.println("dopost"); 12 }
继承的HttpServlet中service方法,调用service方法判断是get还是post请求,之后再根据请求用doGet还是doPost方法处理
右键创建servlet就是创建的HttpServlet的实现类。
模板设计思想(多态)
接口Servlet s = new ServletDemo();
s.service()是调用ServletDemo的service方法,ServletDemo没有,则找其父亲HttpServlet的service方法,HttpServlet重写了service方法,里面doGet或是doPost判断是get还是post请求,而ServletDemo中重写了doPost和doGet方法,执行ServletDemo中的这两个方法,要是在ServletDemo中重写了doPost和doGet方法,模板设计模式就无效了,无法区分doGet或是doPost
继承图
HttpServlet (继承HttpServlet) --> GenericServlet --> Servlet (小到大)
使生成的servlet更清新一些
找到:MyEclipse\Common\plugins目录
把com.genuitec.eclipse.wizards_9.0.0.me201108091322.jar复制到上面目录
改了web.xml之后要在服务器中重新部署应用
带三角的是继承过来的,不带的是自己的
xml配置信息写错报错,检查配置文件是否写错
servlet映射细节
1、只要servlet-name相同,url-pattern不同也可以通过url-pattern中不同的地址访问同一servlet,多个映射路径
2、通配符* 代表任意字符串
url-pattern: *.do 以*.字符串的请求都可以访问 注:不要加/
url-pattern: /* 任意字符串都可以访问
url-pattern: /action/* 以/action开头的请求都可以访问
匹配规则:
优先级:从高到低
绝对匹配> /开头匹配 >扩展名方式匹配
如果url-pattern的值是/,表示执行默认映射。所有资源都是servlet
在tomcat的conf配置文件中的web.xml中配置为/
1 <servlet-mapping> 2 <servlet-name>default</servlet-name> 3 <url-pattern>/</url-pattern> 4 </servlet-mapping>
五、Servlet的线程安全
单实例:每次访问多线程
解决线程安全问题的最佳办法,不要写全局变量,而写局部变量(每次进去都是初始化为1,分页的时候有用)
SingleThreadModel会每次访问一次建一个;用线程会造成线程不安全
六、Servlet获取配置信息
ServletConfig的使用
作用一:可以获取servlet配置信息
方式1:重写父类GenericServlet的init方法初始化
1 // web.xml中的配置信息 2 <servlet> 3 <servlet-name>ServletConf</servlet-name> 4 <servlet-class>cn.guojie.servletConf.ServletConf</servlet-class> 5 <init-param> 6 <param-name>encoding</param-name> 7 <param-value>GBK</param-value> 8 </init-param> 9 </servlet>
1 private ServletConfig config; 2 3 // 重写父类GenericServlet的init方法初始化得到ServletConfig对象,此对象由服务器创建 4 @Override 5 public void init(ServletConfig config) throws ServletException { 6 // TODO Auto-generated method stub 7 this.config = config; 8 } 9 10 public void doGet(HttpServletRequest request, HttpServletResponse response) 11 throws ServletException, IOException { 12 String parameter = config.getInitParameter("encoding"); // 获取配置文件信息 13 System.out.println(parameter);; 14 }
方式2:(常用)
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 // 通过祖先Servlet的getServletConfig方法获得ServletConfig 4 this.getServletConfig().getInitParameter("encoding"); 5 }
方式3:
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 // HttpServlet已经实现了ServletConfig接口 4 String parameter = this.getInitParameter("encoding"); 5 System.out.println(parameter); 6 }
作用二:可以获得ServletContext对象
七、ServletContext (重要)
ServletContext: 代表的是整个应用,一个应用只有一个ServletContext对象,单实例,服务器启动的时候创建,服务器关闭或者应用卸载时销毁
作用:
1、域对象
在一定范围内(当前应用),使多个Servlet共享数据。
ServletContext 维护一个map存储键值对
![](https://images2015.cnblogs.com/blog/979308/201612/979308-20161205112925991-1991573028.png)
常用方法:
1 void setAttribute(String name,object value); // 向ServletContext对象的map中添加数据 2 Object getAttribute(String name); // 从ServletContext对象的map中取数据 3 void rmoveAttribute(String name); // 根据name去移除数据
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 // 调用GenericServlet的方法得到 4 ServletContext application = this.getServletContext(); 5 // 向ServletContext对象的map中添加数据 6 application.setAttribute("name", "guo"); 7 // 通过反射获取对象所属类名 8 application.getClass().getName(); 9 }
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 // 从ServletContext对象的map中取数据 4 String name = (String) this.getServletContext().getAttribute("name"); 5 System.out.println(name); 6 }
2、获取全局配置信息
修改web.xml文件:
getInitParameter ( String name) //根据配置文件中的key得到value
1 <context-param> 2 <param-name>encoding</param-name> 3 <param-value>UTF-8</param-value> 4 </context-param>
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 // 获取全局配置信息 4 String encoding = this.getServletContext().getInitParameter("encoding"); 5 System.out.println(encoding); 6 }
3、获取资源路径
String getRealPath(String path); //根据资源名称得到资源的绝对路径.
可以得到当前应用任何位置的任何资源(properties、xml...)
ResourceBundle只能取到src目录下的class(myeclipse和服务器中相对应)
不要忘了当前路径的/
1 // 获取在web-info文件夹下的文件 2 private void test1() throws IOException, FileNotFoundException { 3 String realPath = this.getServletContext().getRealPath("/WEB-INF/a.properties"); // /是当前应用根目录,部署在服务器上,故目录要是服务器上的目录,而不是myeclipse的 4 System.out.println(realPath); 5 Properties p = new Properties(); 6 p.load(new FileInputStream(realPath)); 7 String value = p.getProperty("name"); 8 System.out.println(value); 9 }
1 // 获取src目录下的b.properties 2 private void test2() throws IOException, FileNotFoundException { 3 String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/b.properties"); 4 System.out.println(realPath); 5 Properties p = new Properties(); 6 p.load(new FileInputStream(realPath)); 7 String value = p.getProperty("name"); 8 System.out.println(value); 9 }
1 // 获取包下面的b.properties 2 private void test3() throws IOException, FileNotFoundException { 3 String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/cn/guojie/servletContext/c.properties"); 4 System.out.println(realPath); 5 Properties p = new Properties(); 6 p.load(new FileInputStream(realPath)); 7 String value = p.getProperty("name"); 8 System.out.println(value); 9 }
4、实现Servlet的转发
RequestDispatcher getRequestDispatcher ( String path) ;//参数表示要跳转到哪去
1 public void doGet(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 4 ServletContext application = this.getServletContext(); 5 // 像下传递,将应用转发到/servlet/Demo6应用,在web.xml中可看到 6 application.getRequestDispatcher("/servlet/demo5").forward(request, response); 7 }
八、Servlet相关对象
Servlet 接口javax.servlet.Servlet
GenericServlet 抽象类javax.servlet.GenericServlet
HttpServlet 抽象类javax.servlet.http.HttpServlet
ServletConfig 接口javax.servlet.ServletConfig
ServletContext 接口javax.servlet.ServletContext
ServletRequest 接口javax.servlet.ServletRequest
ServletResponse 接口javax.servlet.ServletResponse
HttpServletRequest 接口javax.servlet.http.HttpServletRequest
HttpServletResponse 接口javax.servlet.http.HttpServletResponse
RequestDispatcher 接口javax.servlet.RequestDispatcher
UML
如果是通过参数传过来的对象,就叫依赖
通过方法得到的对象,就叫关联
![](https://images2015.cnblogs.com/blog/979308/201612/979308-20161205140048210-318651357.png)
有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。