[TOC]

servlet体系结构

servlet—是一个接口
实现
GenericServlet—是一个抽象类
继承
HttpServlet—是一个抽象类

==GenericServlet== :

​ 将servlet接口中的其他的方法都给了默认实现,只将service方法作为抽象方法。定义一个Servlet类时,可以继承GenericServlet,重写他的service方法就可以了。如果定义一个Servlet类时,可以实现Servlet接口,重写他的(init() , getServletConfig() , service() , getServletInfo() , **destroy()**)

==HttpServlet==:对http协议的封装的servlet类。
使用:定义一个类继承HttpServlet,然后重写doGet和doPost方法就可以了。

1
2
3
4
5
6
7
@WebServlet(urlPatterns = {"/student","/student1"},loadOnStartup = 1)?????
@WebServlet("")
@WebServlet({,,})
路径定义规则:
1. /XXX
2. /MMM/DDD
3. *.action 或者 *.do

1. http

http概念:超文本传输协议。 Hyper text Transform protocol

传输协议:客户端和服务器端进行通信的时候,发送的数据的格式。

1.1 特点

  1. http协议底层是TCP协议。
  2. 默认端口号:80
  3. 基于请求/响应模型的:一次请求对应一次响应。
  4. 无状态的:多次请求与响应之间是互相独立的,数据不能交互。

1.2 版本

  • 1.0:每一次请求响应都需要建立新的连接
  • 1.1:重复使用连接。keep-alive

1.3 请求的数据格式

  1. 请求行:GET /Demo01 HTTP/1.1
  2. 请求头:包含了请求的信息:
    • user-agent:浏览器告诉服务器,当前使用的是什么浏览器哪个版本来访问你的。
    • Referer:http://localhost/ ,告诉服务器,当前请求是从哪里来的。
      • 作用:1.防盗链,2.统计工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//主机
Host: localhost
//用户使用的浏览器
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0

//当前浏览器能够识别的文本的种类
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

//当前浏览器能够识别的语言。 中文,台湾文字,香港文字,英文
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2

//能够接受的编码
Accept-Encoding: gzip, deflate

//告诉服务器请求是从哪里来的,能够防盗链
Referer: http://localhost/

//上下文类型
Content-Type: application/x-www-form-urlencoded

Content-Length: 30

//连接
Connection: keep-alive

//cookie
Cookie: JSESSIONID=3D2A2381F7F130098654C49A402347E7

Upgrade-Insecure-Requests: 1

  1. 请求空行:空行,分割请求头和请求体的。
  2. 请求体:封装post请求的参数的

1.4 响应的数据格式

  1. 响应行 HTTP/1.1 200 OK
    • 组成部分
      • ==协议版本==:http/1.1 长连接, http/1.0 短连接
      • ==响应码(状态码)==:服务器对浏览器的每一次请求都会响应一个状态值。
        • 1XX:服务器接收客户端的消息,但是没有接受完成,等待一段时间后,发送一个1xx的状态码给浏览器。
        • 2XX 成功访问。 200
        • 3XX 重定向 302(重定向) 304(访问缓存)
        • 4XX 客户端错误
          • 404 请求路径没有对应的资源
          • 405 请求类型不支持 get post
        • 5Xx 服务器端错误:500(服务器内部出现异常)
  2. 响应头:
    1. 格式:头名称:值
    2. 具体内容:
      • HTTP/1.1 200 OK
      • Content-Type: text/html
      • Content-dispostion:服务器告诉客户端用什么样的方式打开相应的数据
        • in-line: 默认值,使用浏览器页面打开。
        • attachment;filename=xxx; 以附件的形式打开,文件下载。
  3. 响应空行, 就是一个换行
    • 作用:分割响应头和响应体
  4. 响应体:传输的具体数据,响应给浏览器的结果。

1.5 请求方式

  1. GET:
    1. get请求的参数实在url地址栏中的。
    2. 因为url长度是有限制的。大约4kb , 所以传输的数据最大不能超过4kb。
    3. 不安全
  2. POST:
    1. 请求参数在方法体中
    2. 请求传输的数据大小没有限制
    3. 相对安全。

2. request对象和response对象

request,resposne对象由服务器来创建,我们仅仅是使用它

2.1 request对象

request对象:请求对象

request对象里面封装了所有的请求的消息

2.1.1 request对象的常用方法

常用方法

