Java教程

第二次作业

本文主要是介绍第二次作业,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

第四章深入Servlet技术


一、Servlet概述:
servlet是由sun公司提供的一门用于开发动态web资源的技术。sun公司在其API中提供了一个servlet接口,用户若想发一个web资源(即就是开发一个java程序向浏览器输出数据),需要完成以下的两个步骤:
  1、编写一个java类,实现servlet接口。
  2、把开发好的java类部署到web服务器中。按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为servlet。

Servlet是一种基于java技术的web组件,是一种基于java的且与第三方平台无关的类。通常,它可以被web服务器编译、加载和运行,最后生成动态的资源内容。

二、编写第一个Servlet:

1、编写java类,继承HttpServlet类
2、重新构建doGet方法和doPost方法
3、在web.xml文件中进行配置
4、servlet程序交给tomcat服务器运行

 

三、HttpServeltRequest获取请求行和请求头


获取请求行相关信息的相关方法:
1.getMethod()方法:返回请求方法,请求方法通常是GET或POST,也有可能是HEAD、 PUT或DELETE
2.getRequestURI()方法:返回URI
3.getRemoteAddr()方法:获取请求客户端的IP地址
4.getRemoteport()方法:获取请求客户端的端口号
5.getLocalAddr():获取服务器当前接收的IP地址
6.getContextPath():用于获取URL中属于web应用程序的路径
7.getProtocol():用于获取请求行中的协议名和版本

        //获取请求行
       System.out.println("接收到get请求");
       System.out.println("请求方式:"+request.getMethod());
        System.out.println("URI:"+request.getRequestURI());
        System.out.println("发出请求客户端IP地址:"+request.getRemoteAddr());
        System.out.println("服务点接收请求的IP地址:"+request.getLocalAddr());
        System.out.println("访问客户端的端口号:"+request.getRemotePort());
        System.out.println("web应用路径:"+request.getContextPath());
        System.out.println("http协议和版本:"+request.getProtocol());

四、获取请求头的相关方法:
1.getHeader(String name):该方法返回一个 Enumeration 集合对象,该集合对象由请求消息中出现的某个指定名称的所有头字段值组成。在多数情况下,一个头字段名在请求消息中只出现一次,但有时可能会出现多次


2.getIntHeader(String name):该方法用于获取指定名称的头字段,并且将其值转为 int 类型。需要注意的是,如果指定名称的头字段不存在,则返回值为 -1;如果获取到的头字段的值不能转为 int 类型,则将发生 NumberFormatException 异常


3.getDateHeaders(String name):该方法用于获取指定头字段的值,并将其按 GMT 时间格式转换为一个代表日期/时间的长整数,该长整数是自 1970 年 1 月 1 日 0 时 0 分 0 秒算起的以毫秒为单位的时间值


4.getHeaderNames():获取所有包含请求头字段Enumberation

5.getCharacterEncoding():该方法用于返回请求消息的实体部分的字符集编码,通常是从 Content-Type 头字段中进行提取,结果为 String 类型

        //获取请求头
       Enumeration<String> headerNames = request.getHeaderNames();
       while (headerNames.hasMoreElements()){
           String element = headerNames.nextElement();
          System.out.println(element+":"+request.getHeader(element));
        }

五、获取请求参数:
1.getParameter(String name):该方法用于获取某个指定名称的参数值,如果请求消息中没有包含指定名称的参数,getParameter()方法返回null;如果指定名称的参数存在但没有设置值,则返回一个空串;如果请求消息中包含有多个该指定名称的参数,getParameter()方法返回第一个出现的参数值
2.getParameterNames():该方法用于返回一个包含请求消息中所有参数名的Enumeration对象,在此基础上,可以对请求消息中的所有参数进行遍历处理
3.getParameterMap():个体Parameter Map()方法用于将请求消息中的所有参数名和值装入进一个Map对象中返回

​	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("用户名:" + username);
        System.out.println("密码:" + password);



​
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
<center>


    <h2>发起HTTP get请求</h2>
    <form action="hi" method="get">
        <p>账号: <input type="text" name="name" /></p>
        <p>密码: <input type="text" name="passWord" /></p>
        <input type="submit" value="提交" />
    </form>




</center>
</html>

