zoukankan      html  css  js  c++  java
  • JSP-Servlet的工作流程

    Servlet基础

      1.Servlet概述

        JSP的前身就是Servlet。Servlet就是在服务器端运行的一段小程序。一个Servlet就是一个Java类,并且可以通过“请求-响应”编程模型来访问的这个驻留在服务器内存的Servlet程序。

      2.Tomcat容器等级

        Tomcat的容器分为4个等级,Servlet的容器管理Context容器,一个Context对应一个Web工程。

      3.手工编写第一个Servlet

        编写一个Servlet程序大体上需要3个步骤:继承HttpServlet-->重写doGet()或者doPost()方法-->在web.xml中注册Servlet。

        HttpServlet的继承关系如图:

        重写doGet还是doPost方法需要根据请求方式而定。

      一、编写一个类继承自HttpRequest并重写doGet(或者doPost方法)在项目的src目录下新建一个servlet.MyServlet.java

    复制代码
     1 package servlet;
     2 
     3 import java.io.IOException;
     4 import java.io.PrintWriter;
     5 
     6 import javax.servlet.ServletException;
     7 import javax.servlet.http.HttpServlet;
     8 import javax.servlet.http.HttpServletRequest;
     9 import javax.servlet.http.HttpServletResponse;
    10 
    11 /** 继承自HttpServlet */
    12 public class HelloServlet extends HttpServlet {
    13 
    14     /** 重写doGet方法 */
    15     @Override
    16     protected void doGet(HttpServletRequest request, HttpServletResponse response)
    17             throws ServletException, IOException {
    18         System.out.println("处理get请求。。。");
    19         PrintWriter out = response.getWriter();
    20         out.println("<b>HelloServlet</b>");
    21     }
    22 
    23     /** 重写doPost方法 */
    24     @Override
    25     protected void doPost(HttpServletRequest request, HttpServletResponse response)
    26             throws ServletException, IOException {
    27         System.out.println("处理post请求。。。");
    28         PrintWriter out = response.getWriter();
    29         out.println("<b>HelloServlet</b>");
    30     }
    31     
    32 }
    复制代码

      二、在WEB-INF/web.xml中注册刚刚新建的Servlet:

    复制代码
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <web-app version="2.5" 
     3     xmlns="http://java.sun.com/xml/ns/javaee" 
     4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
     7   <display-name></display-name>    
     8   <welcome-file-list>
     9     <welcome-file>index.jsp</welcome-file>
    10   </welcome-file-list>
    11   
    12   <!-- 注册Servlet开始 -->
    13   <servlet>
    14       <servlet-name>HelloServlet</servlet-name>
    15       <servlet-class>servlet.HelloServlet</servlet-class>
    16   </servlet>
    17   <servlet-mapping>
    18       <servlet-name>HelloServlet</servlet-name>
    19       <url-pattern>/servlet/HelloServlet</url-pattern>
    20   </servlet-mapping>
    21   <!-- 注册Servlet结束 -->
    22   
    23 </web-app>
    复制代码

      其中servlet-name表示Servlet的名字,servlet-class要写完成的类的定义(包名.类名),url-pattern表示Servlet的路径。

      在index.jsp中使用自定义的Servlet处理get和post请求。

    复制代码
     1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
     2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     3 <html>
     4   <head>
     5     <title>手工编写的第一个Servlet</title>
     6   </head>
     7   
     8   <body>
     9     <h1>第一个Servlet小例子</h1><hr>
    10     <a href="servlet/HelloServlet">get方式请求HelloServlet</a><br /><br />
    11     <form action="servlet/HelloServlet" method="post">
    12         <input type="submit" value="post方式请求HelloServlet" /> 
    13     </form>
    14   </body>
    15 </html>
    复制代码

     发布项目,运行结果:

       一个Servlet可以在web.xml中配置多个映射,这样就可以在URL中使用不同的名字访问相同的Servlet。如下所示:就可以使用给人以假象——好像使用的是asp或者php或者更多的语言。

    复制代码
     1 <!-- 注册Servlet开始 -->
     2 <servlet>
     3     <servlet-name>HelloServlet</servlet-name>
     4     <servlet-class>servlet.HelloServlet</servlet-class>
     5 </servlet>
     6 <!-- 一个Servlet可以配置多个映射,向下面这样配置就可以有多种方式访问Servlet了 -->
     7 <servlet-mapping>
     8   <servlet-name>HelloServlet</servlet-name>
     9   <url-pattern>/servlet/HelloServlet</url-pattern>
    10 </servlet-mapping>
    11  <servlet-mapping>
    12   <servlet-name>HelloServlet</servlet-name>
    13   <url-pattern>/servlet/HelloServlet.asp</url-pattern>
    14 </servlet-mapping>
    15  <servlet-mapping>
    16   <servlet-name>HelloServlet</servlet-name>
    17   <url-pattern>/servlet/HelloServlet.php</url-pattern>
    18 </servlet-mapping>
    19  <servlet-mapping>
    20   <servlet-name>HelloServlet</servlet-name>
    21   <!-- *表示任意名称均可 -->
    22   <url-pattern>/servlet/hello/*</url-pattern>
    23 </servlet-mapping>
    24 <!-- 注册Servlet结束 -->
    复制代码

      4.使用MyEclipse编写Servlet

          1.src-->new Servlet。

          2.重写doGet()或者doPost()方法。  

          3.部署运行。

       通过MyEclipse创建Servlet的时候它默认继承自HttpServlet。默认勾选覆写init()、destory()、doGet()和doPost()方法,并且自动向web.xml中注册该Servlet。

       可以发现使用MyEclipse创建的Servlet它已经自动为我们生成了输出的html模板,我们只需要做很少的改动即可。   

      5.Servlet的执行流程和生命周期

        用户点击超链接向Servlet发送请求-->服务器在web.xml中的servlet-mapping寻找与该Servlet相对应的URL地址-->找到对应的Servlet名字-->根据Servlet的名字找到和该Servlet相关的处理类-->根据请求的方式不同确定是调用doGet还是doPost方法。

        一个Servlet的生命周期大致分为3个阶段:

      

        1.客户端发送请求给服务器。

        2.服务器开始接受,先判断该请求的servlet实例是否存在,如果不存在先装载一个servlet类并创建实例。

            如果存在则直接调用该servlet的service方法,之后进行判断是调用  doGet方法还是doPost方法。

        3.servlet创建实例后,调用init方法进行初始化。之后调用servce方法,判断是调用doGet方法还是doPost方法。

          4.最后判断服务器是否关闭,如果关闭则调用destroy方法。

      下面这个例子展示了Servlet的生命周期:

    首先是一个Servlet:TestServlet1

    复制代码
     1 package servlet;
     2 
     3 import java.io.IOException;
     4 import java.io.PrintWriter;
     5 
     6 import javax.servlet.ServletException;
     7 import javax.servlet.http.HttpServlet;
     8 import javax.servlet.http.HttpServletRequest;
     9 import javax.servlet.http.HttpServletResponse;
    10 
    11 public class TestServlet1 extends HttpServlet {
    12 
    13     public TestServlet1() {
    14         System.out.println("TestServlet1构造方法被执行!");
    15     }
    16 
    17     public void destroy() {
    18         System.out.println("TestServlet1销毁方法被执行!");
    19     }
    20 
    21     public void doGet(HttpServletRequest request, HttpServletResponse response)
    22             throws ServletException, IOException {
    23 
    24         System.out.println("TestServlet1的doGet方法被执行!");
    25         response.setContentType("text/html;charset=utf-8");
    26         PrintWriter out = response.getWriter();
    27         out.println("<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">");
    28         out.println("<HTML>");
    29         out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    30         out.println("  <BODY>");
    31         out.println("<h1>你好我是TestServlet1</h1>");
    32         out.println("  </BODY>");
    33         out.println("</HTML>");
    34         out.flush();
    35         out.close();
    36     }
    37 
    38     public void doPost(HttpServletRequest request, HttpServletResponse response)
    39             throws ServletException, IOException {
    40         System.out.println("TestServlet1的doPost方法被执行!");
    41         doGet(request, response);// 让doPost与doGet执行相同的操作
    42     }
    43 
    44     public void init() throws ServletException {
    45         System.out.println("TestServlet1的初始化方法被执行!");
    46     }
    47 
    48 }
    复制代码

        主页index.jsp

    复制代码
     1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
     2 <%
     3 String path = request.getContextPath();
     4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
     5 %>
     6 
     7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     8 <html>
     9   <head>
    10     <base href="<%=basePath%>">
    11     <title>Servlet的生命周期</title>
    12   </head>
    13   
    14   <body>
    15       <h1>Servlet的生命周期</h1><hr />
    16       <a href = "servlet/TestServlet1">以get方式请求TestServlet1</a>
    17   </body>
    18 </html>
    复制代码

      当服务器启动之后我们第一次访问index.jsp的时候,构造方法,初始化方法和doGet()方法执行

        当我们再次请求该页面的时候,只有doGet()方法被执行:

        服务器关闭的时候销毁方法执行。

     6.Tomcat装载Servlet的3种情况

        在下列时刻Servlet容器会加载Servlet:

        1.Servlet容器启动时自动装载某些Servlet,实现它只需要在web.xml文件中的<servlet></servlet>之间添加以下代码:

    <load-on-startup>1</load-on-startup>

      其中,数字越小表示优先级越高。

        例如:我们在web.xml中设置TestServlet2的优先级为1,而TestServlet1的优先级为2,启动和关闭Tomcat:

      优先级高的先启动也先关闭。

        2.客户端首次向某个Servlet发送请求。【例子详见Servlet生命周期的那个例子】?//JSP自动会生成Servlet是为了生成动态的HTML页面流,以便浏览器引擎转化成网页,同时也是为了与Servlet类进行交换数据。

                //JSP—>servlet发送request时候需要写入相应servlet的地址,{一种通过JSP文件里使用跳转标签指明处理该JSP处理的servlet,或者在servlet中通过@WEBSERVLET进行注射}

               web.xml文件只备注servlet,filter等等类的信息。但是这些不是给备注JSP与Servlet对应关系的信息。所以,jsp与servlet对应关系的地址需要在程序里写入,容器引擎我会根据地址自动处理。 //servlet—>jsp发送消息也需要写入{或者通过request重新跳转到一个JSP}

        3.Servlet类被修改后,Tomcat容器会重新装载Servlet。

        Servlet被装载后,Servlet容器会创建一个Servlet实例,并且调用Servlet的init()方法进行初始化,在Servlet的真个生命周期内init()方法只被调用一次。

      7.Servlet与JSP内置对象的对应关系

      8.Servlet获取表单数据

        用户在reg.jsp中填写注册表单,使用post方式将数据发送到一个名称为servlet.RegServlet的Servlet处理【Servlet的doPost()方法】,Servlet将用户信息封装成一个Users对象存储在session中,讲请求转发到userinfo.jsp。在userinfo.jsp中通过<jsp:useBean>指令从session中取出保存的用户对象,通过<jsp:getPerproty>指令显示用户对象的各个字段。

     用户实体entity.Users.java
     注册页reg.jsp
     用户信息显示页userinfo.jsp
     处理用户注册的Servlet:RegServlet

      9.Servlet路径跳转

        相对路径就是相对于当前页面的路径,绝对路径就是相对于项目根目录的路径(绝对路径需要使用到path变量)。

    复制代码
     1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
     2 <%
     3 String path = request.getContextPath();
     4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
     5 %>
     6 
     7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     8 <html>
     9   <head>
    10     <base href="<%=basePath%>">
    11     <title>Servlet路径跳转</title>
    12   </head>
    13   
    14   <body>
    15     <h1>Servlet路径跳转</h1>
    16     <!-- 使用相对路径访问HelloServlet -->
    17     <a href="servlet/HelloServlet">使用相对路径访问servlet</a><br />
    18     
    19     <!-- 使用绝对路径访问HelloServlet,使用path变量 -->
    20     项目的根目录:<%=path %><br />
    21     <a href="<%=path %>/servlet/HelloServlet">使用相对路径访问servlet</a><br />
    22   </body>
    23 </html>
    复制代码

      在web.xml中注册的Servlet的路径写法是绝对路径:

    复制代码
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <web-app version="2.5" 
     3     xmlns="http://java.sun.com/xml/ns/javaee" 
     4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
     7   <display-name></display-name>
     8   
     9   <!-- Servlet注册开始 -->
    10   <servlet>
    11     <description>This is the description of my J2EE component</description>
    12     <display-name>This is the display name of my J2EE component</display-name>
    13     <servlet-name>HelloServlet</servlet-name>
    14     <servlet-class>servlet.HelloServlet</servlet-class>
    15   </servlet>
    16   <servlet-mapping>
    17     <servlet-name>HelloServlet</servlet-name>
    18     <url-pattern>/servlet/HelloServlet</url-pattern><!-- Servlet的路径是绝对路径 -->
    19   </servlet-mapping>
    20   <!-- Servlet注册结束 -->
    21       
    22   <welcome-file-list>
    23     <welcome-file>index.jsp</welcome-file>
    24   </welcome-file-list>
    25 </web-app>
    复制代码

      在Servlet之中路径的跳转问题:

        index.jsp中有一个链接指向servlet.TestServlet

    <a href="servlet/TestServlet">访问TestServlet,跳转到Test.jsp</a>

        servlet.TestServlet的doPost()和doGet()方法如下:

    复制代码
     1 public void doGet(HttpServletRequest request, HttpServletResponse response)
     2             throws ServletException, IOException {
     3 
     4             doPost(request, response);
     5     }
     6 
     7     public void doPost(HttpServletRequest request, HttpServletResponse response)
     8             throws ServletException, IOException {
     9         // 1.使用请求重定向的方式跳转到test.jsp
    10 //        response.sendRedirect("../test.jsp");
    11         // 也可以使用绝对路径的方式request.getContextPath
    12 //        response.sendRedirect(request.getContextPath()+"/test.jsp");
    13         
    14         // 2.使用服务器内部跳转的方式
    15 //        request.getRequestDispatcher("../test.jsp").forward(request, response);
    16         request.getRequestDispatcher("/test.jsp").forward(request, response);
    17     }
    复制代码

      在TestServlet中完成到网站根目录下的跳转有两种方式重定向和服务器内部转发,其中URL的写法也有2种方式:绝对路径和相对路径。相对路径使用..即可,而绝对路径重定向需要依赖request.getContextPath()方法取得上下文环境,而服务器内部转发中的斜线就表示项目的根目录。

      开发中一般在web.xml中配置Servlet的路径为表单所在路径,这样在表单中只需要书写Servlet名字即可。在开发中应该尽量避免../的写法。

      10.阶段案例——使用Servlet完成用户登录

    用户名和密码都是admin,登陆成功则使用服务器内部转发到login_success.jsp,显示登录成功的用户名。登录失败则重定向到login_failure.jsp。

      把login.jsp中表单的action属性改为需要处理登录的Servlet

    1 <form action="servlet/LoginServlet" method="post" name="loginForm">
    2     <!-- 代码省略 -->
    3 </form>
     用户实体类org.po.Users
     处理用户登录的LoginServlet

    Servlet高级

      1.获取初始化参数

        在web.xml中配置Servlet时,可以配置一些初始化参数。而在Servlet中可以通过ServletConfig接口提供的方法来取得这些参数。

        1.首先在index.jsp中建立一条超链接指向servlet.GetInitParameterServlet。

    <a href = "servlet/GetInitParameterServlet">获取Servlet的初始化参数</a>

        2.在web.xml中配置该Servlet的初始化参数:

     web.xml

        3.在GetInitParameterServlet的init方法中使用this.getgetInitParameter(String name)方法获得初始化参数:

     servlet.GetInitParameterServlet.java

    运行结果:

      2.MVC模式

      MVC旨在分离模型、视图、控制。是分层思想的一种体现。

    结构图如下:

      1.浏览器发送请求被控制器接收(Servlet)。

      2.由控制器实例化一个模型层对象(JavaBean),模型层访问EIS(企业信息系统,就是DB)。EIS将结果返回给JavaBean,JavaBean将结果返回给控制层Servlet。

      3.控制层根据模型层返回的结果选择合适的视图给用户呈现。

      3.Model2简介

      Model2实际上就是JSP(V)+Servlet(C)+JavaBean(M),是MVC设计思想。

      4.阶段项目:使用MVC实现购物车

    JSP(View)+Servlet(Control)+ dao(Model)。

    已有的商品实体类:

     Items.java

    实现阶段:创建购物车类-->编写Servlet-->创建页面层。

      1.购物车类Cart的设计:

      购物车有2个属性,分别是购买商品的集合和商品的总价格。

      购物车的方法有3个:添加商品、删除商品、计算商品的总价格。

      那么问题来了,我们应该使用何种集合来存储用户购买的商品?我们可以使用Map类型,键是商品对象,值是该种商品的数量。

    实现如下:

     Cart.java

    接下来测试上面的购物车类:

      直接在给Cart类中编写main方法测试购物车类;

    复制代码
     1 public static void main(String[] args) {
     2         //创建2个商品对象
     3         Items i1 = new Items(1, "沃特篮球鞋", "温州", 200, 500, "001.jpg");
     4         Items i2 = new Items(2, "李宁运动鞋", "广州", 300, 500, "002.jpg");
     5         Items i3 = new Items(1, "沃特篮球鞋", "温州", 200, 500, "001.jpg");
     6         
     7         //创建购物车对象
     8         Cart cart = new Cart();
     9         cart.addGoodsInCart(i1, 1);
    10         cart.addGoodsInCart(i2, 2);
    11         cart.addGoodsInCart(i3, 3);//再买3双沃特篮球鞋
    12         
    13         
    14         //购物车中商品的集合
    15         Set<Map.Entry<Items, Integer>>items = cart.getGoods().entrySet();
    16         for (Map.Entry<Items, Integer> entry : items) {
    17             System.out.println(entry);
    18         }
    19         System.out.println("买4双沃特篮球鞋和2双李宁运动鞋之后,购物车总价格:"+cart.getTotalPrice());;
    20 }
    复制代码

      运行结果:

     

     虽然总金额的计算没有问题,但是用户体验不太好,购物车中中出现了相同的商品记录(应该是需要合并的)。

     一种方式是重写Items类的hashCode和equals方法。重写之后再次运行程序:

      虽然商品的记录在购物车中不会重复,但是购买的数量却不对了,沃特篮球鞋的后面的一条记录替换掉了前面的记录。

      解决方案:此时只要修改购物车的addGoodsInCart()方法就行了:在加入新的商品之前先判断如果已经添加了相同的商品,只需要修改商品的数量即可:

    复制代码
     1 public boolean addGoodsInCart(Items item, int number) {
     2         //如果商品已经在购物车中只需要修改商品数量即可【原有数量+新加入的数量】
     3         if (goods.containsKey(item)) {
     4             goods.put(item, goods.get(item)+number);
     5         }else {
     6             goods.put(item, number);
     7         }
     8         calcTotalPrice();// 重新计算购物车的总金额
     9         return true;
    10 }
    复制代码

      运行结果:

      2.Servlet类的设计

        由Servlet类调用购物车类的代码实现购物功能。

     CartServlet

      3.界面层在details.jsp页面中显示购物车。

     details.jsp

      项目的完整地址:https://git.oschina.net/gaopengfei/JavaWebShoppingDemoByMVC.git

     
     
    标签: javajava webServlet
  • 相关阅读:
    calc常用
    windbg学习---.browse打开一个新的command 窗口
    Native wifi API使用
    驱动学习---PAE--virtual address to physics address
    windbg学习.formats--转换成各种进制
    windbg学习---!thread和.thread
    windbg学习----.process
    windbg学习---!process
    windbg命令----!idt
    16进制转换成字符串
  • 原文地址:https://www.cnblogs.com/w-wfy/p/5833103.html
Copyright © 2011-2022 走看看