运行后在网页中输入如下内容:
点击回车,我们发现这里并没有显示我们刚输入的值,则证明为post请求方式:
控制台输出:
验证成功说明上述方法对于post请求和get请求均适用!
既然代码都是完全相同的,那么我们不必同样的代码书写两边,修改如下:
//当为post请求方式时,我们只需要调用doget方法 this.doGet(req,resp);
验证如下:
运行后在网页中输入如下内容:
回车,确实为post请求方式:
控制台输出:
这样也能够正确使用不同的请求方式,并且这种方式代码量更少!
解决中文乱码问题:
当我们在表单中填写的值为中文时,会出现乱码问题,而这种乱码问题与请求方式是没有关系的,无论是post还是get都会出现乱码问题
举例:
控制台输出:
解决POST请求方式出现的乱码问题:使用setCharacterEncoding设置字符输入流
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("/demo4") public class Myservlet4 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ //一定要写在第一行!!! req.setCharacterEncoding("UTF-8");//设置字符输入流的编码 String username=req.getParameter("username"); System.out.println(username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
乱码问题被解决:
如果还没有解决的小伙伴请检查自己web文件中的请求方式是不是错写成get了,或者可以试试设置为GBK
解决GET请求方式出现的乱码问题:
如下所示:
<configuration> <uriEncoding>${project.build.sourceEncoding}</uriEncoding> </configuration>
Request请求转发:
请求转发[forword]:一种在服务器内部的资源跳转方式
实现方式:req.getRequestDispatcher("资源B路径").forword(req,resp);
举例:
新创建Myservlet5类:
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("/demo5") public class Myservlet5 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("demo5............."); //请求转发---我们所能改变的内容为转发的资源路径,也就是下一个要执行的servlet类 req.getRequestDispatcher("/demo6").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
新创建Myservlet6类:
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("/demo6") public class Myservlet6 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("demo6............."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
打开浏览器访问demo5,控制台输出如下:
请求转发资源共享数据,使用Request对象:
void setAttribute(String name,Object o):存储数据到request域中 Object getAttribute(String name):根据key,获取值 void removeAttribute(String name):根据key,删除该键值对
在上述创建的Myservlet5和Myservlet6的基础上进行如下步骤:
举例:
1:在Myservlet5中添加数据
在Myservlet6中添加下述代码:
打开浏览器访问demo5,控制台输出:
请求转发特点:
浏览器地址栏路径不发生变化 只能转发到当前服务器的内部资源 一次请求,可以在转发的资源间使用request共享数据
Response(响应):
Response:设置响应数据功能介绍
响应数据分为3部分:
1:响应行:HTTP/1.1 200 OK
void setStatus(int sc):设置响应状态码
2:响应头:Content-Type:text/html
void setHeader(String name,String value):设置响应头键值对
3:响应体<html><head><head><body></body></html>
PrintWriter getWriter():获取字符输出流 ServeltOutputStream getOutputStream():获取字节输出流
重定向:一种资源跳转方式
实现方式:
resp.setStatus(302); resp.setHeader("location","资源B的路径");
举例:
创建MyResponse1类:
package Response; 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("/res1") public class MyResponse1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("res1.........."); //重定向 //1:设置响应状态码:302 resp.setStatus(302); //设置响应头Location resp.setHeader("Location","res2"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); }
创建MyResponse2类:
package Response; 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("/res2") public class MyResponse2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("res2.........."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
当在浏览器访问res1:
回车,重定向至res2:
控制台输出:
如果有小伙伴的控制台只输出了res1,如下所示:
错误的原因为:响应头的路径书写错误,有可能是多加了“/”,有可能是忘记写虚拟路径,也就是项目的名称,我这里没写项目名称的原因是因为我的IDE为2021版本的,可以直接写另一个资源的名称
resp.setHeader("Location","res2");
除了上述方法可以进行重定向外,我们还可以使用下述这种简化的方式进行重定向,这种方法的输出结果上述完全相同
resp.sendRedirect("res2");
重定向的特点:
1:浏览器地址栏路径发生变化—>在上述案例中我们已经指出了
2:可以重定向到任意位置的资源(服务器内部,外部均可)
上述案例的资源即为服务器内部,我们也可以将其定位到服务器外部,如下所示,我们将重定向的路径定位至百度:
resp.sendRedirect("https://www.baidu.com/");
浏览器依然访问res1资源:
点击回车,浏览器地址栏路径发生不仅变为了百度的网址,而且页面也是跳转到了百度
3:两次请求,不能在多个资源使用request共享数据
由于浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据
Resopnse响应字符数据:
使用:
1:通过Response对象获得字符输出流
PrintWriter writer=resp.getWriter();
2:写数据
writer.writer("aaa");
举例:
新建servlet类:
package Response; 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.io.PrintWriter; @WebServlet("/res3") public class MyResponse3 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取字符输出流 //该流不需要关闭,当最后程序结束时,response对象被销毁的时候,该流自动关闭 PrintWriter writer=resp.getWriter(); writer.write("aaa"); writer.write("<h1>aaa</h1>"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
浏览器打开运行:
这样看似好像没什么问题,但仔细看,我们写入的<h1>aaa<h1>
的标签本质是想将其以标题的形式显示,但是这里并非如此,而是将其按照文本直接输出了,针对上述问题,解决方法如下:
//将其解析为html文件 resp.setHeader("content-type","text/html");
显示如下:
解决中文乱码问题:
上述实例中,我们所写的字符都是英文的,那么如果是中文的,会出现乱码问题吗?
测试如下:
writer.write("你好");
输出如下所示:
我们看到,你好此时被解析为了两个问号
针对上述问题的解决方法如下:
在doGET方法的第一行加入下述代码:
resp.setContentType("text/html;charset=utf-8");
输出如下:乱码被解决
Resopnse响应字节数据:
1:通过Response对象获取字符输出流
ServletOutputStream outputStream=resp.getOutputStream();
2:写数据
outputStream.write(字节数据);
举例:
package Response; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; @WebServlet("/res4") public class MyResponse4 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //读取文件 FileInputStream fileInputStream = new FileInputStream("E://开心的微笑.jpg"); //获取response字节输出流 ServletOutputStream os = resp.getOutputStream(); //完成流的copy byte[] buff = new byte[1024]; int len = 0; while ((len = fileInputStream.read(buff)) != -1) { os.write(buff, 0, len); } fileInputStream.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
访问res4资源,显示如下:
上述流的copy只是为了巩固基础,为了简化代码,我们可以直接使用工具类,步骤如下:
首先在pom.xml文件中导入下述依赖:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
2:将上述中流copy的部分改为下述代码:
IOUtils.copy(fileInputStream,os);
在浏览器中再次访问res4资源,发现依然可以成功输出,但下述这种方式明显简单许多: