Web复习-7: Servlet

一个Servlet就是运行在web服务器中的Java小程序, 它接收并且响应来自客户端的请求, 通过http的形式.

作用:

  1. 接收请求
  2. 处理请求
  3. 完成响应

由Servlet容器(Tomcat)创建

HelloWorld!

  1. 创建自己的类实现servlet接口
  2. 在service方法中写代码
  3. 在web.xml里面配置
<!-- servlet标签配置servlet的类信息, 告诉服务器, 我有这个servlet -->
<servlet>
    <servlet-name>MyFirstServlet</servlet-name>
    <servlet-class>com.wang.servlet.MyFirstServlet</servlet-class>
</servlet>
<!-- 映射信息 -->
<servlet-mapping>
    <!-- 刚才配置的servlet-name -->
    <servlet-name>MyFirstServlet</servlet-name>
    <!-- servlet用来处理哪个请求 -->
    <url-pattern>/helloworld</url-pattern>
</servlet-mapping>

类信息:

  • servlet-class: 配置全类名, 服务器通过全类名寻找servlet

  • servlet-name: 给自己看的

映射信息:

  • servlet用来处理哪一个信息
  • url-pattern: 告诉服务器servlet用来处理哪个请求

没有/hello静态资源, 就扫描web.xml里面 发现url-pattern中有, 就是告诉服务器, 这个动态资源使用servlet-class中的类处理的, 注意看localhost:8080/08.servlet/helloworld, 后没有后缀

在地址栏输入(或跳转)http://localhost:8080/08.servlet/helloworld访问时:

  1. localhost:8080: tomcat服务器接收请求
  2. 08.servlet/helloworld是否有静态资源与之对应
  3. 没有就去web.xml里面查找, 如果在url-pattern查找到了就是动态资源, 就会有上面的servalet-name, 再去上面的servlet中找全类名
  4. 找到了类, 就调用service方法

(实际上是先在web.xml中查找动态资源, 再去搜索静态页面, 上述流程是为了帮助理解)

Servlet的生命周期

生命周期: 出生到死亡

没有手动创建对象; 而是请求动态资源就hi启动这段servlet并调用其中的service方法, 但我们没有创建对象和调用方法

Servlet是跑在服务器上的, Tomcat服务器就是Servlet容器, 是容器(也就是Tomcat服务器)创建了对象调用了方法.

  • 第一次请求相关url:

    1. 先调用构造器创建Servlet对象
    2. 初始化servlet方法
    3. 调用service方法
  • 以后访问, 只调用service方法;

  • 当项目从服务器上卸载时, 服务器会调用destroy方法(包括移除项目和停止服务器)

整个web运行期间, 只创建了一个servlet对象(单实例), 但是是多线程运行的; 一般不会再servlet中写共享变量, 可能会存下线程安全问题

从init到ServletConfig

餐馆, 一个Servlet就像一个服务员, 有一个自己唯一的config配置, 例如别名和一些属性; 但所有这个web项目下的Servlet服务员, 都有一个共同的代表了web项目信息(类似于餐厅老板)的ServletContext

  1. ServletConfig是什么?
    是封装了当前servlet配置信息的对象, 一个ServletConfig只对应一个servlet, 即this:ConfigServlet
  2. 有什么功能?
    • 获取servletname的别名
    • 获取初始化参数
    • 获取servletContext对象, 代表当前web项目信息, 一个web项目只有一个context
package com.wang.servlet;

public class ConfigServlet implements Servlet {
	private ServletConfig config = null;

	@Override
	// init方法由服务器来调用, config参数由服务器传入
	public void init(ServletConfig config) throws ServletException {
		this.config = config;
		String servletname = config.getServletName();
		System.out.println(servletname);
		String servletinitpara = config.getInitParameter("username");
		System.out.println("初始化参数:"+ servletinitpara);
		ServletContext context = config.getServletContext();
		System.out.println(context);
	}
	//可以直接returnconfig属性
	@Override
	public ServletConfig getServletConfig() {
		// TODO Auto-generated method stub
		return this.config;
	}

	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		// TODO Auto-generated method stub

	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		return "ConfigServlet";
	}
	//服务器停止和项目卸载时调用
	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}

