JavaEE学习笔记Day2

JavaEE学习笔记day2

理解Servlet的编写和访问过程
掌握Servlet父子类之间的继承关系
理解Servlet处理、解析请求以及返回响应的过程
Servlet页面跳转

Servlet的编写和访问过程

servlet的运行过程

servlet程序是由web服务器调用,web服务器收到客户端的发起的http访问请求后:

  1. HTTP服务器(Apache)收到HTTP请求以后,转发给Web容器(Tomcat),此时Web容器会解析HTTP请求的内容,web容器通过请求的URL来选择需要用哪个Servlet来处理请求(这个就是web.xml中配置的或者@webServlet注解的作用了)
  2. web服务器首先检查是否已经装载并创建了该servlet的实例对象。如果是,则执行第5步,否则执行第3步
  3. 装载并创建给servlet的一个实例对象
  4. 调用servlet实例对象的init()方法。
  5. 创建一个用于封装HTTP请求的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和和响应对象作为参数传递出去。
  6. web应用程序被停止或重启之前Servlet引擎将卸载Servlet,并在卸载之前的调用Servlet的destory()方法。

在整个servlet程序中最重要的是Servelt接口,在此接口下定义了一个GenericServlet的子类,但一般不会直接继承此类,而是根据所使用的协议选项GenericServlet的子类继承。(后面会介绍几个servlet的区别)

例如:采用HTTP协议处理,一般而言需要使用HTTP协议操作,用户自定义的Servlet类要继承HttpServlet类。

开发一个可以处理Http请求的Servlet类,则肯定需要继承HttpServlet类,该类提供了不同的方法用于响应客户端请求,常见的方法有:

  1. doGet(HttpServletRequest req, HttpServletResponse resp)
  2. doPost(HttpServletRequest req, HttpServletResponse resp)
  3. service(HttpServletRequest req, HttpServletResponse resp)

在自定义的Servlet类中,根据实际需要重写HttpServlet类中提供的方法,Servlet程序本身也是按照请求响应的方式进行的,所以在方法中定义了两个参数,即HttpServletRequestHttpServletResponse ,用来接收和回应用户的请求。

servlet的编写

  1. 实现Servlet接口,然后实现接口中的五个方法
    1. init(ServletConfig parm1) //该函数用于初始化servlet,类似于类的构造函数,该函数只会被调用一次
    2. getServletConfig()
    3. service(ServletRequest req, ServletResponse res) //这个函数用于处理业务逻辑
      //当用户每访问servlet时,都会调用
      //req:用于获得客户端(浏览器)信息
      //res:用于向客户端(浏览器)返回信息
    4. getServletInfo()
    5. destroy() //销毁,释放内存,三种方式会触发destroy
      //1. reload该servlet(webApps) 2. 关闭tomcat 3.关机
  2. 继承GenericServlet,只需要实现一个方法:service
  3. 继承HttpServlet,复写doGet和doPost方法

Servlet父子类之间的继承关系

三种访问方式的区别

  • 可以看到Servlet接口是定义在javax.servlet包中,该接口定义了5个方法。
    • init() :在Servlet实例化之后,Servlet容器会调用init()方法,来初始化该对象,主要是为了让Servlet对象在处理客户请求之前可以完成一些初始化工作,比如:建立数据库的连接,获取配置信息。
    • service():容器调用service()方法来处理客户端的请求。
    • destroy():当容器检测到一个Servlet对象应该从服务器中被移除的时候,容器会调用该对象的destroy方法,以便让Servlet对象可以释放它所使用的资源,保存数据到持久化存储设备中,例如:将内存中的数据保存到数据库中,关闭数据库的连接。
  • GenericServlet
    直接通过实现Servlet接口来编写一个Servlet类,就需要实现Servlet接口中定义的5种方法,为了简化Servlet的编写,在javax.servlet包中,给我们提供了一个抽象的类GenericServlet,它提供了除service()方法外的其他4种方法的简单实现。GenericServlet类定义了一个通用的,不依赖具体协议的Servlet
  • HttpServlet 由于大多数网络应用中,都是浏览器通过HTTP协议去访问服务器资源,而通常编写的Servlet也主要是应用于HTTP协议的请求和响应,为了快速开发应用于HTTP协议的Servlet,Sun公司在javax.servlet.http包中给我们提供了一个抽象的类HttpServlet,他继承自GenericServlet类,用于创建适合Web站点的HTTP Servlet。
    比如,doPost() doGet()这些方法,从request解析请求信息开始,将根据http协议的格式进行解析,分发到不同的请求方法处理中,doPost() doGet()也肯定是被service方法调用的。

