红宝儿

导航

使用分层实现业务处理

第五章:使用分层实现业务处理
JNDI(Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。现在JNDI已经成为J2EE的标准之一,所有的J2EE容器都必须提供一个JNDI的服务。
JNDI可访问的现有的目录及服务有:
DNS、XNam 、Novell目录服务、LDAP(Lightweight Directory Access Protocol轻型目录访问协议)、 CORBA对象服务、文件系统、Windows XP/2000/NT/Me/9x的注册表、RMI、DSML v1&v2、NIS。数据库
Tomcat 根目录\conf\context.xml文件为全局的上下文配置文件,对所有的Web应用有效。所以将要发布的信息配置在此问件中,再通过JNDI来查找信息
    ---我们可以在Tomcat中发布一条信息,修改context.xml
   
            <Context>
                 <Environment type="java.lang.String" name="林建辉" value="hello"/>
           </Context>
type:java类名的全称
name:变量名,相对于java:comp/env的路径
value:变量值
 数据库连接池的配置:
(第一步:)
 <Resource name="jdbc/news" auth="Container"
  type="javax.sql.DataSource" maxActive="100"
  maxIdle="30" maxWait="10000"
  username="sa" password="123456"  
          url="jdbc:sqlserver://localhost:1433;DatabaseName=NewsManagerSystem"                     
  driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
/>
<!---
       name:指定resource 的JNDI 名字
       auth:指定管理Resource 的Manager,他有两个可选值:Container和Application
       Container表示由容器创建Resource,Application表示由Web应用创建和管理Resource
       type指定由Resource所属的java全类名
       maxActive:指定数据库连接池中处于活动状态的数据库连接的最大数目
       maxIdel:指定数据库连接池中处于空闲状态的数据库连接的最大数目,0表示不受约束
       maxWait:指定数据库连接池中处于空闲状态的最长时间,
              -1表示无限制(以毫秒为单位),超出这 一时间会抛出异常
       username:指定连接数据库的用户名
       password:指定连接数据库的密码
       driverClassName:指定连接数据库的JDBC 驱动程序
       url:指定连接数据库的路径
->
(第二步:)
<web-app>  -----在web.xml里配置
  <resource-ref>
     <res-ref-name> jdbc/news </res-ref-name>--资源的引用名称---可改
     <res-type>  javax.sql.DataSource </res-type> --资源类型
     <res-auth>Container</res-auth>--指定管理所应用资源的Manager
  </resource-ref>
</web-app>  
(第三步:在Basedao中)
import javax.naming.*
          // javax.naming.Context 提供了查找JNDI Resource的接口
             //java:comp/env 为前缀
           Context context=new InitialContext();
            DataSource ds=(DataSource)context.lookup("java:comp/env/jdbc/news");
            con=ds.getConnection();  
还有一种配置数据源的方式,只需要在webRoot 目录下的META-INF目录中,创建一个context.xml文件,添加<Context>节点,然后再写<Resource>
数据源配置完后,要通过数据源访问数据库,还需要添加数据库驱动文件,由于数据源由Tomcat创建并维护,所以必须要把数据库驱动文件放到Tomcat的lib目录下
在使用JNDI获得数据源对象时,可分为如下四个步骤
1:在Tomcat的conf下配置context.xml文件
2:在web应用程序的web-inf下配置web.xml文件
3:添加驱动-------jdbc.jar
4:进行代码编写,使用loopup("java:comp/env/jdbc/news")方法获得数据源对象
"java:comp/env+数据源名称
 
什么是连接池?
数据库连接是非常占用系统资源的,这一点在多用访问的应用程序中体现得尤为突出,对数据库连接的管理   会影响到整个应用程序的伸缩性和健壮性。数据库连接池这是针对这个问题提出来的。
数据库连接池负责分配、管理和释放 数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建一个,它会释放空闲时间超过最大空闲时间的数据库连接
日常生活中的实例:拨打10086热线
热线电话对外是相同的号码,允许同时接入多个电话,但是当所有的接入都在工作,再有电话接入时,就需要等待,直到其中一个接入出现空闲
 
连接池如何管理连接?
  对于连接池的管理可用空闲池,每当用户请求一个连接时,系统先会检查空闲池内有没有空闲连接如果有就分配一个连接给用户;如果没有则检查当前连接池是否达到连接池所允许的最大连接数。如果没有达到,就新建一个连接。如果已达到就等待一定时间,如果在等待的时间内有连接被释放出来,就可以把这个连接分配给等待的用户。如果等待时间超过预定时间,则返回null ,系统对已经分配出去正在使用的连接只做计数,当使用完后再返回给空闲池
数据源与连接池:
数据源是在JDBC 2.0 中引入的一个概念,在JDBC 扩展包中定义了javax.sql.DataSource接口
它负责建立与数据库的连接,在应用中访问数据库是不必编写连接数据库的代码,可以直接从数据源获得   数 据库连接,配置好的数据库连接池也是以数据源的形式存在,这样做可以提高访问数据库的效率。
在传统模式下,数据库连接使用完毕后,需要将其关闭,释放资源,而在连接池中,使用数据源获得数据库连接对象,在调用close()方法时并不会真正地关闭连接,而仅仅是实现了断开应用程序与连接池的联系,即将连接的使用权归还给连接池
 
 
 
JSP 分页显示数据
使用存储过程进行分页,但是需要设置主键和索引提高查询效率,并且可移植性不高;
比较好的分页做法是:每次翻页只从数据库中检索出本页需要的数据。虽然每次翻页都查询数据库,但是查询出的记录很少,网络传输量不大,再配以连接池技术,效率将极大的提高。而在数据库端也有各种成熟的技术用于提高查询速度
 
 
基于方便代码管理和逻辑清晰的考虑 将步骤中有关分页的数据封装到一个page类中
package com.accp.news.entity;
import com.accp.news.dao.*;
public class NewsPage {
    private int total;//总共有X个数据       (数据库查询count(*))
    private int pageCount;//每页M个         (程序设计)
    private int pages;//总共需要Y个页面    (X/M+(X%M==0?0:1))
    private int currentPage;//第N页         (1,2,3,4,5,6,Y)
    public NewsPage() {
        super();
        
        this.total = new NewsDaoSQLServerImpl().getAllNewsCount();
        this.pageCount = 5;
        this.pages = (this.total/this.pageCount+(this.total%this.pageCount==0?0:1));
        this.currentPage = 1;
     }  
      //省略各种get set方法
}  
这个暂时先留着:
 
 
用Commons-FileUpload.jar 包实现文件上传
  实现文件上传,涉及对文件的读写操作,实现起来需要编写大量的代码,并容易引发异常。幸运的是
        目前有很多非常实用的文件上传工具,可以帮助我们实现文件上传的功能,其中应用比较比较多的是Commons-FileUpload组件,使用该组件可以极大的简化开发人员的编码工作量
 
Commons是Apache开放源代码组织的一个java子项目,该项目主要涉及一些开发中常用的模块,如文件上传、命令行处理、数据库连接池等。FileUpload 就是其中的一个用于处理HTTP文件上传的子项目
Commons-FileUpload组件具有以下几个特点:
--》使用简单:Commons-FileUpload组件可以方便地嵌入JSP文件中,在JSP文件中仅编写少量代码即可完成文件上传的功能,十分方便
--》能够全程控制上传内容:使用Command-FileUpload组件提供的对象和操作方法,可以获得全部上传文件的信息,包括文件名称、类型、大小等、方便操作
 
表单的属性设置:
文件上传时,需要在表单属性中添加属性enctype ,该属性用于设置表单提交数据的编码方式。
由于文件传至服务器时与一般的文本类型的编码方式不同,它需要使用multipart/form-data编码方式
 <body>
    <form action="doupload.jsp" method="post" enctype="multipart/form-data">
       <p>姓名:<input type="text" name="user" value="林建辉"></p>
       <div id="imgFileDiv">
            <span id="addFile"><a href="#">批量上传图片</a></span>
            <p>选择图片:<input type="file" name="nfile"></p>
            <p> <input type="submit" name="提交"></p>
       </div>
    </form>
  </body>  
注意:上传文件时,form标签的method属性必须取值为post 不能为get
表单的enctype属性有以下三个值:
application/x-www-form-urlencoded :表示默认值
          作用:用于处理少量文本数据的传递,在想服务器发送大量的文件包含非ASCII字符的文本或二进制数据时效率很低
multipart/form-data:上传二进制数据
   只有使用了multipart/form-data才能完整地传递文件数据,进行上传操作
    text/plain:
       主要用于向服务器传递大量文本数据,比较使用于电子邮件的应用
 
<%@ page import="javax.servlet.jsp.tagext.TryCatchFinally"%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="java.io.*,java.util.*"%>
<%@ page import="org.apache.commons.fileupload.*"%>
<%@ page import="org.apache.commons.fileupload.disk.*"%>
<%@ page import="org.apache.commons.fileupload.servlet.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
    <%
        request.setCharacterEncoding("UTF-8");
          String uploadFileName="";//上传的文件名
          String fieldName="";//表单字段元素的name属性
          //请求信息中的内容是否是multipart类型,然后把请求对象作为参数穿进去
         boolean isMultipart=ServletFileUpload.isMultipartContent(request);
         //上传文件的存储路径(绝对路径
 String uploadFilePath               =request.getSession().getServletContext().getRealPath("upload/");
          if(isMultipart){//因为我要上传二进制文件,所以必须要判断
             FileItemFactory factory=new DiskFileItemFactory();
             ServletFileUpload upload=new ServletFileUpload(factory);
                          upload.setSizeMax(1024*1024)//控制文件上传的大小 这一行可不写
             try{
               //解析form表单中所有的文件
               List<FileItem> items=upload.parseRequest(request);
                 Iterator<FileItem> ite=items.listIterator();
               while(ite.hasNext()){//循环迭代每个文件
                  FileItem item=ite.next();
                  if(item.isFormField()){//判断是否为普通表单字段元素
                     fieldName=item.getFieldName();//表单字段元素的name属性
                     if(fieldName.equals("user")){
                          //输出表单字段的值
                          out.print(item.getString("utf-8")+"上传了文件.<br/>");
                     }
                  }else{
                         //否则为文件表单字段元素
                        fileName=item.getName();
                     if(fileName!=null && !fileName.equals("")){
                         File fullFile=new File(fileName);
                         File saveFile=new File(uploadFilePath,fullFile.getName());
                         item.write(saveFile);
                         uploadFileName=fileName;
                         out.print("上传文件成功后的文件名是:"+uploadFileName);
                     }
                  }
               }
                        
             }catch(Exception e){
                e.printStackTrace();
             }
          }
    %>
</body>
</html>
 
ServletFileUpload 类
public void setSizeMax(long sizeMax)  设置请求消息实体内容的最大允许的字节数
public List parseRequest(HttpServletRequest request)
   解析form表单的每一个字符的数据,返回一个FileItem对象 List集合
public static final boolean isMultipartContext(HttpServletRequest request)
       判断请求信息的内容是否是"multipart/form-data"类型
public void setHeaderEncoding(String encoding)
       设置转换时所使用的字符集编码
 
 
FileItem 接口
FileItem 是一个接口用于封装单个表单字段元素的数据,一个表单字段元素对应一个FileItem对象
在应用程序中使用的是接口的实现类DiskFileItem类,FileItem接口提供的常用方法:
public boolean isFormField()
         判断FileItem对象封装的数据类型 普通表单字段返回true,文件表单字段返回false
public Stirng getName()  
      获得文件上传字段中的文件名,普通表单字段返回null
public String getFiledName()
            返回表单字段的name 属性值
public void write(File file)
           将FileItem对象中的主体内容保存到指定的文件中
public String getString(String encoding)
          将FileItem对象中保存的主体内容以一个字符串的形式返回。
public long getSize() 
         返回单个上传文件的字节数
 
FileItemFactory 接口与实现类
ServletFileUpload 对象的创建需要依赖于FileItemFactory 工厂,将获得的上传文件FileItem对象
 保存至服务器硬盘。FileItemFactory接口的实现类是DiskFileItemFactory
public void setSizeThreshold(int size)-------Size Threshold 门限
                     设置内存缓存区的大小
public void setRepositotyPath(String path)------repository 仓库--贮藏室
                        设置临时文件存放的目录
 
 
 
 
 
 
 
 
JSP +Servlet+javaBean
 
  V------C ------M
 
 
 
 
 
HttpServlet 是一个抽象类  表示一个抽象类
所有自定义的servlet 都会默认继承此抽象类,实现其所有的抽象方法
HttpServlet类之所以是一个抽象类就是因为它有个抽象方法 service()
 
javax.servlet.GenericServlet
定义一个通用的,与协议无关的servlet   (Defines a generic, protocol-independent servlet)  。写在Web上使用的HTTP Servlet,扩展了HttpServlet来代替。
 
GenericServlet类实现了javax.servlet.Servlet  和的javax.servlet.ServletConfig  接口。 GenericServlet类可以由一个servlet可以直接延长,虽然它的扩展协议特定的子类更常见,如HttpServlet。
 
GenericServlet类使得编写servlet更加容易。它提供的生命周期方法的简单版本的init和破坏,并在ServletConfig接口的方法。 GenericServlet类也实现了日志的方法,在ServletContext接口中声明。
 
要编写一个通用的servlet,你只需要重写抽象的服务方法。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
                   Servlet 基础                           
                                            
一:在本章我们将学到如下的内容
 
》HTTP协议原理
 
》服务器端Web编程原理
 
》Servlet与Web容器
 
》Java Web应用程序的组成
 
》Tomcat介绍
 
 
 
一:1.1解析HTTP协议
 
HTTP:超文本传输协议(HyperText Transfer Protocol)
 
HTTP是一种无状态的协议,意思是指在Web浏览器和Web服务器之间不需要建立持久的连接。
 
HTTP是遵循请求/响应(Request/Response)模型的。
 
HTTP处理流程:
 
 
 
 
 
1.1.1建立连接
 
在java底层代码中是这样实现的,只不过浏览器已经帮我们做了!
 
1.1.2 发送请求信息  一旦建立的TCP连接,Web浏览器就会向Web服务器发送请求命令。HTTP协议将请求封装成HTTP请求,他包括请求行,请求头,空行,消息体。
 
1.1.3 回送响应信息
 
1.1.4 关闭连接
 
 
 
1.2 Web服务器的缺陷;
 
只能向客户端提供静态网页内容
增加一个辅助应用生成动态页面 
辅助的在服务器端进行注册,根据参数查找并运行。
 
1.3 服务器端网页编程
 
建动态服务器端内容的过程
–CGI技术
–微软的ASP和ASP.NET技术
–基于Java的Servlet/JSP技术
 
 
1)CGI技术
CGI即通用网关接口(Common Gateway Interface)
最大优点是它可以用Shell、Perl、C、PHP、Python等编写  
但是CGI技术也有缺陷:
每次请求就打开一个CGI进程,严重消耗服务器资源。极大地限制了一个服务器可以支持的并发 CGI用户数量 。
 