ServletContext

获取到ServletContext:

  1. 首先需要获取ServletConfig, 初始化后不会为空

  2. 用ServletConfig获取ServletContext

ServletContext是什么?

​ 一个web应用的对应一个ServletContext, 代表了整个web项目

ServletContext的功能是什么?

  1. getInitParameter(param): 获取web项目的配置信息, 初始化参数(<context-param>)

  2. getContextPath():获取web项目路径

  3. getRealPath(资源):获取资源的真实路径

    1. 虚拟路径: 网络访问使用(地址栏里的), 都对应了一个实际资源;

      • 动态资源: 启动一段程序代码
      • 静态资源: 打开一个文件
    2. 真实路径: 文件在磁盘中的存储路径

    3. 由虚拟路径找到真实路径的方式:

      在这里插入图片描述

  4. 作为最大的域对象共享数据

package com.wang.servlet;

public class ContextServlet implements Servlet {
	private ServletConfig config;

	@Override
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
		this.config = config;

	}

	@Override
	public ServletConfig getServletConfig() {
		// TODO Auto-generated method stub
		return this.config;
	}

	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		// TODO Auto-generated method stub
		ServletConfig config = this.getServletConfig();
		ServletContext context = config.getServletContext();
		//1. context-param:获取配置信息
		String name = context.getInitParameter("user");
		System.out.println(name);//root
		
		//2. 获取项目路径
		String path = context.getContextPath();
		System.out.println(path);///08.servlet
		
		//3. 获取资源路径
		String realPath = context.getRealPath("/index.html");
		System.out.println(realPath);	//D:\Java_learning\tomcatMirror\wtpwebapps\08.servlet\index.html
	}
}

HttpServlet

为处理http请求定制的

  1. post请求: 表单提交指定method=“post”
  2. 回车/超链接/img src =“…”都是get请求

在这里插入图片描述

httpservletrequest: 收到的浏览器端的请求信息, 封装的浏览器请求信息对象

httpservletresponse: 发送给浏览器的响应对象, 封装我们的相应信息

HttpServletResponse

  1. 可以给浏览器响应字符串:

    PrintWriter writer = response.getWriter();
    writer.write("Hello, HttpServlet");
    
  2. 可以重定向到一个页面或其他资源

    重定向: 服务器告诉浏览器去请求别的资源

    response.sendRedirect("资源");
    

    例如一个index页面:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    	<a href="http://localhost:8080/08.servlet/helloworld">链接</a>
    	<br />
    	<form action="MyEclipseServlet" method="post">
    		用户名: <input type="text"> 
    		<input type="submit" value="提交">
    	</form>
    
    </body>
    </html>
    

    form表单提交地址为MyEclipseServlet, 方式为post, 写好响应的动态资源的代码, 并在xml中进行配置

    package com.wang.servlet;
    
    /**
     * Servlet implementation class MyEclipseServlet
     */
    public class MyEclipseServlet extends HttpServlet {
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		response.sendRedirect("success.html");
    	}
    }
    ``
    
    http://localhost:8080/08.servlet/MyEclipseServlet, http://localhost:8080/08.servlet/success.html 都在当前项目下, 和index.html都是同一目录下, 所以使用绝对路径, 即在 MyEclipseServlet和 success.html两个资源名称前都不加斜杠
    
    

HttpServletRequest

  1. 获取请求数据: get放在url后; post放在请求体中

    • getParameter(“标签的name属性”): 获取单个值
    • getParameterValue(“标签的name属性”): 获取多个值例如复选框等
  2. 获取请求头

    request.getHeader(“User-Agent”)

  3. 转发一个页面或资源, 例如上文中的index ➡ 登录成功页面, 可以使用:

    • response重定向
    • request转发

    request转发步骤:

    1. 先获取请求转发器request.getRequestDispatcher("资源地址")
    2. 将请求转发出去dispatcher.forward(req resp)