Servlet中的请求与响应

get请求和post请求的异同

  • 生成方式:
    • get方式有四种: 1)直接在URL地址栏中输入URL。2)网页中的超链接。3)form中method为get。4)form中method为空时,默认是get提交。
    • post方式:form中method属性为post。
  • 数据传送方式
    • get方式:表单数据存放在URL地址后面。所有get方式提交时HTTP中没有消息体。表单数据存放在URL地址后面。所有get方式提交时HTTP中没有消息体。
    • post方式:表单数据存放在HTTP协议的消息体中以实体的方式传送到服务器。表单数据存放在HTTP协议的消息体中以实体的方式传送到服务器。
  • 服务器获取数据方式
    • GET方式:服务器采用request.QueryString来获取变量的。
    • POST方式:服务器采用request.Form来获取数据。
  • 传送的数据量
    • GET方式:数据量长度有限制,一般不超过2kb。因为是参数传递,且在地址栏中,故数据量有限制。
    • POST方式:适合大规模的数据传送。因为是以实体的方式传送的。
  • 安全性
    • GET方式:安全性差。因为是直接将数据显示在地址栏中,浏览器有缓冲,可记录用户信息。所以安全性低。
    • POST方式:安全性高。因为post方式提交数据时是采用的HTTP post机制,是将表单中的字段与值放置在HTTP HEADER内一起传送到ACTION所指的URL中,用户是看不见的。

servlet请求处理过程

  1. Web Client 向Servlet容器(Tomcat)发出Http请求;
  2. Servlet容器接收Web Client的请求;
  3. Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中;
  4. Servlet容器创建一个HttpResponse对象;
  5. Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象
  6. 为参数传给 HttpServlet对象;
  7. HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息;
  8. HttpServlet调用HttpResponse对象的有关方法,生成响应数据;
  9. Servlet容器把HttpServlet的响应结果传给Web Client;

servlet处理请求

处理get请求

  • HelloForm servlet代码(只修改doGet方法其他不需要动):

public class HelloForm extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
//      response.getWriter().append("Served at: ").append(request.getContextPath());
        
        // 设置响应内容类型
                response.setContentType("text/html;charset=UTF-8");

                PrintWriter out = response.getWriter();
                String title = "使用 GET 方法读取表单数据";
                // 处理中文
                String name =new String(request.getParameter("name").getBytes("ISO8859-1"),"UTF-8");
                String docType = " \n";
                out.println(docType +
                    "\n" +
                    "" + title + "\n" +
                    "\n" +
                    "

" + title + "

\n" + "
    \n" + "
  • 站点名:" + name + "\n" + "
  • 网址:" + request.getParameter("url") + "\n" + "
\n" + ""); } }
  • 浏览器输入 http://localhost:8080/test/helloform?name=testdoGet&url=localhost
  • servlet获取name和url参数并展示

使用表单的 POST 方法实例

  • HelloPostForm servlet代码(只展示doGet和都Post方法其他不需要动):
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        // 设置响应内容类型
                response.setContentType("text/html;charset=UTF-8");

                PrintWriter out = response.getWriter();
                String title = "使用 POST 方法读取表单数据";
                // 处理中文
                String name =new String(request.getParameter("name").getBytes("ISO8859-1"),"UTF-8");
                String docType = " \n";
                out.println(docType +
                    "\n" +
                    "" + title + "\n" +
                    "\n" +
                    "

" + title + "

\n" + "
    \n" + "
  • 站点名:" + name + "\n" + "
  • 网址:" + request.getParameter("url") + "\n" + "
\n" + ""); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); }
  • 在WebContent下创建post.html代码如下:




post


    
网址名:
网址:
  • 运行post。html并输入点击提交可观察到 servlet处理结果;

HttpServletResponse 响应

  • getWriter()方法,返回的是一个输出流
  • response.setContentType("text/html");
  • 编码:response.setCharacterEncoding("UTF-8");

form表单提交到servlet的两种方法(action= “”)

  1. 相对路径

    1. action="servlet/helloform"输入web中配置的相对路径 (注意:开头没有/)
      JavaEE学习笔记Day2_第1张图片
      image
    2. action="HelloForm"输入servlet中注解的相对路径 (注意:开头没有/)
      JavaEE学习笔记Day2_第2张图片
      image
  2. 绝对路径 :action="test/servlet/helloform" 即:/项目名/相对路径

Servlet中请求数据的传递、请求转发与页面跳转

request的转向

  • RequestDispatcher.forward()方法:

    • forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。

    • 服务方(如:servlet)将请求转发到同一个WEB应用程序中另一个Servlet(或:JSP)--第三方 进行处理(该过程浏览器方-客户方并不知道),让这个第三方直接将结果返回给浏览器方

    • 通常在servlet中使用的代码是:
      request.getRequestDispatcher(跳转页面的Url).foward(request,response);

  • 有三种方法可以得到Request Dispatcher对象。

    • javax.servlet.ServletRequest的getRequestDispatcher(String path)方法;
      其中path可以是相对路径,但不能越出当前Servlet上下文。如果path以“/”开头,则解析为相对于当前上下文的根。

    • javax.servlet.ServletContext的getRequestDispatcher(String path)方法,其中path必须以“/”开头,路径相对于当前的Servlet上下文。
      可以调用ServletContext的getContext(String uripath)得到另一个Servlet上下文,并可以转向到外部上下文的一个服务器资源链接。

    • 使用javax.servlet. ServletContext的getNamedDispatcher(String name)得到名为name的一个Web资源,包括Servlet和JSP页面。这个资源的名字在Web应用部署描述文件web.xml中指定。

使用:
下面是一个应用的配置文件web.xml:

其中定义了两个Servlet,名字分别为FirstServlet和SecondServlet,对应的类分别为org.javaresearch. redirecttest.ServletOne和org. javaresearch.redirecttest.ServletTwo。可以在浏览器中通过类似于下面的链接访问:
http://localhost:8080/servlet/firstservlet/

使用1中方法,例如在firstservlet可以写入下面的代码:
RequestDispatcher rd = request.getRequestDispatcher("secondservlet");
rd.forward(request, response);
此时控制权将转向到第二个Servlet了。

使用2中的方法,可以从Servlet Context中得到RequestDispatcher代码如下:

RequestDispatcher rd = getServletContext().getRequest
Dispatcher("/servlet/secondservlet");
rd.forward(request, response);

使用3中的方法,从上面的web. xml配置文件可以看到定义了两个Servlet,名字分别为FirstServlet和SecondServlet,所以可以得到命名的Dispatcher:
RequestDispatcher rd = getServletContext().getNamedDispatcher("SecondServlet");
rd.forward(request, response);
这样也可以重定向到SecondServlet了。

  • sendRedirect()方法:
    • response.sendRedirect(跳转页面URL)

就是服务端根据逻辑,发送一个状态码(Location ,状态码320),告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。

服务方(如:servlet)直接将目标URL发回浏览器,让浏览器自己自动重新向目标URL发出HTTP请求。

重定向是作为不同请求来看待的。

  • 区别比较:
JavaEE学习笔记Day2_第3张图片
image
JavaEE学习笔记Day2_第4张图片
image

RequestDispatcher.forward()方法和HttpServletResponse.sendRedirect()方法的区别是:
前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。
所以,前者更加高效,在前者可以满足需要时,尽量使用Request Dispatcher.forward()方法,并且,这样也有助于隐藏实际的链接。
在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用HttpServletResponse.sendRequest()方法。

servlet数据传递

静态变量
HttpServletResponse的sendRedirect()方法
HttpServletRequest的getRequestDispatch()方法
HttpServletRequest的getSession()方法
HttpServletRequest的setAttribute()方法

  • 静态变量
    通过建立一个数据类来进行传递。

案例:

public class MyData{

    public static String data; //通过使用该类来实现数据传递

} 
  • HttpServletResponse的sendRedirect()方法
    基本语法:
    response.sendRedirect("/Web应用名/资源名?uname="+username+"&pwd="+password);
    response.sendRedirect(“servlet的地址?参数名=参数值&参数名=参数值...”);

  • HttpServletRequest的getRequestDispatch()方法
    getRequestDispatch()方法是使WEB服务器从当前Servlet转发到当前应用下的另一个Servlet。
    基本语法:
    request.getRequestDispatcher(资源地址).forward(request,response);

  • HttpServletRequest的getSession()方法
    基本语法:
    1、放入session:request.getSession.setAttribute("loginUser",username);
    2、取出session:request.getSession.getAttribute("loginUser");
    PS:该方法可以传递对象

你可能感兴趣的:(JavaEE学习笔记Day2)