2)java的解决法案
 
 
 
    Web容器;
 
负责管理和运行Servlet的容器叫Web容器
容器对Servlet的支持包括
–通信支持
–生命周期管理
–多线程支持
–JSP支持
-处理安全性
 
    Servlet
 
1:Servlet是常规的Java代码。代码中用了一些新的API,但是不涉及新的语法。
 
2:Servlet代码中有我们不熟悉的重要语句。Servlet不属于J2SE,它属于单独的规范。
 
3:Servlet对标准类(HttpServlet)进行了扩展。
 
4:Servlet没有main()方法。
 
 
这章我们主要的目标
 
理解Servlet
 
Servlet的编码和部署
Servlet生命周期
Servlet的配置
Servlet与容器交互 
 
什么是Servlet?
 
 
在JSP技术出现之前,如果想动态生成HTML页面,那就只有在服务器端云行java程序
 
并生成HTML格式的内容 ,Servlet就 是运行在Web服务器或应用服务器上的Java程序
 
Servlet实际上就是按照Servlet规范编写的一个java类,它主要用于处理客户端请求并作
 
出响应
-在Web上创建动态内容的有效而强大的解决方案
-由容器来管理生命周期与Web服务器交互
-由Sun规范了其功能 
 
Servlet的规范组成  
Web应用程序  Servlet和HTTPServlet   过滤器  安全  国际化  
 
 Servlet API 
 