六、Response对象发送响应行和响应头和响应消息体:
发送响应行:
1.setStatus(int status):当Servlet向客户端回送响应消息时,需要设置一个状态码,该方法用于设置HTTP响应消息的状态码,并生成响应状态行,由于响应状态行中的描述直接和状态码相关,因此只需要设置该方法,就可以发送一个响应行,正常情况下,web服务器会默认发送一个200的状态码
2.sendError(int code):该方法用于发送表示错误信息的状态码,例如404找不到访问资源,还有一种重载形式sendError(int code,String errorMessage),errorMessage可以以文本形式显示在客户端浏览器


发送响应头:
1.addHeader(String name,String value):用于设置HTTP协议的响应头字段,其中Name时响应头字段,Value是响应字段的值
2.setHeader(String name,String value):同上,唯一区别在于可以重复添加同名的响应头字段,会覆盖之前添加的同名的响应头
3.setContentLength():设置HTTP响应消息的内容大小,单位是字节
4.setContentType()L设置Servlet输出内容的类型
5.setCharacterEncoding(String charset)


发送响应消息体:
1.getOutputStream()方法:获取字节流输出对象为ServletOutputStream类型,
2.getWrite()方法:获得的字符输出流对象是PrintWriter类型由于它可以直接输出文本类型,因此需要输出网页文档,需要使用这个方法

       String result="恭喜您登录成功";
       ServletOutputStream outputStream = response.getOutputStream();
       outputStream.write(result.getBytes());
       response.setContentType("text/html;charset=utf-8");
       PrintWriter writer = response.getWriter();
       writer.write(result);
       request.setAttribute("name","123");
       request.getRequestDispatcher("/index.jsp").forward(request,response);

七、Servlet的生命周期

 

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

init(ServletConfig)方法:init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

service() 方法:是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

destory()方法:只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。


HttpServlet方法接口:javax.servlet.http:
继承自Servlet接口,并重新实现了service方法,根据不同请求方式调用不同的处理方法。
service(HttpServletRequest,HttpServletResponse)方法,获取请求方式,分别调用deGet(),或者doPost()方法

当服务器关闭或者项目被移出服务器,destory方法会执行,生命周期结束

架构图:

代码块:

package net.zixue.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "LifeServlet",urlPatterns = "/life")
public class LifeServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("init 被执行了");
        super.init();
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("service 被执行了");
        super.service(req, resp);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("do get被执行了");
    }

    @Override
    public void destroy() {
        System.out.println("destroy被执行了");
        super.destroy();
    }
}

八、ServletConfig对象
ServletConfig对象是它所对应的Servlet对象的相关配置信息
特点:

每一个servlet对象都有一个ServletConfig对象和它相对应
ServletConfig对象在多个Servlet对象之间是不能共享的
常见的ServletConfig对象的方法:
1、getInitParameter(String name):获取指定参数名的初始化参数
2、getInitParameterNames():返回servlet初始化参数的所有名称
3、getServletContext():返回一个Servlet的上下文对象
4、getServletName():获取Servlet的name配置值
web.xml页面展示

​​<servlet>
     <servlet-name>HelloWorld</servlet-name>
     <servlet-class>com.cn.test</servlet-class>
     <!--配置Servlet的初始化参数信息,并且该节点必须在load-on-startup节点之前-->
     <init-param>
     <!--初始化参数名-->
     <param-name>user</param-name>
     <!--初始化参数值-->
     <param-value>root</param-value>
     </init-param>

     <init-param>
     <param-name>password</param-name>
     <param-value>123456</param-value>
     </init-param>

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

九、ServletContext-获取项目初始值
ServletContext定义
即Servlet上下文环境,该对象表示当前web应用环境信息
获取ServletContext对象

1、通过ServletConfig的getServletContext()方法可以得到ServletContext对象
2、HttpServelt中直接通过this.getServletConext()获取
域对象
域对象就是在不同资源之前来共享数据,保存数据,获取数据,ServletContext对象通常称为Context域对象。ServletContext是我们学习的第一个域对象

使用SevletContext获取整个项目web初始化参数

   <context-param>
    <param-name>encoding</param-name>
    <param-value>utf-8</param-value>
</context-param>

●String getIni tParameter (String name) ;根据名称获取初始化参数

●Enumeration get Ini tParameterNames O) ;获取所有初始化的参数名称

2.使用ServletContext在多个Servlet中共享数据

●void setAttribute(String name, Object object) ;存放数据

●Object getAttribute(String name) ;获取数据