1
2
3
4
5
6
7
8
9
10
11
12
request.getMethod();      //返回请求的方式  GET/POST/PUT/...
request.getContextPath(); //获取的是虚拟目录 /day08
request.getServletPath(); //servlet路径 /request01
request.getQueryString(); //查询的是get方式的请求参数。
request.getRequestURI(); //获取URI地址 /day08/request01
request.getRequestURL();//http://localhost:8080/day09/response01
request.getProtocol(); //HTTP/1.1
request.getRemoteAddr(); //拿到的是客户机的ip地址。0:0:0:0:0:0:0:1

/*
request.getRequestURI() == request.getContextPath() + request.getServletPath();
*/

获取请求头信息的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//请求头数据
request.getHeaderNames();//获取头的名称的集合
request.getHeader(String name) 根据头获取值

//枚举,类似于迭代器
//获取头的集合
Enumeration<String> headerNames = req.getHeaderNames();

//判断是否还有元素 headerNames.hasMoreElements();
while(headerNames.hasMoreElements()){
//拿到下一个元素
String name = headerNames.nextElement();


//根据头名称获取对应的值得信息。
String value = req.getHeader( name );

}

//获取user-agent头信息对应的数据
String header = request.getHeader("user-agent");


/**user-agent
谷歌浏览器:
user-agent = Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36
火狐浏览器:
user-agent = Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0
IE浏览器:
user-agent = Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
360浏览器:
user-agent = Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko

IE浏览器和360浏览器的区别?????
360安全浏览器(360 Security Browser)是360安全中心推出的一款基于IE和Chrome双内核的浏览器,是世界之窗开发者凤凰工作室和360安全中心合作的产品。

*/

拿到请求体的信息(GET请求没有请求体)

1
2
3
4
//获取字符流对象
//仅仅针对于post请求有效,拿到的是请求体的内容。
BufferedReader reader = request.getReader()

获取参数的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@WebServlet("/request06")
//request域,向request域中加入一组数据
request.setAttribute("name","mm");
//请求的转发
request.getRequestDispatcher("/request07").forward(req,resp);

@WebServlet("/request07")
//从request域中取出name绑定的数据。
Object name = request.getAttribute( "name" );


//根据参数的名称拿到参数的值
request.getParameter(String name) ;

//一致性获取到所有参数的键值对信息,然后封装成一个map集合。
Map<String, String[]> map = request.getParameterMap();

// 创建一个user对象
User user = new User();
//该方法可以将map集合直接封装成响应的javaBean对象。
BeanUtils.populate(user,map);


请求对象的编码问题

tomcat8以前的版本中,GET和POST中文都会乱码。

但是在**jdk8?**的版本中,get请求的默认编码格式变成了UTF-8,所以不会有乱码的情况出现了。

1
request.setCharacterEncoding("utf-8");

2.1.2 request对象的体系结构

  • ServletRequest – 接口
  • HttpServletRequest –接口
  • org.apache.catalina.connector.RequestFacade 实现类

2.1.3 用户登陆案例

  1. 编写login.html页面 username 和 password两个输入框
    1. 使用Druid连接池,操作mysql中的user表。
    2. 使用jdbcTemplate技术封装jdbc;
    3. 登陆成功后跳转到successServlet中展示:登陆成功
    4. 登陆失败跳转到errorServlet中展示:登陆失败。

2.2 response对象

response对象:响应对象

response,服务器发送给客户端的数据

response对象中设置了所有的响应给浏览器的消息

2.1 设置响应行:设置状态码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

//重定向,重定向可以到其他IP地址,如:http://www.taobao.com
response.setStatus(302);
response.setHeader("location","/day09/status02");
===========================
response.sendRedirect( "/day09/status02");


//重定向---拿不到money数据
request.setAttribute( "money","1000" );
String contextPath = request.getContextPath();
response.sendRedirect( contextPath + "/testRedirect");


//转发---拿得到money数据
request.setAttribute( "money","1000" );
request.getRequestDispatcher("/testForward").forward( req,resp );

//转发无法访问到当前项目以外的任何服务。
//req.getRequestDispatcher("http://www.baidu.com").forward(req,resp);

response.setStatus(404);//404请求路径没有对应的路径
response.setStatus(405);//请求类型不支持 GET/POST
//当前的servlet中只有doGet方法,无法处理doPost方法,当发送一个post请求过来的时候,无法处理,给浏览器一个状态码405



response.setStatus( 500 ); //(服务器内部出现异常)HTTP ERROR 500


//resp对象默认使用iso-8859-1进行编码

getRequestURI()和getRequestURL()

1
2
3
String requestURI = req.getRequestURI();///day09/response01
StringBuffer requestURL = req.getRequestURL();
//http://localhost:8080/day09/response01

2.设置响应头