HttpServlet的public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException;
 
            
 
       这是一个Servlet的HTTP-specific方案,它相当于一个分配器,可以根据
 
 
 
请求方法 的类型调用相应的doXxx()方法
 
      
 
当你开发Servlet时,在多数情况下你不必重载这个方法。
 
 
 
 
ServletConfig接口
 
Servlet容器使用ServletConfig对象在Servlet初始化期间向其传递配置信息
       定义
 
       public interface ServletConfig
 
       这个接口定义了一个对象,通过这个对象,Servlet引擎配置一个Servlet并且允许Servlet获得一个有关它的ServletContext接口的说明。每一个ServletConfig对象对应着一个唯一的Servlet。
 
       方法
 
       1、getInitParameter
 
       public String getInitParameter(String name);
 
       这个方法返回一个包含Servlet指定的初始化参数的String。如果这个参数不存在,返加空值。
 
       2、getInitParameterNames
 
       public Enumeration getInitParameterNames();
 
       这个方法返回一个列表String对象,该对象包括Servlet的所有初始化参数名。如果Servlet没有初始化参数,getInitParameterNames返回一个空的列表。
 
       3、getServletContext
 
       public ServletContext getServletContext();
 
       返回这个Servlet的ServletContext对象。
 
 
ServletContext接口
 
 详情请看ServletAPI手册
 
 
 
Servlet生命周期
Servlet不能独立运行,它必须被部署到Servlet容器中,由容器实例化和调用Servlet的方法
 
Servlet容器在Servlet的生命周期内管理Servlet,当Servlet容器启动或者当客户端发送一个请求时,Servlet容器会在内存中查找是否存在该Servlet容器,如果不存在,就创建一个Servlet实例,如果存在该Servlet实例,就直接从内存中取出该实例响应请求
加载和实例化、初始化、处理请求、销毁
Tomcat服务器停止时,destory()方法才被执行
初始化和 销毁通常执行一次,服务可以执行多次。
所有的Servlet必须实现javax.servlet.Servlet接口。这个接口定义了 init();service(ServletRequest req, ServletResponse resp);destory();
 
 
Servlet的编码和部署
 
 
在web.xml中部署servlet:
<servlet>
      <servlet-name>OutputStream</servlet-name>
      <servlet-class>com.cy.OutputStream</servlet-class>
</servlet>
 
映射servlet:
 
<servlet-mapping>
       <servlet-name>OutputStream</servlet-name>
       <url-pattern>/OutputStream</url-pattern>
</servlet-mapping>
 
 
 
servlet配置:
 
为Servlet提供初始化配置信息
配置信息由web.xml声明中的字符串组成
 
eg:
<web-app>
   <!--上下文参数在servlet标签外-->
<context-param>
       <param-name>contextName</param-name>
     <param-value>name</param-value>
 
</context-param>
<servlet>
 
    ....
 
  <init-param>
 
     <param-name>name</param-name>
 
     <param-value>Kitty</param-value>
 
  </init-param>
 
