1.目标
1.使用request对象接收来自客户端浏览器的请求数据。
2.使用response对象响应数据给浏览器客户端。
3.使用注解开发servlet。
2.绝对路径(掌握)
前端页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
TODO:绝对路径
1.带网络三要素的绝对路径:http://127.0.0.1:8080/pathAbso
2.省略网络三要素的绝对路径:只能访问当前服务器。/pathAbso 不能省略/
-->
<a href="http://127.0.0.1:8080/pathAbso">带网络三要素的绝对路径</a><br>
<a href="/pathAbso">不带网络三要素的绝对路径</a><br>
</body>
</html>
servlet类:
package com.itheima.sh.a_servlet_01;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class PathDemo01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("绝对路径 get");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("绝对路径 post");
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>PathDemo01Servlet</servlet-name>
<servlet-class>com.itheima.sh.a_servlet_01.PathDemo01Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PathDemo01Servlet</servlet-name>
<url-pattern>/pathAbso</url-pattern>
</servlet-mapping>
</web-app>
浏览器访问:
3.相对路径(掌握)
web阶段的相对路径相对的不是当前项目,相对的是当前url地址栏。
demo02.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
TODO:相对路径 相对当前url地址栏的
1.我们在浏览器地址栏上访问的页面是: http://localhost:8080/demo02.html。
而在该页面中访问servlet的地址是:http://localhost:8080/pathAbso2
对于当前页面而言,pathAbso2即servlet类的地址和demo02.html是同一级目录,因此在/demo02.html页面如果使用相对路径访问那么
可以书写:./pathAbso2 .表示当前路径可以省略,省略后:pathAbso2
-->
<a href="./pathAbso2">相对路径</a><br>
<a href="pathAbso2">相对路径</a><br>
</body>
</html>
package com.itheima.sh.a_servlet_01;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class PathDemo02Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("相对路径。。。。PathDemo02Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
<servlet>
<servlet-name>PathDemo02Servlet</servlet-name>
<servlet-class>com.itheima.sh.a_servlet_01.PathDemo02Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PathDemo02Servlet</servlet-name>
<url-pattern>/pathAbso2</url-pattern>
</servlet-mapping>
demo03.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
TODO:相对路径 相对当前url地址栏的
2.需求:在demo03.html页面访问pathAbso3的servlet类
在浏览器地址栏上访问的静态资源路径是:http://localhost:8080/aaa/demo03.html
那么我们要访问的Servlet路径是: http://localhost:8080/pathAbso3
在demo03.html使用相对路径访问pathAbso3的相对路径写法是:../pathAbso3
针对http://localhost:8080/aaa/demo03.html 页面我们这里使用..表示demo03.html的上一级目录即http://localhost:8080/aaa
然后在aaa同一级目录下查找pathAbso3
-->
<a href="../pathAbso3">相对路径</a><br>
</body>
</html>
package com.itheima.sh.a_servlet_01;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class PathDemo03Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("相对路径。。。。PathDemo03Servlet....");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
<servlet>
<servlet-name>PathDemo03Servlet</servlet-name>
<servlet-class>com.itheima.sh.a_servlet_01.PathDemo03Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PathDemo03Servlet</servlet-name>
<url-pattern>/pathAbso3</url-pattern>
</servlet-mapping>
web阶段的相对路径相对的是浏览器url地址栏。
. 表示当前路径,可以省略
.. 表示上一级路径。
4.Servlet3.0注解开发 (掌握)
我们之前都是servlet2.5使用的是xml开发,弊端是在web.xml中进行配置会导致配置冗余并且麻烦。从servlet3.0开始我们引入注解开发,主要简化代码开发的。因此要求导入的servlet依赖必须是servlet3.0之后
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
注解开发实现:
1.导入依赖:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
2.在包上右键====》new ===>servlet(create servlet)
package com.itheima.sh.b_anno_servlet_02;
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("/annoDemo01Servlet")
public class AnnoDemo01Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("注解开发...简单");
}
}
5.Servlet3.0注解开发注意事项 (掌握)
package com.itheima.sh.b_anno_servlet_02;
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;
/*
TODO:
1.注解开发使用的注解是 @WebServlet
2.@WebServlet注解常见的属性是:
1)String name() default ""; 相当于web.xml中的 <servlet-name></servlet-name> 不写
name="AnnoDemo01Servlet" ====><servlet-name>AnnoDemo01Servlet</servlet-name>
2)String[] urlPatterns() default {}; 相当于web.xml中的<url-pattern></url-pattern>
回顾:
I:使用注解的时候,如果注解的属性是数组,那么我们使用的时候只给属性一个值,此时可以省略{}
3)String[] value() default {}; 该属性等价于urlPatterns属性,定义该属性的目的就是为了简化代码书写。
在使用注解的时候关于属性名是value是可以省略的
回顾:
I:如果注解中只有一个属性是value,那么可以省略
II:如果注解中有多个属性,并且每个属性都有默认值,此时在给value赋值的时候可以省略value,如果除了给value
赋值还有其他属性赋值不能省略value
*/
//@WebServlet(urlPatterns={"/annoDemo01Servlet"},name="AnnoDemo01Servlet")
//@WebServlet(urlPatterns={"/annoDemo01Servlet","/annoDemo02Servlet"},name="AnnoDemo01Servlet")
//@WebServlet(value="/annoDemo01Servlet",name="AnnoDemo01Servlet")
@WebServlet("/annoDemo01Servlet")//这里给value赋值
public class AnnoDemo01Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("注解开发...简单");
}
}
6.在idea中配置Servlet3.0注解开发的模板 (掌握)
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebServlet("/${Entity_Name}")
public class ${Class_Name} extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
doGet(request,response);
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
}
}
7.HTTP协议
1.介绍
超文本传输协议。是互联网行传输数据的一种规范。
2.浏览器抓包观察请求报文协议(必须会)
1.在浏览器中按f12
2.
3.
8.request请求对象和response响应对象初体验
package com.itheima.sh.c_http_request_03;
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("/requestAndResponseDemo01Servlet")
public class RequestAndResponseDemo01Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//TODO:request对象处理客户端浏览器的请求数据
String username = request.getParameter("username");
System.out.println("username = " + username);
//TODO:response响应数据给浏览器的
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("程序员");
}
}
9.request对象的继承关系 掌握
1.HttpServletRequest 接口继承了ServletRequest 接口,对父接口进行扩展,可以处理满足所有http协议的请求。
2.HttpServletRequest 和 ServletRequest都是接口,不能创建对象,因此在tomcat底层定义实现类并创建实现类对象:
public class RequestFacade implements HttpServletRequest {}
tomcat底层创建门面类RequestFacade对象
ServletRequest request = new RequestFacade(); 多态
10.请求行的方法(掌握)
package com.itheima.sh.d_request_04;
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("/requestRowDemo01Servlet")
public class RequestRowDemo01Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求方式: GET String getMethod()
System.out.println(request.getMethod());
//2.获取虚拟目录(项目访问路径): String getContextPath() 就是我们在tomcat配置的位置设置的路径,是虚拟的,就是随便定义
//如果设置虚拟路径位置是/那么该方法获取的内容是空字符串
System.out.println(request.getContextPath());//""
//3.获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
//StringBuffer getRequestURL() 获取的是请求资源的绝对路径(含三要素)
//StringBuilder 和 StringBuffer都表示字符串缓冲区,字符可以改变 。StringBuilder多线程不安全 效率高
//StringBuffer多线程安全 效率低
StringBuffer sb = request.getRequestURL();
String s = sb.toString();
// http://localhost:8080/day16/requestRowDemo01Servlet
System.out.println("s = " + s);
//4.获取URI(统一资源标识符): /request-demo/req1
//String getRequestURI() 获取的是请求资源的绝对路径(不含三要素)
// /day16/requestRowDemo01Servlet
System.out.println(request.getRequestURI());
//5.获取请求参数(GET方式): username=zhangsan&password=123 了解
//String getQueryString()
System.out.println(request.getQueryString());//"username=suoge&pwd=1234"
}
}
1.获取请求方式: GET String getMethod()。
2.获取虚拟目录(项目访问路径): String getContextPath()。
3.StringBuffer getRequestURL() 获取的是请求资源的绝对路径(含三要素) 获取URL。
4.String getRequestURI() 获取的是请求资源的绝对路径(不含三要素) 获取URI。
11.获取请求头的方法(掌握)
package com.itheima.sh.d_request_04;
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("/requestHeaderDemo02Servlet")
public class RequestHeaderDemo02Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
String getHeader(String name) 参数name书写的是请求头冒号左边的内容例如:User-Agent
*/
//需求:获取请求头key是User-Agent的值
String header = request.getHeader("User-Agent");
//Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
System.out.println("header = " + header);
}
}
12.获取请求体数据 掌握
package com.itheima.sh.d_request_04;
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.BufferedReader;
import java.io.IOException;
@WebServlet("/requestBodyDemo03Servlet")
public class RequestBodyDemo03Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
1.获取请求体数据的方法:
1)ServletInputStream getInputStream()该方法可以获取字节和字符数据
2)BufferedReader getReader() 获取字符数据
*/
//1.获取输入流对象
BufferedReader reader = request.getReader();
//2.使用字符缓冲流读取字符数据
String line=null;
while((line= reader.readLine())!=null){
System.out.println(line);//"username=zhangsan&pwd=123"
}
//这里不用单独释放IO流了,因为reader对象使用request获取,只要request对象销毁,流关闭
}
}
13.获取请求参数的通用方式(很重要)
1.问题
根据上述API的讲解,我们发现如果是get请求,获取请求参数使用的API是:
String getQueryString()
如果是post请求,获取请求参数的API是:
1)ServletInputStream getInputStream()该方法可以获取字节和字符数据
2)BufferedReader getReader() 获取字符数据
package com.itheima.sh.d_request_04;
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.util.Arrays;
import java.util.Map;
@WebServlet("/requestDemo05Servlet")
public class RequestDemo05Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
获取请求参数的通用方式:
1.Map<String,String[]> getParameterMap() 获取所有的请求参数。
抓包冒号左边的作为map集合的key,冒号右边的值作为map集合的value
2.String[] getParameterValues(String name) 获取指定的值。参数是抓包冒号左边的标识。获取的值放到数组中
3.String getParameter(String name)获取指定的值。 参数是抓包冒号左边的标识
注意:如果参数的name有多个值谁在前面先获取谁
抓包结果:
username: zhangsan
password: 1234
hobby: 1
hobby: 2
*/
/*
1.Map<String,String[]> getParameterMap() 获取所有的请求参数。
抓包冒号左边的作为map集合的key,冒号右边的值作为map集合的value
*/
Map<String, String[]> map = request.getParameterMap();
//jdk8遍历map
map.forEach((key,value)->{
System.out.println(key+"---"+ Arrays.toString(value));
});
/*
2.String[] getParameterValues(String name) 获取指定的值。参数是抓包冒号左边的标识。获取的值放到数组中
*/
//参数username是是抓包冒号左边的标识===》 username: zhangsan
String[] usernames = request.getParameterValues("username");
System.out.println(Arrays.toString(usernames));
/*
3.String getParameter(String name)获取指定的值。 参数是抓包冒号左边的标识
注意:如果参数的name有多个值谁在前面先获取谁
*/
//参数username是是抓包冒号左边的标识===》 username: zhangsan
String username = request.getParameter("username");
System.out.println("username = " + username);
String hobby = request.getParameter("hobby");
System.out.println("hobby = " + hobby);
}
}
14.解决post请求乱码问题 掌握
从tomcat8开始,对get请求已经解决了中文乱码问题。对于post请求没有解决中文乱码问题。需要我们使用代码解决。
【1】产生乱码的原因以及解决乱码分析
【2】代码实现
package com.itheima.sh.d_request_04;
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("/requestDemo06Servlet")
public class RequestDemo06Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
TODO:解决post请求中文乱码
1.使用request对象调用方法 request.setCharacterEncoding("UTF-8");//告知tomcat使用UTF-8解码
注意:是解决请求体数据的乱码的。是解决post乱码的
2.使用javase的API解决
编码:URLEncoder类中的静态方法static String encode(String s, String enc) s:编码的字符串 enc 表示编码表
解码:URLDecoder类中的静态方法static String decode(String s, String enc) s:解码的字符串 enc 表示编码表
3.使用javase的API解决即String类
编码:URLEncoder类中的静态方法static String encode(String s, String enc) s:编码的字符串 enc 表示编码表
解码:URLDecoder类中的静态方法static String decode(String s, String enc) s:解码的字符串 enc 表示编码表
*/
//TODO:1.使用request对象调用方法
// request.setCharacterEncoding("UTF-8");//告知tomcat使用UTF-8解码
//获取数据
String username = request.getParameter("username");//username: 锁哥
// System.out.println("username = " + username);
//TODO:2.使用javase的API解决
/*
编码:URLEncoder类中的静态方法static String encode(String s, String enc) s:编码的字符串 enc 表示编码表
解码:URLDecoder类中的静态方法static String decode(String s, String enc) s:解码的字符串 enc 表示编码表
*/
// 编码:URLEncoder类中的静态方法static String encode(String s, String enc) s:编码的字符串 enc 表示编码表
//username = URLEncoder.encode(username, "ISO-8859-1");
//解码:URLDecoder类中的静态方法static String decode(String s, String enc) s:解码的字符串 enc 表示编码表
//username = URLDecoder.decode(username, "UTF-8");
//TODO:3.使用javase的API解决即String类
/*
编码:String类中的非静态方法byte[] getBytes(String charsetName) 参数表示编码表
解码:使用String类中的构造方法String(byte[] bytes, String charsetName) bytes:解码的字节数组 charsetName 表示编码表
*/
//编码:String类中的非静态方法byte[] getBytes(String charsetName) 参数表示编码表
byte[] bytes = username.getBytes("ISO-8859-1");
//解码:使用String类中的构造方法String(byte[] bytes, String charsetName) bytes:解码的字节数组 charsetName 表示编码表
username = new String(bytes,"UTF-8");
System.out.println("username = " + username);
}
}