zoukankan      html  css  js  c++  java
  • java web学习笔记-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生命周期的那个例子】

        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>指令显示用户对象的各个字段。

     1 package entity;
     2 
     3 import java.util.Date;
     4 
     5 /** 用户实体类 */
     6 public class Users {
     7     private String username;
     8     private String password;
     9     private String email;
    10     private String sex;
    11     private Date birthday;
    12     private String[] favorites;
    13     private String introduce; // 自我介绍
    14     private boolean flag; // 是否接受协议
    15 
    16     public Users() {
    17     }
    18 
    19     public String getUsername() {
    20         return username;
    21     }
    22 
    23     public void setUsername(String username) {
    24         this.username = username;
    25     }
    26 
    27     public String getPassword() {
    28         return password;
    29     }
    30 
    31     public void setPassword(String password) {
    32         this.password = password;
    33     }
    34 
    35     public String getEmail() {
    36         return email;
    37     }
    38 
    39     public void setEmail(String email) {
    40         this.email = email;
    41     }
    42 
    43     public String getSex() {
    44         return sex;
    45     }
    46 
    47     public void setSex(String sex) {
    48         this.sex = sex;
    49     }
    50 
    51     public Date getBirthday() {
    52         return birthday;
    53     }
    54 
    55     public void setBirthday(Date birthday) {
    56         this.birthday = birthday;
    57     }
    58 
    59     public String[] getFavorites() {
    60         return favorites;
    61     }
    62 
    63     public void setFavorites(String[] favorites) {
    64         this.favorites = favorites;
    65     }
    66 
    67     public String getIntroduce() {
    68         return introduce;
    69     }
    70 
    71     public void setIntroduce(String introduce) {
    72         this.introduce = introduce;
    73     }
    74 
    75     public boolean isFlag() {
    76         return flag;
    77     }
    78 
    79     public void setFlag(boolean flag) {
    80         this.flag = flag;
    81     }
    82 
    83 }
    用户实体entity.Users.java
     1 <%@ page language="java" import="java.util.*" contentType="text/html;charset=utf-8"%>
     2 
     3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     4 <html>
     5   <head>
     6     <title>用户注册</title>
     7      <style type="text/css">
     8      .label{
     9           width: 20%    
    10      }
    11      .controler{
    12           width: 80%    
    13      }
    14      </style>  
    15      <script type="text/javascript" src="js/Calendar3.js"></script>
    16   </head>
    17   
    18   <body>
    19        <h1>用户注册</h1>
    20     <hr>
    21     <form name="regForm" action="servlet/RegServlet" method="post" >
    22               <table border="0" width="800" cellspacing="0" cellpadding="0">
    23                 <tr>
    24                     <td class="lalel">用户名:</td>
    25                     <td class="controler"><input type="text" name="username" /></td>
    26                 </tr>
    27                 <tr>
    28                     <td class="label">密码:</td>
    29                     <td class="controler"><input type="password" name="password" ></td>
    30                     
    31                 </tr>
    32                 <tr>
    33                     <td class="label">确认密码:</td>
    34                     <td class="controler"><input type="password" name="confirmpass" ></td>
    35                     
    36                 </tr>
    37                 <tr>
    38                     <td class="label">电子邮箱:</td>
    39                     <td class="controler"><input type="text" name="email" ></td>
    40                     
    41                 </tr>
    42                 <tr>
    43                     <td class="label">性别:</td>
    44                     <td class="controler"><input type="radio" name="sex" checked="checked" value="Male"><input type="radio" name="sex" value="Female"></td>
    45                 </tr>
    46                
    47                 <tr>
    48                     <td class="label">出生日期:</td>
    49                     <td class="controler">
    50                       <input name="birthday" type="text" id="control_date" size="10"
    51                       maxlength="10" onclick="new Calendar().show(this);" readonly="readonly" />
    52                     </td>
    53                 </tr>
    54                 <tr>
    55                     <td class="label">爱好:</td>
    56                     <td class="controler">
    57                     <input type="checkbox" name="favorite" value="nba"> NBA &nbsp;
    58                       <input type="checkbox" name="favorite" value="music"> 音乐 &nbsp;
    59                       <input type="checkbox" name="favorite" value="movie"> 电影 &nbsp;
    60                       <input type="checkbox" name="favorite" value="internet"> 上网 &nbsp;
    61                     </td>
    62                 </tr>
    63                 <tr>
    64                     <td class="label">自我介绍:</td>
    65                     <td class="controler">
    66                         <textarea name="introduce" rows="10" cols="40"></textarea>
    67                     </td>
    68                 </tr>
    69                 <tr>
    70                     <td class="label">接受协议:</td>
    71                     <td class="controler">
    72                         <input type="checkbox" name="isAccept" value="true">是否接受霸王条款
    73                     </td>
    74                 </tr>
    75                 <tr>
    76                     <td colspan="2" align="center">
    77                         <input type="submit" value="注册"/>&nbsp;&nbsp;
    78                         <input type="reset" value="取消"/>&nbsp;&nbsp;
    79                     </td>
    80                 </tr>
    81               </table>
    82     </form>
    83   </body>
    84 </html>
    注册页reg.jsp
     1 <%@ page language="java" import="java.util.*,java.text.*" contentType="text/html; charset=utf-8"%>
     2 <%@ page import="entity.Users" %>
     3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     4 <html>
     5   <head>
     6     <title>用户信息显示</title>
     7     <style type="text/css">
     8      .title{
     9          width: 30%;    
    10          background-color: #CCC;
    11          font-weight: bold;
    12      }
    13      .content{
    14          width:70%;
    15          background-color: #CBCFE5;
    16      }
    17      
    18    </style>  
    19   </head>
    20   
    21   <body>
    22     <h1>用户信息</h1>
    23     <hr>
    24     <center>
    25      <jsp:useBean  id="regUser" class="entity.Users" scope="session"/>   
    26      <table width="600" cellpadding="0" cellspacing="0" border="1">
    27         <tr>
    28           <td class="title">用户名:</td>
    29           <td class="content">&nbsp;<jsp:getProperty name="regUser" property="username"/></td>
    30         </tr>
    31         <tr>
    32           <td class="title">密码:</td>
    33           <td class="content">&nbsp;<jsp:getProperty name="regUser" property="password"/></td>
    34         </tr>
    35         <tr>
    36           <td class="title">性别:</td>
    37           <td class="content">&nbsp;<jsp:getProperty name="regUser" property="sex"/></td>
    38         </tr>
    39         <tr>
    40           <td class="title">E-mail:</td>
    41           <td class="content">&nbsp;<jsp:getProperty name="regUser" property="email"/></td>
    42         </tr>
    43         <tr>
    44           <td class="title">出生日期:</td>
    45           <td class="content">&nbsp;
    46             <% 
    47                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
    48                String date = sdf.format(regUser.getBirthday());
    49             %>
    50              <%=date%>
    51           </td>
    52         </tr>
    53         <tr>
    54           <td class="title">爱好:</td>
    55           <td class="content">&nbsp;
    56             <% 
    57                String[] favorites = regUser.getFavorites();
    58                if(favorites!=null){
    59                    for(String f:favorites)
    60                    {
    61                 %>
    62                     <%=f%> &nbsp;&nbsp;
    63                 <% 
    64                    }
    65                }
    66             %>
    67           </td>
    68         </tr>
    69         <tr>
    70           <td class="title">自我介绍:</td>
    71           <td class="content">&nbsp;<jsp:getProperty name="regUser" property="introduce"/></td>
    72         </tr>
    73         <tr>
    74           <td class="title">是否介绍协议:</td>
    75           <td class="content">&nbsp;<jsp:getProperty name="regUser" property="flag"/></td>
    76         </tr>
    77      </table>
    78     </center>
    79   </body>
    80 </html>
    用户信息显示页userinfo.jsp
     1 package servlet;
     2 
     3 import java.io.IOException;
     4 import java.text.ParseException;
     5 import java.text.SimpleDateFormat;
     6 import java.util.Date;
     7 
     8 import javax.servlet.ServletException;
     9 import javax.servlet.http.HttpServlet;
    10 import javax.servlet.http.HttpServletRequest;
    11 import javax.servlet.http.HttpServletResponse;
    12 
    13 import entity.Users;
    14 
    15 public class RegServlet extends HttpServlet {
    16 
    17     public RegServlet() {
    18         super();
    19     }
    20 
    21     public void destroy() {
    22         super.destroy(); // Just puts "destroy" string in log
    23     }
    24 
    25     public void doGet(HttpServletRequest request, HttpServletResponse response)
    26             throws ServletException, IOException {
    27 
    28         doPost(request, response);//因为表单是post方式提交的
    29     }
    30 
    31     public void doPost(HttpServletRequest request, HttpServletResponse response)
    32             throws ServletException, IOException {
    33 
    34         request.setCharacterEncoding("utf-8");
    35         
    36         Users u = new Users();
    37         String username,password,email,introduce,sex,isAccept;
    38         Date birthday;
    39         String[]favorites;
    40         
    41         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    42         
    43         try {
    44             
    45             username = request.getParameter("username");
    46             password = request.getParameter("password");
    47             sex = request.getParameter("sex");
    48             email = request.getParameter("email");
    49             introduce = request.getParameter("introduce");
    50 
    51             if (request.getParameter("birthday")!=null&&request.getParameter("birthday").length()!=0) {
    52                 birthday = sdf.parse(request.getParameter("birthday"));
    53             }else {
    54                 birthday = new Date();
    55             }
    56             
    57             favorites = request.getParameterValues("favorite");//getParamterValues返回字符串数组
    58             isAccept = request.getParameter("isAccept");
    59             
    60             u.setUsername(username);
    61             u.setPassword(password);
    62             u.setEmail(email);
    63             u.setBirthday(new Date());
    64             u.setIntroduce(introduce);
    65             u.setFavorites(favorites);
    66             u.setSex(sex);
    67             u.setFlag(isAccept!=null&&isAccept.equals("true")?true:false);
    68             
    69             //把注册成功的用户对象保存在session中
    70             request.getSession().setAttribute("regUser", u);
    71             
    72             request.getRequestDispatcher("../userinfo.jsp").forward(request, response);
    73         } catch (ParseException e) {
    74             e.printStackTrace();
    75         }
    76     }
    77 
    78     public void init() throws ServletException {
    79     }
    80 
    81 }
    处理用户注册的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>
     1 package org.po;
     2 
     3 /**
     4  * 用户类-javabean
     5  */
     6 public class Users {
     7     private String username;
     8     private String password;
     9 
    10     public Users() {
    11     }
    12 
    13     public String getUsername() {
    14         return username;
    15     }
    16 
    17     public void setUsername(String username) {
    18         this.username = username;
    19     }
    20 
    21     public String getPassword() {
    22         return password;
    23     }
    24 
    25     public void setPassword(String password) {
    26         this.password = password;
    27     }
    28 
    29 }
    用户实体类org.po.Users
     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 
    10         Users u = new Users();
    11         String username = request.getParameter("username");
    12         String password = request.getParameter("password");
    13         u.setUsername(username);
    14         u.setPassword(password);
    15         
    16         if (u.getUsername().equals("admin")&&u.getPassword().equals("admin")) {
    17             request.getSession().setAttribute("username", username);
    18             request.getRequestDispatcher("/login_success.jsp").forward(request, response);
    19         }else {
    20             response.sendRedirect("../login_failure.jsp");
    21         }
    22     }
    处理用户登录的LoginServlet

    Servlet高级

      1.获取初始化参数

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

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

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

        2.在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>GetInitParameterServlet</servlet-name>
    14     <servlet-class>servlet.GetInitParameterServlet</servlet-class>
    15     
    16     <!-- 配置用户名初始化参数 -->
    17     <init-param>
    18         <param-name>username</param-name>
    19         <param-value>admin</param-value>
    20     </init-param>
    21     <!-- 配置密码初始化参数 -->
    22     <init-param>
    23         <param-name>password</param-name>
    24         <param-value>123456</param-value>
    25     </init-param>
    26     
    27   </servlet>
    28   <!-- 注册Servlet结束 -->
    29 
    30   <servlet-mapping>
    31     <servlet-name>GetInitParameterServlet</servlet-name>
    32     <url-pattern>/servlet/GetInitParameterServlet</url-pattern>
    33   </servlet-mapping>    
    34   <welcome-file-list>
    35     <welcome-file>index.jsp</welcome-file>
    36   </welcome-file-list>
    37 </web-app>
    web.xml

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

     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 GetInitParameterServlet extends HttpServlet {
    12     /* 封装属性 */
    13     private String username ;
    14     private String password ;
    15     
    16     public String getUsername() {
    17         return username;
    18     }
    19     
    20     public void setUsername(String username) {
    21         this.username = username;
    22     }
    23 
    24     public String getPassword() {
    25         return password;
    26     }
    27 
    28     public void setPassword(String password) {
    29         this.password = password;
    30     }
    31 
    32     public GetInitParameterServlet() {
    33         super();
    34     }
    35 
    36     public void destroy() {
    37         super.destroy(); // Just puts "destroy" string in log
    38     }
    39 
    40     public void doGet(HttpServletRequest request, HttpServletResponse response)
    41             throws ServletException, IOException {
    42 
    43         doPost(request, response);
    44     }
    45 
    46     public void doPost(HttpServletRequest request, HttpServletResponse response)
    47             throws ServletException, IOException {
    48 
    49         response.setContentType("text/html;charset=utf-8");
    50         PrintWriter out = response.getWriter();
    51         out.println("<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">");
    52         out.println("<HTML>");
    53         out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    54         out.println("  <BODY>");
    55         out.println("从web.xml中获取初始化参数,用户名:"+username+"<br />");
    56         out.println("从web.xml中获取初始化参数,密码:"+password);
    57         out.println("  </BODY>");
    58         out.println("</HTML>");
    59         out.flush();
    60         out.close();
    61     }
    62 
    63     /** 可以在Servlet的init方法中获得web.xml中配置的初始化参数 */
    64     public void init() throws ServletException {
    65         this.setUsername(this.getInitParameter("username"));
    66         setPassword(getInitParameter("password"));
    67     }
    68 
    69 }
    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)。

    已有的商品实体类:

     1 package entity;
     2 
     3 /**
     4  * 商品类(与DB中的表名一致)-javabean 属性和DB中表的字段完全一致
     5  */
     6 public class Items {
     7     private int id;
     8     private String name;
     9     private String city;
    10     private int price;
    11     private int number;
    12     private String picture;
    13 
    14     public Items() {
    15     }
    16 
    17     public Items(int id, String name, String city, int price, int number,
    18             String picture) {
    19         super();
    20         this.id = id;
    21         this.name = name;
    22         this.city = city;
    23         this.price = price;
    24         this.number = number;
    25         this.picture = picture;
    26     }
    27 
    28     public int getId() {
    29         return id;
    30     }
    31 
    32     public void setId(int id) {
    33         this.id = id;
    34     }
    35 
    36     public String getName() {
    37         return name;
    38     }
    39 
    40     public void setName(String name) {
    41         this.name = name;
    42     }
    43 
    44     public String getCity() {
    45         return city;
    46     }
    47 
    48     public void setCity(String city) {
    49         this.city = city;
    50     }
    51 
    52     public int getPrice() {
    53         return price;
    54     }
    55 
    56     public void setPrice(int price) {
    57         this.price = price;
    58     }
    59 
    60     public int getNumber() {
    61         return number;
    62     }
    63 
    64     public void setNumber(int number) {
    65         this.number = number;
    66     }
    67 
    68 
    69     public String getPicture() {
    70         return picture;
    71     }
    72 
    73     public void setPicture(String picture) {
    74         this.picture = picture;
    75     }
    76     
    77     @Override
    78     public String toString() {
    79         return "商品编号:"+this.getId()+",商品名称:"+this.getName();
    80     }
    81 }
    Items.java

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

      1.购物车类Cart的设计:

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

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

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

    实现如下:

     1 package entity;
     2 
     3 import java.util.HashMap;
     4 import java.util.Iterator;
     5 import java.util.Set;
     6 
     7 /** 购物车类 */
     8 public class Cart {
     9     private HashMap<Items, Integer> goods;// 商品信息以键值对的方式保存在hashMap中
    10     private double totalPrice;
    11 
    12     public Cart() {
    13         // 在构造方法中初始化属性
    14         goods = new HashMap<Items, Integer>();
    15         totalPrice = 0;
    16     }
    17 
    18     public HashMap<Items, Integer> getGoods() {
    19         return goods;
    20     }
    21 
    22     public void setGoods(HashMap<Items, Integer> goods) {
    23         this.goods = goods;
    24     }
    25 
    26     public double getTotalPrice() {
    27         return totalPrice;
    28     }
    29 
    30     public void setTotalPrice(double totalPrice) {
    31         this.totalPrice = totalPrice;
    32     }
    33 
    34     /**
    35      * 添加商品到购物车
    36      * @param items:商品对象
    37      * @param number:商品数量
    38      */
    39     public boolean addGoodsInCart(Items item, int number) {
    40         goods.put(item, number);
    41         calcTotalPrice();// 重新计算购物车的总金额
    42         return true;
    43     }
    44 
    45     /**
    46      * 从购物车中删除商品
    47      */
    48     public boolean removeGoodsFromCart(Items item) {
    49         goods.remove(item);
    50         calcTotalPrice();// 重新计算购物车的总金额
    51         return true;
    52     }
    53 
    54     /** 计算购物车的总金额 */
    55     public double calcTotalPrice() {
    56         double sum = 0;
    57         Set<Items> keys = goods.keySet();// 获得键的集合
    58         Iterator<Items> iterator = keys.iterator();
    59         while (iterator.hasNext()) {
    60             Items items = (Items) iterator.next();
    61             sum += items.getPrice() * goods.get(items);
    62         }
    63         this.setTotalPrice(sum);// 设置总金额
    64         return sum;
    65     }
    66 }
    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类调用购物车类的代码实现购物功能。

     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 import dao.ItemsDAO;
    12 import entity.Cart;
    13 import entity.Items;
    14 
    15 public class CartServlet extends HttpServlet {
    16     
    17     private String action;//购物车的动作(添加?删除?显示?商品)
    18     private ItemsDAO idao = new ItemsDAO();//商品业务逻辑类的对象
    19 
    20     public CartServlet() {
    21         super();
    22     }
    23 
    24     public void destroy() {
    25         super.destroy(); // Just puts "destroy" string in log
    26     }
    27 
    28     public void doGet(HttpServletRequest request, HttpServletResponse response)
    29             throws ServletException, IOException {
    30         doPost(request, response);
    31     }
    32     
    33     public void doPost(HttpServletRequest request, HttpServletResponse response)
    34             throws ServletException, IOException {
    35 
    36         response.setContentType("text/html;charset=utf-8");
    37         PrintWriter out = response.getWriter();
    38         if (request.getParameter("action")!=null) {
    39             this.action = request.getParameter("action");
    40             
    41             if (action.equals("add")) {//添加商品进购物车
    42                 if(addToCart(request,response)){
    43                     request.getRequestDispatcher("/add_to_cart_success.jsp").forward(request, response);
    44                 }else {
    45                     request.getRequestDispatcher("/add_to_cart_failure.jspp").forward(request, response);
    46                 }
    47             }
    48             if (action.equals("show")) {//显示购物车
    49                 request.getRequestDispatcher("/cart.jsp").forward(request, response);
    50             }
    51             if(action.equals("delete")){//从购物车中删除商品
    52                 deleteFromCart(request,response);
    53                 request.getRequestDispatcher("/cart.jsp").forward(request, response);
    54             }
    55         }
    56     }
    57 
    58     /** 从购物车中删除商品  */
    59     private boolean deleteFromCart(HttpServletRequest request,
    60             HttpServletResponse response) {
    61         String id = request.getParameter("id");
    62         Cart cart = (Cart) request.getSession().getAttribute("cart");
    63         Items item = idao.getItemsById(Integer.parseInt(id));
    64         if (cart.removeGoodsFromCart(item)) {
    65             return true;
    66         }else {
    67             return false;
    68         }
    69     }
    70 
    71     /** 添加商品进购物车 */
    72     private boolean addToCart(HttpServletRequest request,
    73             HttpServletResponse response) {
    74         String id = request.getParameter("id");
    75         String number = request.getParameter("num");
    76         Items item = idao.getItemsById(Integer.parseInt(id));
    77         
    78         //是否是第一次给购物车添加商品?【给session中创建一个购物车对象】
    79         if (request.getSession().getAttribute("cart")==null) {
    80             Cart cart= new Cart();
    81             request.getSession().setAttribute("cart", cart);
    82         }
    83         
    84         //获得Session中保存的购物车对象
    85         Cart cart = (Cart) request.getSession().getAttribute("cart");
    86         if (cart.addGoodsInCart(item, Integer.parseInt(number))) {
    87             return true;
    88         }else {
    89             return false;
    90         }
    91     }
    92 
    93     public void init() throws ServletException {
    94     }
    95 
    96 }
    CartServlet

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

      1 <%@page import="entity.Items"%>
      2 <%@page import="dao.ItemsDAO"%>
      3 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
      4 <%
      5 String path = request.getContextPath();
      6 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
      7 %>
      8 <!-- 显示商品详情,并在右侧显示商品的浏览记录(最近5条记录) -->
      9 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     10 <html>
     11   <head>
     12     <title>欢迎光临网上商城</title>
     13     <link href="css/main.css" rel="stylesheet" type="text/css">
     14     <script type="text/javascript" src="js/lhgcore.js"></script>
     15     <script type="text/javascript" src="js/lhgdialog.js"></script>
     16     <style type="text/css">
     17         div{
     18           float:left;
     19           margin-left: 30px;
     20           margin-right:30px;
     21           margin-top: 5px;
     22           margin-bottom: 5px;
     23         }
     24         div dd{
     25           margin:0px;
     26           font-size:10pt;
     27         }
     28         div dd.dd_name{
     29           color:blue;
     30         }
     31         div dd.dd_city{
     32           color:#000;
     33         }
     34         div #cart{
     35          margin:0px auto;
     36          text-align:right; 
     37         }
     38         span{
     39          padding:0 2px;border:1px #c0c0c0 solid;cursor:pointer;
     40         }
     41         a{
     42           text-decoration: none; 
     43         }
     44     </style>
     45     <script type="text/javascript">
     46       function selflog_show(id) { 
     47          var num =  document.getElementById("number").value; 
     48          J.dialog.get({id: 'haoyue_creat',title: '购物成功', 600,height:400, link: '<%=path%>/servlet/CartServlet?id='+id+'&num='+num+'&action=add', cover:true});
     49       }
     50       function add(){
     51          var num = parseInt(document.getElementById("number").value);
     52          if(num<100){
     53             document.getElementById("number").value = ++num;
     54          }
     55       }
     56       function sub(){
     57          var num = parseInt(document.getElementById("number").value);
     58          if(num>1){
     59             document.getElementById("number").value = --num;
     60          }
     61       }
     62     </script>
     63   </head>
     64   
     65   <body> 
     66       <h1>商品详情</h1><hr>
     67       <a href="index.jsp">首页</a> >> <a href="index.jsp">商品列表</a><hr/>
     68       <center>
     69           <table width="750" height="60" cellpadding="0" cellspacing="0" border="0">
     70               <tr>
     71               <!-- 商品详细信息 -->
     72               <%
     73                   Items item = new ItemsDAO().getItemsById(Integer.parseInt(request.getParameter("id")));
     74                   if(item!=null){
     75                %>
     76                       <td width="70%" valign="top">
     77                           <table>
     78                               <tr>
     79                                   <td rowspan="4"><img src="images/<%=item.getPicture()%>" width="200" height="160"/></td>
     80                               </tr>
     81                               <tr>
     82                                   <td><b><%=item.getName() %></b></td>
     83                               </tr>
     84                               <tr>
     85                                   <td>产地:<%=item.getCity() %></td>
     86                               </tr>
     87                               <tr>
     88                                   <td>价格:¥<font color="red"><b><%=item.getPrice() %></b></font></td>
     89                               </tr>
     90                               <tr>
     91                                   <td>
     92                                       购买数量:<span id="sub" onclick="sub();">-</span>
     93                                       <input type="text" id="number" name="number" value="1" size="2"/>
     94                                       <span id="add" onclick="add();">+</span>
     95                                   </td>
     96                               </tr>
     97                           </table>
     98                           <div id="cart">
     99                                <img src="images/buy_now.png">
    100                                <a href="javascript:selflog_show(<%=item.getId()%>)"><img src="images/in_cart.png" /></a>
    101                                <a href="servlet/CartServlet?action=show"><img src="images/view_cart.jpg"/></a>
    102                          </div>
    103                       </td>
    104               <%
    105                   }    
    106                %>
    107                <!-- 取得Cookie -->
    108                <%
    109                    String list = "";
    110                    // 从客户端获得Cookie集合
    111                    Cookie[]cookies = request.getCookies();
    112                    if(cookies!=null&&cookies.length>0){
    113                        for(Cookie c:cookies){
    114                            if(c.getName().equals("ListViewCookie")){
    115                                list = c.getValue();
    116                            }
    117                            
    118                            String[] arr = list.split(",");
    119                            // 相同商品只在浏览记录中存放一次
    120                            if(Arrays.binarySearch(arr, request.getParameter("id"))<0){
    121                                list += request.getParameter("id") + ",";
    122                            }
    123                            // 如果浏览记录超过1000条,则清空Cookie
    124                            if(arr!=null&&arr.length>1000){
    125                                list = "";// 清零-置空串
    126                            }
    127                            Cookie cookie = new Cookie("ListViewCookie",list);
    128                            response.addCookie(cookie);
    129                        }
    130                    }
    131                 %>
    132                 
    133                 <!-- 浏览过的商品 -->
    134                 <td width="30%" bgcolor="#EEE" align="center">
    135                     <br /><b>您浏览过的商品</b><br />
    136                     <!-- 循环开始 -->
    137                     <%
    138                         ArrayList<Items>itemsList = new ItemsDAO().getViewList(list);
    139                         if(itemsList!=null&&itemsList.size()>0){
    140                             for(Items i:itemsList){
    141                      %>
    142                             <div>
    143                                 <dl>
    144                                     <dt><img src="images/<%=i.getPicture() %>" width="120" height="90" border="1" /></dt>
    145                                     <dd class="dd_name"><%=i.getName() %></dd>
    146                                     <dd class="dd_city">产地:<%=i.getCity() %>&nbsp;&nbsp;价格:¥<%=i.getPrice() %></dd>
    147                                 </dl>
    148                             </div>
    149                     <%
    150                             }
    151                         }
    152                      %>
    153                     <!-- 循环结束 -->
    154                 </td>
    155               </tr>
    156           </table>
    157       </center>
    158   </body>
    159 </html>
    details.jsp

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

  • 相关阅读:
    最小的linux发行版TinyCore Linux 系统,从分区安装系统开始
    目标世界上最小的Linux系统—ttylinux体验
    在虚拟机上安装树莓派系统
    天气预报查询
    树莓派做服务器,搭建Typecho博客和Owncloud云盘
    超好用的C#控制台应用模板
    一个简单好用的日志框架NLog
    让编写的单元测试同时支持 NUnit/MSTest
    使用MSTest进行单元测试入门
    C#开源日志文件实时监控工具Tail
  • 原文地址:https://www.cnblogs.com/happyfans/p/4363366.html
Copyright © 2011-2022 走看看