servlet文件打开白屏无代码_Servlet

d33bfffde442e7a8b29503b67a770466.png

Servlet概述

1 什么是servlet

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容
ervlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
Servlet编程需要使用到javax.servlet  和 javax.servlet.http两个包下面的类和接口,在所有的类和接口中,javax.servlet.servlet 接口最为重要。所有的servlet程序都必须实现该接口或者继承实现了该接口的类。javax.servlet.ServletConfig;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;
javax.servlet.http.HttpSession;
javax.servlet.http.Cookie;

2 Servlet的基本使用

  1. 在src创建package
  2. 选中刚刚创建的包,右键-->New-->Servlet
  3. 第一个Servlet代码如下:
    /**
    *第一个Servlet程序
    */
    @WebServlet("/HelloServlet")
    public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
    * @see 构造函数
    */
    public HelloServlet() {
    super();
    // TODO Auto-generated constructor stub
    }

    /**
    * @see 处理Get请求
    */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 响应内容到浏览器
    response.getWriter().print("Hello Word");;
    }

    /**
    * @see 处理Post请求
    */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
    }

    }
  4. 发布右键-->Run As-->Run On Server
  5. 浏览器输入网址访问:http://localhost:8080/项目名称/HelloServlet

5.3 常见错误解决方法

HTTP Status 404   找不到
解决方法:查看Tomcat的webapps目录下找到当前项目在WEB-INF下的classes内能否找到刚刚的class文件
如果有,重新启动Tomcat
如果没有,在Eclipse中选择Project-->clean让Eclipse清空缓存并重新构建项目,再次运行

5.4 HTTP协议

5.4.1 什么是HTTP协议

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议,是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式
HTTP协议的主要特点如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

5.4.2 Http协议的通信

HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤:
1、 建立TCP连接
在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更低层协议的连接。因此,首先要建立TCP连接,一般TCP连接的端口号是80
2、 浏览器向Web服务器发送请求命令
一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令
例如:GET/sample/hello.html HTTP/1.1
3、 浏览器发送请求头信息
浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。
4、 Web服务器应答
客户机向服务器发出请求后,服务器会客户机回送应答,
HTTP/1.1 200 OK
应答的第一部分是协议的版本号和应答状态码
5、 Web服务器发送应答头信息
正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。
6、 Web服务器向浏览器发送数据
Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据
7、 Web服务器关闭TCP连接
一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码
Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽

5.4.3 数据格式

HTTP请求格式

当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息,HTTP请求信息由3部分组成:
l 请求方法URI协议/版本
l 请求头(Request Header)
l 请求正文
下面是一个HTTP请求的例子:
GET/hello HTTP/1.1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Language:zh-CN,zh;q=0.8,en-GB;q=0.6,en;q=0.4
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Accept-Encoding:gzip, deflate, br
 
name=zhangsan
1、请求方法URI协议/版本
请求的第一行是“方法URL议/版本”:GET/hello HTTP/1.1
以上代码中“GET”代表请求方法,“/hello”表示URI,“HTTP/1.1代表协议和协议的版本。
根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。
URL完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“/”开头,最后,协议版本声明了通信过程中使用HTTP的版本。
2、请求头(Request Header)
请求头包含许多有关的客户端环境和请求正文的有用信息。例如,请求头可以声明浏览器所用的语言,请求正文的长度等。
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Language:zh-CN,zh;q=0.8,en-GB;q=0.6,en;q=0.4
Connection:Keep-Alive
Host:localhost
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36
Accept-Encoding:gzip, deflate, br
3、请求正文
请求头和请求正文之间是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。请求正文中可以包含客户提交的查询字符串信息:
name=zhangsan

第六章 Servlet使用

6.1 Servlet核心接口和类

Servlet接口
在ServletAPI中最重要的是Servlet接口,所有Servlet都会直接或间接的与该接口发生联系,或是直接实现该接口,或间接继承自实现了该接口的类。
该接口包括以下五个方法:
​
init(ServletConfig config)
ServletConfig getServletConfig()
service(ServletRequest req,ServletResponse res)
String getServletInfo()
destroy( )
GenericServlet抽象类
它对Servlet接口中的部分方法(init和destroy)添加了实现,使得开发时只需要考虑针对service方法的业务实现即可。
HttpServlet类
是继承GenericServlet的基础上进一步的扩展,
扩展方法:
public voidinit(ServletConfig config),
public void init()。他们有如下的关系: init(ServletConfig config)方法由tomcat自动调用,它读取web工程下的web.xml,将读取的信息打包传给此参数,此方法的参数同时将接收的信息传递给GenericServlet类中的成员变量config,同时调用init()。以后程序员想重写init方法可以选择init(ServletConfig config)或者init(),但是选择init(ServletConfig config)势必会覆盖此方法已实现的内容,没有为config变量赋值,此后若是调用getServletConfig()方法返回config时会产生空指针异常的,所以想重写init(ServletConfig config)方法,必须在方法体中第一句写上 super.init(config),为了防止程序员忘记重写super.init(config)方法sun公司自动为用户生成一个public void init()的方法

6.2 Servlet的三种创建方式

Servlet的第一种创建方式:继承HttpServlet

/**
 * Servlet implementation class HelloServlet
 * 演示Servlet的第一种创建方式,继承HttpServlet.也是开发中推荐的
 * 
 */
@WebServlet("/hs1")
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
​
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        response.getWriter().print("我是Servlet创建的第一种方式");
    }
    /**
     * @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);
    }
}

Servlet创建的第二种方式:实现接口Servlet

/**
 * Servlet创建的第二种方式:实现接口Servlet
 * */
@WebServlet("/hs2")
public class HelloServlet2 implements Servlet{
​
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }
​
    @Override
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return null;
    }
​
    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }
​
    @Override
    public void init(ServletConfig arg0) throws ServletException {
        // TODO Auto-generated method stub  
    }
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("OK");
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().println("我是第二种创建方式");
    }
}

Servlet的第三种创建方式:继承GenericServlet类

/**
 * Servlet的第三种创建方式:继承GenericServlet类*/
@WebServlet(value="/hs3")
public class HelloServlet3 extends GenericServlet{
​
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("OK");
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().println("我是第三种创建方式");
    }
}

6.3 Servlet的2种配置方式

第一种注解式配置 Servlet3.0及以后 :

/**
 * Servlet implementation class HelloServlet
 * 演示Servlet注解式配置
 */
@WebServlet(value="/hello",loadOnStartup=1)
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        response.getWriter().print("OK");
    }
    /**
     * @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);
    }
}

第二种web.xml配置 Servlet所有版本都支持:

/**
 * Servlet implementation class HelloServlet
 * 演示Servlet的web.xml配置
 */
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
​
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        response.getWriter().print("OK");
    }
    /**
     * @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);
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>Web_Day11</display-name>
  <!--Servlet的第二种配置  -->
  <!--Servlet配置  -->
  <servlet>
  <!--名称  -->
    <servlet-name>hello2</servlet-name>
    <!--Servlet的全称类名  -->
    <servlet-class>com.qf.web.servlet.HelloServlet</servlet-class>
    <!--启动的优先级,数字越小越先起作用  -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!--映射配置  -->
  <servlet-mapping>
  <!--名称  -->
    <servlet-name>hello2</servlet-name>
    <!--资源的匹配规则:精确匹配  -->
    <url-pattern>/hello2</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>login.html</welcome-file>
  </welcome-file-list>
</web-app>

6.4 Servlet生命周期

6.4.1 什么是生命周期

生命周期也就是生命历程,就像人都是从怀胎-->出生-->婴儿-->儿童-->少年-->成年-->中年-->老年-->死亡

6.4.2 生命周期的四个阶段

阶段一、实例化
实例化阶段是Servlet生命周期中的第一步,由Servlet容器调用Servlet的构造器创建一个具体的Servlet对象的过程。而这个创建的时机可以是在容器收到针对这个组件的请求之后,即用了才创建;也可以在容器启动之后立刻创建实例,而不管此时Servlet是否使用的上。使用如下代码可以设置Servlet是否在服务器启动时就执行创建
阶段二、初始化
Servlet在被加载实例化之后,必须要初始化它。在初始化阶段,init()方法会被调用。这个方法在javax.servlet.Servlet接口中定义。其中,方法以一个ServletConfig类型的对象作为参数。ServletConfig对象由Servlet引擎负责创建,从中可以读取到事先在web.xml文件中通过<init-param>节点配置的多个name-value名值对。ServletConfig对象还可以让Servlet接受一个ServletContext对象。
一般情况下,init方法不需要编写,因GenericServlet已经提供了init方法的实现,并且提供了getServletConfig方法来获得ServletConfig对象。
注:init方法只被执行一次
阶段三、就绪/服务
Servlet被初始化以后就处于能够响应请求的就绪状态。每个对Servlet的请求由一个ServletRequest对象代表,Servlet给客户端的响应由一个ServletResponse对象代表。当客户端有一个请求时,容器就会将请求与响应对象转给Servlet,以参数的形式传给service方法。service方法由javax.servlet.Servlet定义,由具体的Servlet实现
HttpServlet将service方法拆分了。doGet和doPost
阶段四、销毁
Servlet容器在销毁Servlet对象时会调用destroy方法来释放资源。通常情况下Servlet容器停止或者重新启动都会引起销毁Servlet对象的动作,但除此之外,Servlet容器也有自身管理Servlet对象的准则,整个生命周期并不需要人为进行干预

Servlet代码如下:

/**
 * Servlet implementation class LifeServlet
 * 演示Servlet的生命周期:
 * 1、实例化
 * 2、init:初始化
 * 3、service:服务
 * 4、destory:销毁
 */
@WebServlet("/LifeServlet")
public class LifeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LifeServlet() {
        super();
        System.out.println("1、完成了实例化");
        // TODO Auto-generated constructor stub
    }
    @Override
    public void init() throws ServletException {
        // TODO Auto-generated method stub
        super.init();
        System.out.println("2、完成了初始化");
    }
​
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("3、就绪中");
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }
​
    /**
     * @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);
    }
    
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        super.destroy();
        System.out.println("4、销毁了");
    }
}

6.5 获取请求参数

html页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>欢迎页面</title>
</head>
<body>
<h1>欢迎你</h1>
<div>
<form action="HelloServlet">
<label>姓名:</label><input name="name"><br/>
<label>年龄:</label><input  name="age"><br/>
<input type="submit" value="提交">
</form>
</div>
</body>
</html>

Servlet代码:

​
/**
 * Servlet implementation class HelloServlet
 * 演示Servlet的获取请求参数
 * 
 */
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取表单提交的姓名
        String name=request.getParameter("name");
        //获取年龄
        String age=request.getParameter("age");
        //服务端输出打印
        System.out.println(request.getRemoteAddr()+"发来信息:姓名:"+name+"---->年龄:"+age);
    }
​
    /**
     * @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);
    }
}

6.6 请求方式

默认的请求方式是GET请求

6.6.1 GET请求

GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连
GET提交的数据大小有限制(因为浏览器对URL的长度有限制)
GET方式提交数据,会带来安全问题
效率高

对应的Servlet的方法是doGet

6.6.2 POST请求

POST方法是把提交的数据放在HTTP包的Body中
POST方法提交的数据没有限制
POST提交的数据相对安全
效率相对没有GET高

对应的Servlet的方法是doPost

6.7 如何处理中文参数

6.7.1 为什么表单中会产生中文乱码

产生乱码,就是因为服务器和客户端沟通的编码不一致造成的,因此解决的办法是:在客户端和服务器之间设置一个统一的编码,之后就按照此编码进行数据的传输和接收

6.7.2 GET中文乱码

在Tomcat7及以下
客户端以UTF-8的编码传输数据到服务器端,而服务器端的request对象使用的是ISO8859-1这个字符编码来接收数据,服务器和客户端沟通的编码不一致因此才会产生中文乱码的。解决办法:在接收到数据后,先获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题。

Tomcat8的版本中GET基本就不会乱码了,因为服务器对url的编码格式可以进行自动转换

解决get中文乱码的代码:

/**
 * Servlet implementation class HelloServlet
 * 演示Servlet的GET请求,中文乱码的问题
 * 
 */
@WebServlet("/GETServlet")
public class GetServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
​
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取表单提交的姓名
        String name=request.getParameter("name");
        name=new String(name.getBytes("ISO8859-1"),"UTF-8");
        //获取年龄
        String age=request.getParameter("age");
        //服务端输出打印
        System.out.println(request.getRemoteAddr()+"发来信息:姓名:"+name+"---->年龄:"+age);
    }
    /**
     * @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);
    }
}

6.7.3 POST乱码

由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器也需要设置以UTF-8字符编码进行接收,要想完成此操作,服务器可以直接使用从ServletRequest接口继承而来的"setCharacterEncoding(charset)"方法进行统一的编码设置。

解决POST中文乱码代码如下:

/**
 * Servlet implementation class HelloServlet
 * 演示Servlet的GET请求,中文乱码的问题
 * 
 */
@WebServlet("/GETServlet")
public class GetServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
​
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        }
​
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求参数的编码格式--对GET无效
        request.setCharacterEncoding("UTF-8");
        //获取表单提交的信息
        String name=request.getParameter("msg");
        //服务端输出打印
        System.out.println(request.getRemoteAddr()+"发来信息:"+msg);
    }
}

6.8 Servlet输出中文

6.8.1 页面返回乱码原因

浏览器识别不到返回的中文是什么编码格式,就会默认使用GB2312,如果返回的是UTF-8格式的那么在浏览器上就会显示乱码的问题

6.8.2 如何解决内容中的乱码

response.setContentType("text/html;charset=UTF-8");

第七章 Servlet路径处理和特性

7.1 重定向

重定向就是通过各种方法将各种网络请求重新定个方向转到其它位

7.1.1 重定向原理和特点

客户浏览器发送http请求----》web服务器接受后发送302状态码响应及对应新的location给客户浏览器--》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址----》服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。

特点:
1,重定向是客户端行为。
2,重定向是浏览器做了至少两次的访问请求的。
3,重定向浏览器地址改变。
4,重定向2次跳转之间传输的信息会丢失(request范围)。
5,重定向可以指向任何的资源,包括当前应用程序中的其他资源,同一个站点上的其他应用程序中的资源,其他站点的资源。注意:传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录

7.1.2 实现重定向

html页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<div>
<form action="login" method="post">
<label>账号:</label><input name="un"/><br/>
<label>密码:</label><input type="password" name="pw"/><br/>
<input type="submit" value="登录"/>
</form>
</div>
<h1><a href="register.html">还没账号请注册</a></h1>
</body>
</html>

Servlet代码:

/**
 * Servlet implementation class LoginServlet
 * 实现登录信息操作
 */
@WebServlet(value="/LoginServlet",initParams={@WebInitParam(name="version",value="v10")})
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LoginServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
​
    @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        super.init(config);
    }
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //response.getWriter().append("Served at: ").append(request.getContextPath());
    }
​
    /**
     * @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);
        //获取表单提交的用户名
        String username=request.getParameter("un");
        //获取密码
        String password=request.getParameter("pw");
        //服务端输出打印
        System.out.println("POST:用户名:"+username+"---->密码:"+password);
        //重定向.可以跳转到指定的页面
        response.sendRedirect("register.html"); 
    }
}

7.2 请求转发

Servlet除了支持重定向之外还支持请求转发

7.2.1 转发的原理和特点

原理:
客户浏览器发送http请求----》web服务器接受此请求--》调用内部的一个方法在容器内部完成请求处理和转发动作----》将目标资源发送给客户。在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的

特点:
1,转发是服务器行为
2,转发是浏览器只做了一次访问请求
3,转发浏览器地址不变
4,转发2次跳转之间传输的信息不会丢失,所以可以通过request进行数据的传递
5,转发只能将请求转发给同一个WEB应用中的组件
注意:如果创建RequestDispatcher 对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。

7.2.2 实现请求转发

package com.qf.web.servlet;
​
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
​
/**
 * Servlet implementation class RegisterServlet 
 请求转发
 */
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
​
    /**
     * @see HttpServlet#HttpServlet()
     */
    public RegisterServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
​
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }
​
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取表单提交的用户名
        String username = request.getParameter("un");
        // 获取密码
        String password = request.getParameter("pw");
        // 服务端输出打印
        System.out.println("POST:注册:用户名:" + username + "---->密码:" + password);
        //请求转发
        request.getRequestDispatcher("LoginServlet").forward(request, response);
    }
}

7.3 请求资源路径

7.3.1 什么是请求资源路径

在浏览器输入:http://127.0.0.1:8080/Web_Day12/HelloServlet
Web_Day12/HelloServlet就是请求资源路径

7.3.2 容器对请求的处理过程

在浏览器输入:http://127.0.0.1:8080/Web_Day12/HelloServlet
浏览器依据ip,port建立与Servlet容器之间的连接,然后将请求资源路径Web_Day12/HelloServlet 发送过去给容器
容器依据应用名“/Web_Day12”找到应用所在的文件夹,容器会默认请求的是一个Servlet,
如果使用的是XML配置,那么查找web.xml文件中所有的Servlet配置url-pattern,看是否有匹配的Servlet
如果使用的是注解式配置,那么就直接检索注解@WebServlet的值是否匹配

7.3.3 匹配Servlet的规则

容器在进行url-pattern比对的时候是遵循一定的匹配原则的

匹配规则:

url-pattern定义匹配规则,取值说明:
精确匹配
/具体的名称		 只有url路径是具体的名称的时候才会触发Servlet
后缀匹配
*.xxx			只要是以xxx结尾的就匹配触发Servlet
通配符匹配
/* 				匹配所有请求,包含服务器的所有资源

7.4 单Servlet实现多请求

7.4.1 为什么要将Servlet合并

Servlet作为Web应用中最核心的环节是因为这个组件不仅能接受请求,还能够为该请求提供响应,所以Servlet一般都会充当整个应用的控制器来进行请求的分发,为不同的请求找到对应的资源。于是程序中大多只需要一个Servlet完成这个分发工作即可,合并多个Servlet为一个Servlet会让程序的处理逻辑更加明确

实现Servlet的合并:
使用后缀模式完成请求资源路径的匹配
分析请求资源路径中的请求目标,完成分发的动作

7.4.2 使用后缀模式完成路径匹配

2种方式:
1、在web.xml中
可以设置url-pattern的值为:*.do,这样只要是以do结尾的请求都可以进行匹配
2、在定义的Servlet类上
在注解@WebServlet("*.do")

7.4.3 分析请求资源后分发

配置完web.xml文件后,不同请求都会发送到Web.SomeServlet来处理,要想起到分发的作用,则需要分析调过来的请求中具体的请求目标是什么。

7.8 ServletContext

ServletContext:Servlet上下文

7.8.1 什么是Servlet上下文

Servlet上下文又叫做:ServletContext。
当WEB服务器启动时,会为每一个WEB应用程序(webapps下的每个目录就是一个应用程序)创建一块共享的存储区域
ServletContext也叫做“公共区域”,也就是同一个WEB应用程序中,所有的Servlet和JSP都可以共享同一个区域。
ServletContext在WEB服务器启动时创建,服务器关闭时销毁
容器在启动的时候,会为每一个web应用创建唯一的一个符合ServletContext接口的对象,该对象一般称之为"servlet上下文"。

7.8.2 如何获得Servlet上下文

方式一:GenericServlet提供了getServletContext()方法。
方式二:ServletConfig提供了getServletContext()方法。
方式三:HttpSession提供了getServletContext()方法。
方式四:HttpServletRequest提供了getServletContext()方法。

7.8.3 Servlet上下文的作用及特点

作用:
1、获取真实路径
获取当前项目的发布路径
request.getSelectContext().getRealPath("/");
2、获取容器的附加信息
System.out.println(request.getServletContext().getServerInfo());
System.out.println(request.getServletContext().getContextPath());
3、全局容器
//设置信息到全局容器中
request.getServletContext().setAttribute("msg", "共享信息");
//获取数据
System.out.println(request.getServletContext().getAttribute("msg"));
//移除数据
request.getServletContext().removeAttribute("msg");
特点:
唯一性: 一个应用对应一个servlet上下文。
一直存在: 只要容器不关闭或者应用不卸载,servlet上下文就一直存在。

7.9 Servlet的路径

绝对路径:绝对路径就是你的主页上的文件或目录在硬盘上真正的路径,(URL和物理路径)例如:
C:/xyz/test.txt 代表了test.txt文件的绝对路径。http://www.sun.com/index.htm也代表了一个
URL绝对路径

相对路径:相对与某个基准目录的路径。包含Web的相对路径(HTML中的相对目录),例如:在
Servlet中,"/"代表Web应用的跟目录。和物理路径的相对表示。例如:"./" 代表当前目录,
"../"代表上级目录。这种类似的表示,也是属于相对路径

服务器端的相对地址指的是相对于你的web应用的地址,这个地址是在服务器端解析的
(不同于html和javascript中的相对地址,他们是由客户端浏览器解析的)也就是说这时候
在jsp和servlet中的相对地址应该是相对于你的web应用,即相对于http://127.0.0.1:8080/test/的

7.10 Servlet线程安全问题

7.10.1 线程安全问题

因为每次请求都会创建一个线程,如果多人同时请求,那么就会存在多个线程操作同一个Servlet对象,那么如果在对应的方法中操作了成员变量,就有可能产生线程安全的问题。

7.10.2 如何保证线程安全

1、synchronized
将存在线程安全问题的代码放到同步代码块中
2、实现singleThreadModel接口
servlet实现singleThreadModel接口后,每个线程都会创建servlet实例,这样每个客户端请求就不存在共享资源的问题,但是servlet响应客户端请求的效率太低,所以已经淘汰。
3、尽可能只使用局部变量

7.11 综合案例

实现个人信息详细信息的提交

页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>个人信息的收集</title>
</head>
<body>
<h3>个人信息</h3>
<form action="quest" method="post">
<label>姓名:</label><input type="text" name="name"><br/>
<label>年龄:</label><input type="text" name="age"><br/>
<label>性别:</label><input type="radio" name="sex" id="female" checked/><label for="female">女</label>
<input type="radio" name="sex" id="male"/><label for="male">男</label><br/>
<label>联系方式:</label><input type="text" name="phone"><br/>
<label>电子邮件:</label><input type="email" name="email"><br/>
<input type="submit">
</form>
</body>
</html>

Servlet:

​
/**
 * Servlet implementation class Servlet1
 */
@WebServlet("/quest")
public class DBWriteServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DBWriteServlet() {
        super();
    }
​
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
​
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("name");
        int age =Integer.parseInt(request.getParameter("age")) ;
        String sex = request.getParameter("sex");
        String phone = request.getParameter("phone");
        String email = request.getParameter("email");
        System.out.println(name);
        System.out.println(age);
        System.out.println(sex);
        System.out.println(phone);
        System.out.println(email);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值