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
  • 相关阅读:
    有点忙啊
    什么是协程
    HDU 1110 Equipment Box (判断一个大矩形里面能不能放小矩形)
    HDU 1155 Bungee Jumping(物理题,动能公式,弹性势能公式,重力势能公式)
    HDU 1210 Eddy's 洗牌问题(找规律,数学)
    HDU1214 圆桌会议(找规律,数学)
    HDU1215 七夕节(模拟 数学)
    HDU 1216 Assistance Required(暴力打表)
    HDU 1220 Cube(数学,找规律)
    HDU 1221 Rectangle and Circle(判断圆和矩形是不是相交)
  • 原文地址:https://www.cnblogs.com/w-wfy/p/5833103.html
Copyright © 2011-2022 走看看