<load-on-startup>2</load-on-startup>//加载顺序排第二
 
</servlet>
 
</web-app>
 
 
 
java中<load-on-startup>含义
    java中的load-on-startup用于表示该servlet是否在servlet容器启动的时候加载。
示例:<load-on-startup>xx</load-on-startup>
其中:如果xx是负数或者其他数值或者没有指定,表示该servlet在被选择时才加载;
      如果xx为正数或者为0,表示在servlet容器启动的时候就加载,而且数值越小,加载的优先级越高!
 
注意:有些初始值需要servlet容器在启动的时候就应该加载到内存中,所以很有必要设置这些初始值在启动的时候就应该加载,这种情况下就可以设置这个servlet的load-on-startup属性
 
 
Servlet在编译的代码之外有初始化参数,当参数改变时,不需要重新编译Servlet  ,每个servlet都有一个与之相联的对象ServletConfig; (在servletConfig对象中包含了servlet的初始化参数信息。)
 
得到指定的参数value:String value= getServletConfig().getInitParameter(“name"); 
 
也可以这么写:String value= this.getInitParameter(“name"); //this可省
 
得到所有的所有的参数value:需要应用一个ServletConfig中的一个方法:getInitParameterNmes():返回一个Enumeration(枚举)对象,里面包含了所有的初始化参数。
 
 
 
Enumeration e = this.getServletConfig().getInitParameterNames();  
        while(e.hasMoreElements()){  
            String name = (String)e.nextElement();  
            String value = this.getServletConfig().getInitParameter(name);  
            System.out.println(name+"="+value);  
        }  
    }  
 获得上下文参数:
String value=this.getServletContext().getInitparameter("contextName");
 
import java.io.IOException;  
import java.io.PrintWriter;  
import java.util.Enumeration;  
  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
/**  
 * 获取Http协议的请求行,请求头  
 * @author Starjuly  
 *  
 */  
public class RequestDemo1 extends HttpServlet {  
  
       
    public void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        System.out.println("请求行的方法:" + request.getMethod());  
        System.out.println("请求行的URI:" + request.getRequestURI());  
        System.out.println("请求行的URL:" + request.getRequestURL());  
        System.out.println("请求行的版本:" + request.getProtocol());  
          
        System.out.println("请求头:"+request.getHeader("User-Agent"));  
        //利用迭代器遍历所有的请求头  
        Enumeration names = request.getHeaderNames();   
        while(names.hasMoreElements()){  
            //获取请求头  
             String  nextElement = (String)names.nextElement();  
             //获取每个请求头的内容  
             String header = request.getHeader(nextElement);   
             System.out.print(nextElement+" : ");  
             System.out.println(header);  
        }  
          
    }  
  
       
    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
  
        doGet(request,response);  
    }  
  
}  
 
ServletContext 应用上下文:
 
属于整个Web应用程序
可以访问到Web应用程序资源的本地输入流
把资源的虚拟路径转换为物理路径
记录事件日志
绑定一个对象在整个Web应用程序中共享
 
初始化web应用程序参数:
 <web-app>
 
 …
 
 <context-param>
 
     <param-name>admin email</param-name>
 
     <param-value>admin@cy.com</param-value>
 
  </context-param>
 
     …
 
</web-app>
 
 
 
在Servlet中共享信息
 
为所有的Servlet设置一个实时变化的参数值
在Web应用程序中共享一个对象
eg:
servletContext.setAttribute("password", "tiger");
 
String password = (String) servletContext.getAttribute("password");
 
虚拟路径转换为物理路径:
 
getResourcePaths(java.lang.String path):返回一个集合,路径必须从Web应用程序的根“/”开始;
 
getResourceAsStream(java.lang.String path):返回一个InputStream对象。当一个资源需要逐字节读取的时候该方法比较适用。
 
getResource(java.lang.String path):返回一个Web资源列表。
 
 
 
Servlet与jsp 的区别:
JSP在本质上就是Servlet,但是两者的创建方式不一样.Servlet完全是JAVA程序代码构成擅长于流程控制和事务处理而通过Servlet
来生成动态网页;JSP由HTML代码和JSP标签构成,可以方便地编写动态网页
因此在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页.在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层.
答案2:
JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
 
 
 
回顾上一章的知识:
Java Servlet是运行在Web服务器或应用服务器上的Java程序
Servlet规范对Servlet功能进行了严格定义
Servlet API与容器进行通讯
Servlet的编码和部署
Servlet需要在容器中进行注册和映射
容器管理Servlet的生命周期
SevletConfig对象为Servlet提供初始化参数
ServletContext对象属于整个Web应用程序
 
本章学习知识:
回顾HTTP请求的处理过程(回顾第一章)
设置HTTP状态码
设置HTTP响应头
设置HTTP消息体
请求重定向和自动刷新页面
 
设置HTTP状态码
 
设置响应状态行:
HTTP状态码:
HTTP状态码:
 
100-199:表示信息性代码,标示客户端应该采取的其他动作,请求正在进行。
 
200-299:表示客户请求成功。
 
300-399:表示用于已经移走的资源文件,指示新的地址。
 
400-499:表示由客户端引发的错误。
 
500-599:表示由服务器端引发的错误
 
servlet设置状态码一般使用HttpServletResponse的setStatus()方法;
设置HTTP响应头
 
HttpServletResponse对象用于操纵响应的HTTP头
目的用于告诉客户端
–发送回来的内容的类型
–有多少内容正被发送
常用的方法:
setContentType(String mimetype);
 
addCookie(Cookie c);
 
发送内容的服务器的类型
 
设置HTTP消息体
 
HttpServletResponse对象负责将信息返回给客户端
 
HttpServletResponse对象只产生一个空的HTTP响应
 
传回自定义的内容需要使用getWriter()或者getOutputStream()方法
 
–传送普通文本
 
–传送二进制内容 
 
 
 
请求重定向和自动刷新页面
 
重定向的原理:(看三张图片):
 
         
 
            
 
          
 
使用sendRedirect(String URL)方法实现重定向,
 
 
 
在指定时间内自动刷新当前页或到一个新的页面
根据时间来控制响应
想在响应中有一个短时间的暂停 
response.setHeader("Refresh", "time; URL=url" );
 
 总结:
请求URL时HTTP发出了多个请求
状态码告诉浏览器发送的内容及格式状态
Servlet API与容器进行通讯
HttpServletResponse定义的常量来避免直接使用整数
在通过PrintWriter对象发送任何内容之前先调用 HttpServletResponse的setStatus()方法
为了让Servlet发挥最大的效能,HttpServletResponse对象用于操纵响应的HTTP头
getWrite()或者getOutputStream()方法传送文本或者二进制内容给客户端
sendRedirect方法实现重定向
HTTP响应头“Refresh”会根据时间来控制响应
 
回顾上一章的知识:
请求网络资源HTTP会发出多个请求并得到响应
设置响应状态行关键是设置状态码
在向客户端输出内容之前要设置状态码和响应头
设置响应头让Servlet发挥最大功能
消息体可以用文本或二进制流方式发送
响应重定向把请求转发给另外一个URL,利用302状态码和Locatoin头,让浏览器处理
可以根据时间来控制响应
 
本章目标:
HTTP请求提交的方法
获取HTTP请求行与请求头
获取表单数据
请求派发和请求范围
 
GET/POST提交方法:
浏览器向Web服务器发送HTTP请求
–用户在网页上点击一个超连接
–用户提交在网页上填写好的表单
–用户在浏览器地址栏中输入URL地址并回车 
默认情况下都是使用HTTP协议的GET方法提交请求
 
GET/POST提交方法区别:
 
何时使用GET/POST方法:
 
1:请求一个静态页面或图形文件时使用GET方法,因为仅仅需要发送文件名;
 
2:发送大数据的时候,使用POST方法;
 
3:上传文件时,使用POST方法;
 
4:发送用户名、密码或其他保密信息的时候使用POST方法;
 
获取HTTP协议请求行:
HttpServletRequest对象的如下方法访问
–getMethod():获取HTTP的请求方法,例如GET、POST等
-getRequestURI():获取请求的URI资源
 
–getRequestURL():获取请求的URL,包含协议名、服务器名或IP、端口号和请求资源但不包括查询字符串参数
–getQueryString():获取请求URL后面的查询字符串
–getProtocol():获取HTTP的协议名和版本号
–getContextPath():获取请求URI资源的上下文路径
–getServletPath():获取Servlet的映射路径
 
获取HTTP协议请求头:
HTTP请求头用于告诉服务器客户端使用什么软件以及客户端想要服务器如何返回请求的信息
HttpServletRequest对象的如下方法访问
–getHeader(name):返回指定的请求头的值
–getHeaders(name) :返回一个Enumeration(枚举)包含请求头中的所有值
–getHeaderNames():特定请求中接受到的所有请求头的名称
–getIntHeader(name):获取特定请求头的值,并将其转化为int类型
–getDateHeader(name):获取特定请求头的值,并将其转化为Date类型  
 
Enumeration enum = request.getHeaderNames();
 
      while (enum.hasMoreElements()) {
 
          String headerName = (String) enum.nextElement();
 
         String headerValue = request.getHeader(headerName);
 
        out.print("<b>"+headerName + "</b>: ");
 
        out.println(headerValue + "<br>");
 
      }
 
 
 
获取请求消息体:
 
消息体可以是普通文本也可以是二进制数据 
HttpServletRequest对象可以使用通用的方法来获取表单数据
 