1
2
3
4
resp.setCharacterEncoding( "UTF-8" );
resp.setHeader( "content-type", "text/html;charset=utf8");
//===========================================
resp.setContentType("text/html;charset=utf-8");

3.设置响应体,使用输出流,将数据输送到浏览器端

1
2
3
4
5
6
7
8
9
//通过resp的对象创建一个打印输出路对象
PrintWriter writer = resp.getWriter();//字符输出流
writer.write( "hello mm\r\n");
writer.write( "hello mm");
//乱码!因为是resp对象默认使用iso-8859-1进行编码

//字节输出流
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write( "hello 喵喵".getBytes() );

2.3 Request、Response对象的内存地址维护

  • 在同一个浏览器中不断的向同一个Servlet发送请求,reqeust和response不断的新建和销毁但是内存地址没有改变。是因为tomcat根据访问的IP地址对reqeust和response内存地址进行维护,当reqeust和response对象销毁后,tomcat不会立刻将该内存地址销毁,而是将该内存进行占位,等到下次创建新的reqeust和response对象就会分配到这个内存中。

  • 避免了不断分配新内存造成资源浪费。

  • 如果该内存长时间(默认30分钟)没有reqeust和response对象,将会销毁该内存地址,或是存放其他的对象。

2.4 转发和重定向的区别 forward和redirect的区别

2.4.1转发

请求的转发。request.getRequestDispatcher(“/request07”).forward(req,resp);

1.url地址栏不变
2.转发无法访问当前项目以外的服务
3.转发是一次请求。
4.req域中的存储的数据在 转发后能够取出来
5.转发的路径中不写项目的虚拟目录

2.4.2 重定向

response.sendRedirect( contextPath + “/testRedirect”);

1.url地址栏会变
2.重定向可以访问当前项目以外的其他服务器。
3.两次请求
4.重定向后无法取出重定向前req域中的数据。
5.重定向的路径中要添加虚拟目录

3. 相对路径和绝对路径

3.1 相对路径

相对路径:通过相对路径不可以确定唯一的资源。相对路径指的是当前资源访问地址之间的关系,而不是文件在文件系统中的路径关系

​ ./index.html
​ ./ : 代表的是当前路径下。
​ ../ :上一级目录下。

3.2 绝对路径

绝对路径:通过绝对路径可以确定唯一的资源。
/index.html

4. ServletContext对象

概念:代表的是整个web应用。可以和程序的服务器进行通信,ServletContext对象是单例的。

4.1 获取ServletContext对象

1
2
3
4
5
6
7
8
//通过request对象获取。
ServletContext servletContext = req.getServletContext();

//通过HttpServlet对象来获取
ServletContext servletContext1 = this.getServletContext();


System.out.println(servletContext==servletContext1);//true

4.2 ServletContext对象作用

  1. 获取文件的MIME类型
    • MIME类型:在互联网通信的过程中定义的一种文件数据类型。
    • text/html 大类型/小类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//获取文件的mime类型
String mimeType = servletContext.getMimeType( str );

resp.getWriter().write( mimeType );
/**
mm.jpg 图像/ JPEG
*mm.mp4 image/jpeg
*mm.doc application/msword
*mm.pdf application/pdf
*mm.mp3 音频/ MPEG
*mm.md audio/mpeg
* */


  1. 作为域对象存储数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@WebServlet("/demo03")
ServletContext servletContext = req.getServletContext();

servletContext.setAttribute( "name","耐你" );

resp.sendRedirect("/demo04");//重定向




@WebServlet("/demo04")
ServletContext servletContext = req.getServletContext();

Object name = servletContext.getAttribute( "name" );
//拿到 耐你
     ==突破了重定向req无法共享数据的局限性==。**ServletContext的域对象在整个生命周期中被所有的servlet对象所共享。**
  1. 获取文件的真实路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//拿到文件的真实路径,“/”代表的就是web工程的classpath路径。
String realPath = servletContext.getRealPath( "index.html" );
//realPath = D:\javaCode\workspace_web\out\artifacts\day09_war_exploded\index.html
System.out.println( "realPath = " + realPath );




String realPath1 = servletContext.getRealPath("/WEB-INF/web.xml");
// realPath1 = D:\javaCode\workspace_web\out\artifacts\day09_war_exploded\WEB-INF\web.xml
System.out.println("realPath1 = " + realPath1);


//src下的文件最终都放到了WEB-INF下面的classes文件夹下
String realPath2 = servletContext.getRealPath("/WEB-INF/classes/a.txt");

// realPath2 = D:\javaCode\workspace_web\out\artifacts\day09_war_exploded\WEB-INF\classes\a.tx
System.out.println("realPath2 = " + realPath2);