注意: 转发和重定向, 都是对请求的响应, 因此只能在一次请求中只能使用两者中的一个. 否则就是对请求进行多次响应

  1. 作为域对象共享数据(ServletContext–> application, request)

转发与重定向

重定向: 告诉浏览器重新请求资源, 同样可以请求动态资源

转发: 服务器处理完成后转交到另一个资源

  1. 转发的资源是静态资源: 服务器会给浏览器返回这个资源
  2. 转发的资源是动态资源, 即转交给下一个servlet(可以形成处理链, 直到最后一个servlet)

两种跳转的区别:

请求转发重定向
地址栏动态资源地址转发后的资源地址
请求同一次请求两次请求
APIRequestResponse
响应状态码200第一次为302, 第二次为200
位置服务器内部完成浏览器完成
WEB-INFO可以访问不能访问
目标资源必须是当前web应用中的资源不局限于当前web应用
共享请求数据域可以共享不能

图解

请求转发:

在这里插入图片描述

重定向:
在这里插入图片描述

乱码问题–编码解码方式不统一

响应给浏览器的数据是乱码

常见问题: 在正常显示中文的html页面中写入中文乱码writer.write(“中文字符”), 显示的是????

需要在还没有产生流的时候(在第一次操作response之前)告诉浏览器编码格式以及传输数据的内容类型(MIME)

方法有如下三种:

  1. reponse.setContentType("text/html");
    reponse.setCharsetEncoding("utf-8");
    
  2. reponse.addHeader("Content-Type","text/html/charset=utf-8")
    
  3.  reponse.setContentType("text/html/charset=utf-8")
    
    

响应给浏览器的数据是乱码, 原因是浏览器不知道数据的类型以及编码格式. 解决的方式是告诉浏览器了内容类型以及编码格式, 万变不离其宗, 需要设置的都是响应头中的ContentType: text/html/charset=utf-8

表单中的乱码

表单中输入中文, 提交过来是乱码

post乱码原因

浏览器将数据提交, 但服务器不知道浏览器的编码规则.

解决方法: 让服务器直到编码规则, 重新设置请求的编码格式, 同样需要在开始使用之前就设置, 这个对请求体有作用.

request.setCharacterEncoding(“utf-8);
get乱码原因

数据传输流程: 浏览器将表单数据等请求编码好, 发过来给服务器, 服务器解码封装成request对象.

原因: get请求传来的数据在url中, 也被浏览器编码.过来的时候早已被服务器按照默认的解码方式解码然后封装为request对象.

解决办法: 需要在server.xml在8080端口那里直接设置URIEncoding="utf-8"

项目路径

绝对路径: 以/开始, 代表的是当前项目的根目录08.servlet

注意: 转发与重定向的方法里面对根目录的区别

  1. 转发使用绝对路径来写, 从当前项目的根目录08.servlet开始http://localhost:8080/08.servlet, 例如/index.html
  2. 重定向到绝对路径: 容器的根目录http://localhost:8080, 写绝对路径的时候需要带上项目名/08.servet/index.html

原因: 转发是服务器内部转发, 在项目内部, 所以根目录定位在项目上; 而重定向, 请求由浏览器来发, 所以根目录定位在容器的根目录上

web.xml中服务器解析的时候对应的是项目的根目录, 服务器解析哪个项目对应的就是项目的当前根

动态获取项目路径(项目根目录)两种方法:

ServletContext context = getServletContext();
String path = context.getContextPath();
//这样写是一样的
String path2 = request.getContextPath()
//绝对路径再由项目路径和资源路径拼串产生即可
path+"/pages/a.html"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值