网站开发--详解Servlet(上)
https://developer.aliyun.com/article/1480770?spm=a2c6h.13148508.setting.14.5f4e4f0ejwri0Q
💕"Echo"💕
作者:Mylvzi
文章主要内容:网站开发–详解Servlet
2.获取请求报文中的query string**
query string,译为查询字符串,往往和用户的关键信息相关(登录密码),在日常的开发中,我们也经常利用到query string来完成一些业务上的逻辑,所以获取请求报文中的query string是一个很频繁且重要的操作
query string在请求报文中的位置是不固定的,具体位置取决于请求报文中的方法(method),如果方法是Get,query string就位于URL之中,如果方法是Post,query string就位于body之中
注意:实际上URL中是包含query string的,但是在servlet的getURL类似的方法中返回的是一个不携带query string的URL(可能是因为查询字符串这个操作过于频繁,就单独拿出来进行包装了)
1.方法为Get
说明:前后端交互的一个关键点在于前端和后端要对传输内容的格式都了然于胸,后端要知道前端是如何组织数据进行传输的
比如,规定好客户端发送的请求报文中的query string的格式是类似于:
username=zhangsan&password=123456
那么服务器这边就可以规定好的格式进行解析
代码演示:
@WebServlet("/request2") public class GetRequestParameter extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取用户传输过来的query string // 假设用户传输过来的query string的格式是形如 username='lisi'&password='123'这样的形式 // servlet会自动将query string中的所有内容存储到一个Map结构之中(键值对都存储到其中 // 后端程序员只需通过getParameter()方法来获取具体的值即可 // 注意你构造的query string内部不需要有引号!!! // 可以根据这个特性来完成很多操作 比如判断用户名是否正确 // 在传输中文的时候最好传输urlencode之后的内容 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println("username=" + username); System.out.println("password=" + password); } }
当在浏览器中输入:“http://127.0.0.1:8080/testsevlet/request2?username=zh&password=123”
在终端上显示:
如果不添加query string,显示的结果就是null
总结:
对于Get方法的请求,query string位于首行中,直接使用getParameter方法,并制定参数,就能获取到对应的值
2.方法为Post
此时query string位于body之中,而body的传输是有不同的格式的,对于不同格式的body,要采用不同的方法来进行解析,获取query string,常用的body格式有两种:
- form表单
- json
1.form表单格式
body通过form表单来进行数据的组织,内部是键值对,Content-Type:application/x-www-form-urlencoded
获取body中的内容和上面获取query string的方法一致
通过postman发送一个post请求
服务器的代码不变,打印结果为:
总结:如果body的格式是form表单,虽然此时query string位于body之中,但是也可以直接使用**getParameter()**方法,并指定参数来获取要查询的内容
2.json格式
如果body是通过json格式来进行组织,原生的Servlet是不支持解析json格式的数据的,此时需要进入第三方库jackson
来帮助进行json格式数据解析(jackson也是spring官方推荐的用于解析JSON格式数据的第三方库)
准备:引入jackson依赖
在maven中找到jackson,选择合适的版本进行路径的复制,并在项目中的pom.xml中引入
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.0</version> </dependency>
引入好依赖之后就可以使用jackson中的api解析json格式的数据
具体的操作依赖于一个类和两个核心方法:
ObjectMapper(对象映射器),是JSON数据与Java对象转换的核心枢纽,在交互时,通过JSON字符串进行网络传输,处理逻辑,使用Java对象
站在服务器的角度,我们收到的数据是JSON字符串,需要将其转化为Java对象(read放哪发),来完成一些业务上的逻辑,完成后,还需要将处理好的Java对象转化为JSON字符串(write方法)
1.创建一个类 用于接收JSON字符串
// 创建一个类 用于接收JSON字符串 class Request { public String username; public String password; }
2.交互
// 创建出ObjectMapper实例 private ObjectMapper objectMapper = new ObjectMapper(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1.将JSON字符串转化为Java对象 Request request = objectMapper.readValue(req.getInputStream(),Request.class); // 2.获取query string String username = request.username; String password = request.password; // 3.打印 String user = "username=" + username + "<br>password=" + password; System.out.println(user); // 4.将打印的结果传输给客户端 // 这个方法就是和上面的read方法相反 // 这里把Java对象转化为json字符串,传输给客户端 String respBody = objectMapper.writeValueAsString(user); resp.getWriter().write(respBody); }
3.发送请求并打印结果
objectMapper.readValue()内部做了很多工作,最终的结果是把JSON字符串转化为Request的Java对象,内部具体实现细节为:
- 根据请求报文的输入流(就是方法的第一个参数)获取到请求报文中的body部分的所有内容
- 按照JSON格式进行解析,并把解析出来的所有的键值对都存储到一个Map之中
- 通过第二个参数(反射)来明确要转化的Java对象,拿着Java对象中的属性从Map之中寻找对应的值,并把对应的值赋给赋给创建出来的Java对象
通过以上三步就完成了JSON字符串到Java对象的转化,举一个简单的例子
以上就是关于HttpRequestServlet的所有内容,可以观察到,这个类中大部分方法都是get方法,主要原因是因为我们是想通过这个类获取到客户端发送的请求报文,而不是去修改请求报文,所以不需要设置set方法,而在下面要介绍的HttpResponseServlet类中,更多的方法就是set方法(服务器这边要返回一个响应报文)
三.HttpResponseServlet
常用方法:
setStatus() 设置状态码
@WebServlet("/status") public class StatusServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // resp.setStatus(404);// 此时响应报文的状态码就被设置为404 // 如果只传输上述的状态码 浏览器是空白界面 不会有任何信息 // 我们一般看到的都是有一个"错误界面" // 可以通过 resp.sendError(404,"你小子搜的是什么资源???"); // 这里面就比较的灵活了 // 根据一定的逻辑 来灵活的输出状态码信息 } }
当需要发送报错信息时,更推荐使用第二种方式,更加灵活
结果显示:
setHeader 在头部中设置一些属性
自动刷新
每间隔1s就自动刷新界面,利用header中的refresh字段
@WebServlet("/refresh") public class RefreshServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setHeader("refresh","1");// 1s 后自动刷新界面 resp.getWriter().write("" + System.currentTimeMillis()); } }
sendRedirect() 构造重定向
当状态码是3xx时,就代表要进行重定向,利用sendRedirect方法可以直接跳转
@WebServlet("/redirect") public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // // 一个重定向的报文包含两部分:状态码 和 要跳转的界面 // resp.setStatus(302);// 核心是要有对应的状态码(以3开头),以及要跳转的界面(Location字段) // resp.setHeader("Location","https://sogou.com");// 此时就会自动跳转到搜狗界面 // 上述写法比较繁琐 一般来说会使用下面这个方法来设置一个跳转的响应报文 resp.sendRedirect("https://sogou.com"); } }
不仅可以通过服务器这边设置跳转的界面,还可以在前端中使用JS定时器来实现相同的效果
<!DOCTYPE html> <html> <head> <title>页面跳转示例</title> <script> // 在页面加载后,等待 3 秒后跳转到新页面 window.onload = function() { setTimeout(function() { window.location.href = "https://www.sogou.com"; }, 3000); // 3 秒 }; </script> </head> <body> <h1>页面将在 3 秒后跳转到搜狗主页</h1> </body> </html>
以上就是<<网站开发–详解Servlet>>的所有内容,重点掌握三个类的api的基本用法,多多使用就能融会贯通,实现更复杂的交互!