package zyt.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ServletTest3",urlPatterns = "/test3")
public class ServletTest3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String encoding=this.getServletContext().getInitParameter("encoding");
        System.out.println("encoding="+encoding);
    }
}

十、ServletContext对象——在多个sevlet之间共享数据 

Enumeration getAtributeNames():返迥-个Enumeration对象,该对象包含了所有存放在ServletContext中的所有域属性名

Object getAttibute(String name):根据参数指定的属性名返回一一个与之匹配的域属性值

void removeAttribute(String name):根据指定的域属性名,从ServletContex中删除匹配的域属性

void stAtribute(String name,Object obj):设置ServletContext的域属性,其中name是域属性名,obj是域属性值

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

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext context=this.getServletContext();
		//通过setAttribute()方法设置属性值
		context.setAttribute("data", "this servlet save data");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doGet(request, response);
	}
	//浏览器测试网址 http://localhost:8080/chapter03/TestServlet04
}



十一、ServletContext——读取项目的资源文件

package net.zixue.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

@WebServlet(name = "ServletTest4",urlPatterns = "/test4")
public class ServletTest4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/db.properties");//读取文件的路径,返回文件流
        Properties properties = new Properties();
        properties.load(resourceAsStream);
       String name = properties.getProperty("name");
       String pass =  properties.getProperty("passWord");
       String url = properties.getProperty("url");
        System.out.println(url);
        System.out.println(pass);
        System.out.println(name);
    }
}

 十二、请求转发

在Servlet中请求转发是大量要使用的,因为当我们访问一一个Servlet的时候通常会执行一些后台的业务逻辑,然后跳转到一个结果页面,那么跳转到结果页面的这个过程就是请求转发,举个例子我们做登录的功能,我们填写用户名密码然后提交到一个负责登录的Servlet, Servlet 为我们做用户名和密码的校验,如果我们都正确的话,我们就要跳转到登录的提示页面,如果错误就要跳转到登录失败的页面。Request的请求转发也可以叫做服务器端的跳转,虽然有页面的跳转但是我们会发现地址栏是不会有变化的。

请求转发的相关方法:
RequestDispatcher对象,可以通过request.getRequestDisptcher()方法获取调用这个对象的forward方法就可以实现请求转发
转发过程中携带数据:
request本身也是一个域对象,request可以携带数据传递给其他web资源
setAttribute方法:
getAttriubute 方法:
removeAttribute方法:
getAttributeNames方法:
重定向:
重定向是根据服务器返回的状态码来实现的。客户端浏览器在请求服务器的时候,服务端会返回一个状态码,服务器通过HttpServletResponse的setStatus(int status)方法来设置状态码。如果服务器这个时候返回的状态码是301或者是302,则浏览器就会到新的网址重新请求该资源。服务的响应中会带着这个新资源的地址。

请求转发和重定向的区别:

 1.可以理解为是客户端行为,客户端发起一次请求,服务器端给出一次响应,但这个响应包含下一次客户端需要访问的服务器端处理程序的地址,客户端再次发起请求,将会得到处理结果,也就意味...

2.使用当前后两个页面有数据传递时,例如查询了数据需要在页面显示时,用请求转发 当没有数据传递,例如做了更新操作跳转到其他页面,就用重定向。

十三、网页自动刷新

在遇到页面乱码问题时的解决办法:
在方法体内插入这段话即可解决乱码问题

response.setContentType("text/html;charset=utf-8");
package net.zixue.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "RefreshServlet",urlPatterns = "/refresh")
public class RefreshServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String message="<meta http-equiv='refresh' content='3;url=/hello/home.html'>3秒后会自动跳回首页</meta>";
        request.setAttribute("message",message);
        request.getRequestDispatcher("/index.jsp").forward(request,response);
    }



    private void RefreshDemol(HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        response.setHeader("refresh","3;url='/hello/home.html");
        response.getWriter().print("3秒钟自动刷新");
    }
}

十四、Servlet线程安全

当多个客户端并发访问一个Servlet时,web服务器会为每一个客户端的访问创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内部如果访问了同一个资源的话,就可能引发线程安全问题

package net.zixue.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ThreadServlet",urlPatterns = "/thread")
public class ThreadServlet extends HttpServlet {
    int i=0;
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        synchronized (this)
        {
            i++;//第一次访问i已经是1,第二次访问i=2
            try{
                Thread.sleep(5*1000);
            }catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(i+"");
        }

    }
}

 

这篇关于第二次作业的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!