请求转发和请求方法:
重定向和请求转发之间最大的区别在于,重定向让客户端浏览器来完成,而请求转发是在服务器端做工作。
请求转发:
RequestDispatcher对象可以通过调用ServletRequest对象的方法:getRequestDispatcher(String path);
RequestDispatcher对象提供了两种方法来包含资源以及请求转发到不同的资源:
forward(ServletRequest, ServletResponse):派发请求和响应对象到RequestDispatcher 对象所确定的新资源(Servlet、JSP或者HTML等)
include(ServletRequest, ServletResponse):该方法关键是能包含服务器端的资源 
总结:
HttpServletRequest对象主要用于处理分析请求
默认情况下,使用HTTP协议的GET方法提交请求
HTML表单通过“method”属性使浏览器使用HTTP POST方法
GET/POST方法适用于不同场合
HttpServletRequest对象中最常用的方法是获取请求表单参数
HttpServletRequest对象也可以得到请求中参数的原始字节数据
重定向和请求派发之间最大的区别在于,重定向让客户端浏览器来完成,而请求派发是在服务器端做工作
HttpServletRequest可以把一个对象用名字绑定在请求范围内,并且进行访问和删除
 
状态管理概述
Cookie
Session
URL重写
 
状态管理概述:
HTTP协议使用的是无状态的连接
对容器而言,每一个请求都来自于一个新的客户
这里我们有四种方法来解决这个状态:
a:表单隐藏字段
b:Cookie
c:  Session
d:  URL重写
 
我们就来一一介绍这四种方案:
A:状态管理解决方案-表单隐藏字段
   表单隐藏字段:
<input type="hidden" name="session"  value=""/>
1:对用户在网站上的访问进行会话跟踪。
 
2:为服务器端程序提供预定义的输入。
 
3:存储动态产生的页面上下文信息。  
 
隐藏字段存在一个主要的缺点,即只有每当每个页面都是动态生成的时候才有效。
 
 
 
 
 
B:表单是在生成动态时才有效,那么我们就使用HTTP Cookie来固定的保存在某个地方,需要是读取。
 
 
 
使用HTTP Cookie可以很好的维护和保留用户的状态信息,但是Cookie涉及到一些敏感的隐私问题,一些用户会禁用Cookie,这时我们需要另一个方法来解决
 
 
 
C:URL重写
 
 
 
D:Servlet提供了出色的解决方案,HttpSessionAPI,这种高级接口建立在Cookie和URL重写之上。
 
把客户的状态信息保存在服务器端
Session对象就是服务器为客户端创建并维护的用于存放客户状态数据的对象 
 
 
 
一:Cookie
 
1:Cookie原理:
 
服务器在响应请求时将一些数据以“键-值”对的形式通过响应信息保存在客户端,当浏览器再次访问相同的应用时,会将原先的Cookie通过请求信息带到服务器端。
Cookie cookie = new Cookie("cool", "tiger!");
 
response.addCookie(cookie); 
 
2:在Serlvet中管理Cookie
 
Servlet中提供了如下一系列操作Cookie的API
–Cookie(name, value):构造方法用于创建一个或多个Cookie
–setMaxAge(int lifetime):设置Cookie的过期时间(以秒为单位)。默认值为负值(Cookie将在浏览器关闭时过期)
–getMaxAge():获取Cookie的过期时间。
–getName():获取Cookie的名字
–setValue(String value):指定Cookie的值。
–getValue():获取Cookie的值
-.......
 
3:在Servlet中使用Cookie
要将Cookie发送到客户端,Servlet应该按照下列的操作步骤执行:
–创建一个或多个Cookie,使用构造方法指定Cookie的名字和值
–使用setXXX方法为Cookie设置属性值
–使用HttpServletResponse对象的addCookie()方法将Cookie插入到响应头中
要读取客户端传入的Cookie,Servlet执行下列操作步骤:
–使用HttpServletRequest对象的getCookie方法返回一个Cookie对象数组
–Servlet遍历该数组(调用getName()方法),直到找到与名称相匹配的Cookie值
 
 
 
二:Session
1:Session原理
-服务器可以为客户端创建并维护一个Session对象,用于存放数据。
-在创建Session对象的同时,服务器将会为该 Session对象产生一个唯一编号,这个编号称之为SessionID
-服务器以Cookie的方式将SessionID存放在客户端。
-当浏览器再次访问该服务器时,会将SessionID作为Cookie信息带到服务器,服务器可以通过该SessionID检索到以前的Session对象,并对其进行访问
 
2:Session工作流程
 
3:Session会话跟踪机制
 
用户发送请求
HttpSession session = request.getSession(); //getSession(false)方法使用已经存在的会话,而不必创建新会话
 
