2.2 请求方式
2.2.1 请求方式介绍
不同的请求方式在数据传输时,会有所不同;在表单提交以及服务器处理时都会采用不同的方式。浏览器针对每种请求方式也会使用不同的缓存技术,提高相应的处理速度。
常用的请求方式有:
get: 请求服务器上指定的资源 post: 向服务器上的资源提交数据 head: 和get相似 put: 上传资源 delete: 删除资源
get请求:
浏览器发送get请求的场景: 1. 在地址栏单纯的输入一个地址 2. a标记产生的请求 3. form表单默认提交方式,也是get请求 注意: 1. get请求,如果带有一些提交数据,比如用户名,密码等。那么这些数据会被添加到地址栏中,不安全。 2. get请求提交的数据量比较小,在4KB以内。 例子: requestMethod? username=zhangsan&password=123456&hobby=book&hobby=music
post:
浏览器发送post请求的场景: 1. form表单的method属性的值为post时。 注意: 要传输给服务器的处理数据都会在正文(http信息数据的body)中存储。相对安全
小贴士:
如果想要提交form表单,两个属性要知道: 1. method属性,用于指定请求方式,默认不写是get请求 2. action属性,是必填项,因为action的值就是地址栏上的url-pattern.
2.2.2 service/doGet/doPost/
实际上:当浏览器发送请求后,会默认执行servlet组件继承过来的service方法,然后service方法里的逻辑:String method = req.getMethod(); 会获取请求的方法,
如果是get请求,会执行doGet(req, resp); 如果是post请求,会执行doPost(req, resp);
上述代码说明:程序员在写servlet时,可以选择覆盖service方法,也可以选择覆盖doGet() 或者是doPost方法。前提如果是get请求,可以直接覆盖doGet(), 如果是post请求,可以直接覆盖doPost()
注意:如果重写了service方法,就不会再执行doGet/doPost方法,除非重写的service方法里调用了doGet/doPost
package com.shuilidianli.web; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class TestMethodServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("-----doGet-------"); PrintWriter pw = resp.getWriter(); pw.println("get"); pw.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("-----doPost-------"); doGet(req,resp); } }
web.xml
<servlet> <servlet-name>test</servlet-name> <servlet-class>com.shuilidianli.web.TestMethodServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/test</url-pattern> </servlet-mapping>
test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post" action="test"> <input type="submit" value="提交"> </form> </body> </html>
2.3 请求对象
web服务器(tomcat容器)在接收到浏览器发送过来的请求后,发送过来的所有通信数据都会被web服务器进行封装和提供。这些信息主要被封装到两个对象上。
一个是HttpServletRequest类型的对象:
1. 浏览器发送的所有数据都会被web服务器封装到HttpServletRequest类型的对象上,此类型提供了相应的方法可以从对象上获取相关的数据。比如请求行的数据、消息头、实体内容(正文、参数值) 2.作用: 读取和设置http的请求数据 取得和设置cookies 实现请求转发 取得路径信息 标识HTTP会话
2.3.1 参数值的获取
不管是get请求提交的少量数据,还是post请求提交的大量的数据。那么服务器端就要接受到这些数据,并处理。
浏览器发送的数据有以下两种情况:
1:1的情况:
localhost:8088/day42_servlet/web?username=zhangsan&password=123456 上述的地址,?后面是要传入到服务端的数据,username对应一个值,password对应一个值
1:N的情况
localhost:8088/day42_servlet/web?username=zhangsan&password=123456&hobby=book&hobby=movie&gender=f 上述的地址,?后面是要传入到服务端的数据,username对应一个值,password对应一个值,gender对应一个值 而hobby对应两个值,hobby与它的值就是1:N的情况
服务端的请求对象提供了相应的获取参数值的方法。
方法1:String getParameter() : 解析:获取的是1对1的参数值, 比如用户名或密码 用法: String value = request.getParameter("key") 注意: 如果没有获取值,那么返回的是null,而不是异常 方法2:String[] getParameterValues(): 解析:获取的是1对多的参数值, 比如 爱好 用法:String[] values = request.getParameter("key") 注意:如果没有获取值,那么返回的是null,而不是异常
参数:浏览器封装的参数是以键值对的形式体现的,比如username=zhangsan. username是参数名,zhangsan是参数值。
注意:input元素的name属性用于指定参数名
2.4 响应对象
一个是HttpServletResponse类型的对象
1.web服务器会对浏览器进行响应,响应的所有数据都会被封装到HttpServletResponse类型的对象上。此类型提供了相关设置方法,可以设置状态行、消息头、实体内容等。 2.作用: 设置客户端的输出内容 设置响应状态码 设置浏览器的解码方式 设置cookies 实现重定向
2.5 中文乱码问题
两处乱码:
第一处: 后端响应浏览器时: response向浏览器返回中文时出现乱码
response.getWriter().println("你好,Servlet");
第二处: post请求时,浏览器向后端发送了中文时出现了乱码
String username = request.getParameter("username"); username=张三 是汉字时
乱码的情况原因很简单,就是编码过程使用的字符集与解码过程使用的字符集不一致造成的,不是逻辑问题。
编码:字符串变成字节数组的形式 "中国"-->[-86,-92,-78,-12,-64,-23] 使用字符手册 UTF8 三个字节对应一个汉字 解码:字节数组变成字符串的形式 [-86,-92,-78,-12,-64,-23]-->"中国" 使用字符手册uncode 两个字节对应一个汉字
浏览器使用post请求方式提交中文时:
1. 确保浏览器的html页面是utf-8编码集 2. 在servlet中(也就是服务端)的service方法的第一行处,使用 request.setCharacterEncoding("utf-8");即可
浏览器使用get请求方式提交中文时:
1. 确保浏览器的html页面是utf-8编码集 2. 因为服务端默认使用iso-8859-1进行解码。我们的解决方式就是在服务端再次使用iso-8859-1进行编码,然后在使用utf-8进行解码。 String username = request.getParameter("username") // byte[] bs = username.getBytes("iso-8859-1") ; //借助string的构造器,重新解码即可 String str = new String(bs,"utf-8");//
服务端向浏览器发送中文乱码情况:
只需要在服务端对中文进行编码前,写入这一行代码即可: response.setContentType("text/html;charset=utf8");
2.6 Servlet调用DAO
第一步:引入第三方资源,比如相关依赖的jar包坐标, mysql驱动,druid数据源
第二步:在resources配置druid.properties
第三步:编写DruidUtil工具类,并测试(里面提供main方法)
第四步:根据ORM关系模型,编写emp表的实体类Emp
第五步:编写相关的Dao接口以及Dao接口的实现类
第六步:编写EmpServlet组件
第七步: 编写web.xml
第八步:File–>Project structure–>Artifacts–>Available Elements–>右键点击项目–>put into output root
第九步:重新部署项目(启动tomcat) 在浏览器上输入地址进行测试
2.7 总结 servlet的运行流程:
1: 浏览器发送地址请求 2: 根据ip和port号定位到tomcat容器 3: tomcat容器根据appName确定项目 4: 然后tomcat查找当前项目下的web.xml配置信息,用url-pattern与地址信息进行匹配 5: 根据两个相同的name找到对应的servlet组件 6: 执行servlet组件里的service方法(执行的是classes里的class文件) 7: 向浏览器发送响应信息。 8:浏览器收到响应信息后会进行解析和显示。
三、 Servlet对路径的处理
3.1 重定向
用户在浏览器输入一个地址,或者点击按钮触发一个请求地址,然后去往服务器端,此时服务端处理完相关计算后,再次向浏览器发送一个302状态和一个新的地址(比如www.baidu.com). 之后浏览器收到了302状态码和一个新的地址,然后浏览器就重新向这个新的地址发送请求。 302: 表示重定向, 当浏览器收到的状态码是302,表示需要重新发送请求,请求地址是和302一起过来的那个新的地址。
适合的场景:
用户使用浏览器触发了一次请求后,然后服务端向浏览器发送一个新的地址,由浏览器自动再次发送一个请求。 比如:添加一个新员工后,然后页面自动显示所有员工信息,包含两次请求 第一次:insert, 用户主动触发的 第二次: select, 是服务端告诉浏览器再次触发 再比如:登录成功后,跳转到主页面(所有员工信息) 第一次: 登录验证(LoginServlet) --调用DAO的checkLogin方法,返回true或者false --如果登录成功,此时应该向浏览器发送响应数据(302,新地址appName/findA11) 第二次: 跳转到主页面(findAllServlet) --调用DAO的findA11方法,查询所有的员工信息,返回Resulset --遍历Resultset,然后使用流对象的println方法,拼接成一个table.响应对象将数据打包,返回给浏览器,浏览器解析成一个table
如何重定向
response.sendRedirect(String url) url: 是重定向的新地址, 该地址可以是任意地址, 302状态码是响应对象自己设置的,不需要程序员设置
重定向的特点:
1. 重定向的地址可以是任何地址 2. 重定向后,浏览器的地址发生了变化 3. 重定向所涉及到的web组件并不共享同一个request和response 4. 重定向前,不可以关闭流 ,即不能调用 pw.close()
3.2 转发
3.2.1 什么是转发
一个web组件(servlet/jsp)将未完成的任务转交给另外一个web(servlet/jsp)组件。
3.2.2 如何转发
步骤1: 绑定数据 request.getAttribute("school","shuilidianli") 步骤2: 获取转发器,同时指定目的地的地址 RequestDispatcher rd = request.getRequestDispatcher("/servlet03"); 步骤3: 开始转发,带上request和response对象 rd.forward(request,response);
3.2.3 转发的特点
转发是服务器的行为 浏览器在这个过程中只有一次行为,路径不会发生任何的变化 转发可以带有数据 request对象中 转发只能在当前项目中进行转发,不能转发外部资源
----未完待续----