服务器的响应
再次发送请求
4:HttpSessoin接口
HttpSession接口常用的一些方法
–setAttribute(java.lang.String, java.lang.Object):在Session对象中用一个名字绑定一个对象。
–getAttribute(java.lang.String):通过名字获取Session对象中保存的对象。
–removeAttribute(java.lang.String):在Session中删除与一个名字对应的对象。
–getCreationTime():返回第一次创建会话的时间。
–getLastAccessedTime():返回容器最后一次得到该会话ID的请求时间。
–setMaxInactiveInterval(int interval):对于会话指定客户请求的最大间隔时间,以秒为单位。-1表示永不过期
–getMaxInactiveInterval(int interval):返回客户请求的最大间隔时间。
–invalidate():会话结束,当前存在在会话中的所有会话属性也会解除绑定。
–getId():此方法返回每个session唯一的标识 
-......
5:会话超时管理
销毁会话可以采用如下三种简单的方式           //浏览器关闭时并不意味着Session对象被删除
–设置会话超时。
–在Session对象上调用invalidate()方法。
–应用结束(崩溃或取消部署)
在web.xml文件中配置    //以分钟为单位
<session-config>
 
       <session-timeout>15</session-timeout>
 
  </session-config> 
 
 6:Session持久化管理
 
三:URL重写
 
Session对象的正常使用要依赖于Cookie
URL地址重写能够取得置于Cookie中的会话,并把会话ID附加到访问应用的各个URL最后
URL重写方法:
 
response.encodeURL()
 
response.encodeRedirectURL(“/lovobook/sucess.html” )
 
URL重写是容器自动完成的,但需要我们对URL进行编码才有效 
 
总结:
 
1 HTTP协议使用的是无状态的连接,连接只针对一个请求/响应
2 状态管理方案:表单隐藏字段、Cookie、Session、URL重写
3 Cookie是Web服务器发送到客户端浏览器并保存的简短文本信息
4 Session对象就是服务器为客户端创建并维护的用于存放客户状态数据的对象
5 用户会禁用Cookie。这时我们可以使用URL地址重写来解决
6 通过HttpServletResponse的addCookie方法将该Cookie信息添加到响应信息中
7 Session对象是某个Servlet调用HttpServletRequest.getSession()这样的语句时才被创建
8 Session对象是保存在服务器端,浏览器关闭时并不意味着Session对象被删除
9 Session只认SessionID不认人
10 应当尽量使用维护时间短的域对象
11 在向客户返回第一个响应时,会同时尝试设置Cookie和URL重写两种做法 
 
 
     
 EL(Expresstion Language)表达式和JSTL(JSP Standard Tag Library)
 
 
 <%
               Map map=new HashMap();
               map.put("one","java");
               request.setAttribute("map", map);//这句话一定要写,要不然EL获取不到
   %>
   学科:    ${map.one}  
 
 
如果map里放的是数字字符串,则在EL表达式的里不能通过" ."操作符来获取值
 
只能通过[ ]操作符来获取值,否则会运行时出错
 
 
 
 
 
 
 
 
 
 
 
 
 
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>  
 
<c:set   target="${provinceList[0]}" property="provinceName" value="林建辉" var="u" scope="application" ></c:set>
 <c:out value="${provinceList[0].provinceName }" default="noUname" escapeXml="true"></c:out>
//通过变量名获取值,如果变量名为空,则显示默认值
 <c:out value="${u}" default="noUname" escapeXml="true"></c:out>  
 
Empty 操作符:
 
是一个前缀操作符,用于检测一个值是否为null或empty
 
例如:如果变量a不存在或者变量a 的值为空,则${empty a }  为true  
检查非空用${ not empty a }或${ !empty a }  
 
作用域的访问对象:当使用EL表达式访问某个对象时,应该指定查找范围,如
 
${requestScope.employee}
 
如果不指定就会按照page---》request---》session--》application
 
<c:set var="isLogin" value="${!empty sessionScope.user }"></c:set>
  <c:if test="${isLogin }">
    //如果为真执行里面的内容
  </c:if>  
 
 
相当于if --else 
 <c:choose >
    <c:when test="${!empty isLogin }">
    
    </c:when>
 
    <c:otherwise>
    
    </c:otherwise>
  </c:choose>  
 
使用EL遍历Map集合
 
<%
    Map<String ,String> map=new HashMap<String ,String>();
    map.put("sssss","dddd");
    map.put("qqqqq","wwwwwww");
    map.put("aaaaaa","bbbbbbb");
    
         request.setAttribute("map", map);
  %>
    <%--一定要写${ } --%>
  <c:forEach var="entry" items="${map}">
        <%--充分说明map里有key属性和 value属性 --%>
      ${entry.key }---${entry.value}<br/>
  
  </c:forEach>  
 
 
 
 
 
 
 
 
如果:定义了var属性,则target属性会被禁止,包括property属性,而且JavaBean对象及property属性
不存在时不会报错
 
<c:set var="aa" value="2" target="javaBean" scope="request" property="name"></c:set>
  <c:out value="${javaBean.name }"></c:out>  
 
当没有指定var 变量时,target属性和scope属性不能同时存在,因为此时target对象是一个JavaBean对象  使用${requestScope.user},如果再定义scope属性的话会发生冲突

posted on 2020-05-12 18:33  红宝儿  阅读(181)  评论(0编辑  收藏  举报