- 1.Servlet运行原理
- 1.1 Tomcat详解
- 1.2Tomcat执行流程
- 2.Servlet API详解
- 2.1 HttpServlet
- 2.1.1 核心方法
- 2.2.2 代码示例:处理GET请求
- 2.2.3代码示例:处理POST请求
- 2.2 HttpServletRequest
- 2.2.1核心方法
- 2.2.2打印Hreader信息
- 2.2.3获取GET请求中的参数
- 2.2.4 获取POST请求中的参数(1)
- 2.2.5 获取JSON格式参数
- 2.2.6获取JSON格式参数(2)
- 2.2.7 使用 postman模拟发送请求
- 3.HttpServletResponse
- 设置状态码
- 自动刷新
- 重定向
在Servlet的代码中我们并没有写main方法,那么代码中的doGet代码部分是如何被调用的,这和Tomcat有关。
1.1 Tomcat详解我们代码的实现是在Tomcat基础上运行的。
当浏览器给服务器发送请求的时候,Tomcat作为HTTP服务器,就可以接收到这个请求。
HTTP协议作为一个应用层协议,需要底层协议栈来支持工作:
详细的交互过程:
1.接收请求
(1)用户在浏览器输入一个URL,此时浏览器就会构成一个HTTP请求。
(2)这个HTTP请求会经过网络协议栈逐层封装成二进制比特流,最终通过物理层的硬件设备转换成光电信号/电信号传输出去。
(3)这些承载信息的光信号/电信号通过互联网上的一系列网络设备,最终达到目标主机。
(4)服务器主机收到这些光信号/电信号,又会通过网络协议栈逐层进行分用,层层解析,最终还原HTTP请求,并交给Tomcat进程进行处理(根虎端口号确定进程)。
(5)Tomcat通过Socket读取到这个请求(一个字符串),并按照HTTP请求的格式来解析这个请求,根据请求中的Context Path
确定一个webapp
,再通过Servlet Path
确定一个具体的类,再根据当前请求的方法(GET/POST/…),决定调用这个类的doGet或者doPost等方法,我们的代码中的doGet/doPost方法的第一个参数HttpServletRequest就包含了这个HTTP请求的详细信息。
2.根据请求计算响应
在我们的doGet/doPost方法中,就执行到了我们自己的代码,我们自己的代码会根据请求中的一些信息,来给HttpServletResponse对象设置一些属性,例如状态码,header,body等。
3.返回响应
(1)doGet/doPost执行完毕后,Tomcat就会自动把HttpsServletResponse这个我们刚设置好的对象转换成一个符合HTTP协议的字符串,通过Socket把这个响应发送出去。
(2)此时响应数据在服务器的主机上通过网络协议栈层层封装,最终又得到一个二进制的bit流,通过物理层硬件设备转换成光信号/电信号传输出去。
(3)这些承载信息的光信号/电信号通过互联网上的一系列网络设备,最终到达浏览器所在的主机(需要网络层和数据链路层参与)。
(4)浏览器主机收到这些光信号/电信号,又会通过网络协议栈逐层进行分用,层层解析,最终还原成HTTP响应,并交给浏览器处理。
(5)浏览器也通过Socket读到这个响应(一个字符串),按照HTTP响应的格式来解析这这个响应,并且把body中的数据按照一定的格式显示在浏览器的界面上。
通过代码形式描述Tomcat初始化/处理请求两部分核心逻辑。
1.Tomcat初始化流程
class Tomcat {
// ⽤来存储所有的 Servlet 对象
private List<Servlet> instanceList = new ArrayList<>();
public static void main(String[] args) {
new Tomcat().start();
}
public void start() {
// 根据约定,读取 WEB-INF/web.xml 配置⽂件;
// 并解析被 @WebServlet 注解修饰的类
// 假定这个数组⾥就包含了我们解析到的所有被 @WebServlet 注解修饰的类.
Class<Servlet>[] allServletClasses = ...;
// 这⾥要做的的是实例化出所有的 Servlet 对象出来;
for (Class<Servlet> cls : allServletClasses) {
// 这⾥是利⽤ java 中的反射特性做的
// 实际上还得涉及⼀个类的加载问题,因为我们的类字节码⽂件,是按照约定 的
// ⽅式(全部在 WEB-INF/classes ⽂件夹下)存放的,所以 tomcat 内部是
// 实现了⼀个⾃定义的类加载器(ClassLoader)⽤来负责这部分⼯作。
Servlet ins = cls.newInstance();
instanceList.add(ins);
}
// 调⽤每个 Servlet 对象的 init() ⽅法,这个⽅法在对象的⽣命中只会被调⽤这 ⼀次;
for (Servlet ins : instanceList) {
ins.init();
}
// 利⽤我们之前学过的知识,启动⼀个 HTTP 服务器
// 并⽤线程池的⽅式分别处理每⼀个 Request
ServerSocket serverSocket = new ServerSocket(8080);
// 实际上 tomcat 不是⽤的固定线程池,这⾥只是为了说明情况
ExecuteService pool = Executors.newFixedThreadPool(100);
while (true) {
Socket socket = ServerSocket.accept();
// 每个请求都是⽤⼀个线程独⽴⽀持,这⾥体现了我们 Servlet 是运⾏在多线 程环境下的
pool.execute(new Runnable() {
doHttpRequest(socket);
});
}
// 调⽤每个 Servlet 对象的 destroy() ⽅法,这个⽅法在对象的⽣命中只会被调
⽤这⼀次;
for (Servlet ins : instanceList) {
ins.destroy();
}
}
}
(1)Tomcat的代码中内置了main方法,当我们启动Tomcat的时候,就是从Tomcat的main方法开始执行的。
(2)被@WebServlet
注解修饰的类会在Tomcat启动的时候就被获取到,并集中管理。
(3)Tomcat通过反射的语法机制来创建被@WebServlet
注解修饰的类的实例。
(4)这些实例被创建完了之后,会调用其中的init方法进行初始化(这个方法是HttpServlet是自带的,我们自己写的类可以重写init).
(5)这些实例被销毁之前,会调用其中的destory方法进行收尾(这个方法是HttpServlet自带的,我们自己写的类可以重写destory)
(6)Tomcat内部也是通过Socket API进行网络通信。
(7)Tomcat为了能同时响应多个HTTP请求,采取了多线程的方式实现,因此Servlet是运行在多线程环境下的
2.Tomcat处理请求流程
class Tomcat {
void doHttpRequest(Socket socket) {
// 参照我们之前学习的 HTTP 服务器类似的原理,进⾏ HTTP 协议的请求解析,和响
应构建
HttpServletRequest req = HttpServletRequest.parse(socket);
HttpServletRequest resp = HttpServletRequest.build(socket);
// 判断 URL 对应的⽂件是否可以直接在我们的根路径上找到对应的⽂件,如果找到, 就是静态内容
// 直接使⽤我们学习过的 IO 进⾏内容输出
if (file.exists()) {
// 返回静态内容
return;
}
// ⾛到这⾥的逻辑都是动态内容了
// 根据我们在配置中说的,按照 URL -> servlet-name -> Servlet 对象的链条
// 最终找到要处理本次请求的 Servlet 对象
Servlet ins = findInstance(req.getURL());
// 调⽤ Servlet 对象的 service ⽅法
// 这⾥就会最终调⽤到我们⾃⼰写的 HttpServlet 的⼦类⾥的⽅法了
try {
ins.service(req, resp);
} catch (Exception e) {
// 返回 500 ⻚⾯,表示服务器内部错误
}
}
}
(1)Tomcat从Socket中读到的HTTP请求是一个字符串,然后会按照HTTP协议的格式解析成一个HttpServlet对象。
(2)Tomcat会根据URL中的path判定这个请求是请求一个静态资源还是动态资源,如果是静态资源,如果是静态资源,直接找到对应的文件把文件的内容通过Socket返回,如果是动态资源,才会执行到Servlet的相关逻辑。
(3)Tomcat会根据URL中的Context Path
和Servlet Path
确定要调用哪个Servlet 实例的service方法。
(4)通过service方法,就会进一步调用到自己写的doGet或者doPost.
3.Servlet的service方法实现
(1)Servlet的service方法内部会根据当前请求的方法,决定调用其中的某个doXXX方法。
(2)在调用doXXX方法的时候,就会触发多态机制,从而执行到我们自己写的子类中的doXXX方法。
2.Servlet API详解 2.1 HttpServlet多态:
(1)我们前⾯⾃⼰写的 HelloServlet 类, 继承⾃ HttpServlet 类. ⽽ HttpServlet ⼜继承⾃ Servlet. 相当于 HelloServlet 就是 Servlet 的⼦类. 接下来, 在 Tomcat 启动阶段, Tomcat 已经根据注解的描述, 创建了 HelloServlet 的实例, 然后把这个实 例放到了 Servlet 数组中.
(2) 后⾯我们根据请求的 URL 从数组中获取到了该 HelloServlet 实例, 但是我们是通过 Servlet ins 这 样的⽗类引⽤来获取到 HelloServlet 实例的.
(3) 最后, 我们通过 ins.doGet() 这样的代码调⽤ doGet 的时候, 正是 “父类引用指向⼦类对象”, 此时就 会触发多态机制, 从⽽调⽤到我们之前在 HelloServlet 中所实现的 doGet ⽅法
等价的代码:
Servlet ins = new HelloServlet(); ins.doGet(req, resp);
在写servlet代码的时候,首先第一步就是先创建类,继承HttpServlet,并重写其中的某些方法。
2.1.1 核心方法
1.在实际中我们主要写doXXX方法,很少会重写init/destory/service.
2.这些方法的调用时机,就称为"Servlet生命周期":
HttpServlet的实例只是在程序启动时创建一次,而不是每次收到HTTP请求都重新创建实例。
1.创建MethodServlet.java,创建doGet方法:
2.创建testMethod.html,放到webapp目录中,如下:
一个Servlet程序中可以同时部署静态文件,静态文件就放到webapp目录中即可。
3.数据提交的两种方式:
(1)form表单提交:
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录系统</title>
</head>
<body>
<form action="login" method="post">
<div style="margin-top:50px;margin-left:40%">
<h1 style="padding-left:50px">用户登录</h1>
姓名:<input type="text" name="username">
<p>
密码:<input type="password" name="password">
<p>
<div style="padding-left:50px">
<input type="submit" value="提 交">
<input type="reset" value="重 置">
</div>
</div>
</form>
</body>
</html>
LoginServlet.java:
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("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String result = "未知错误";
// 1.得到参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2.业务处理
// 非空效验
if (null != username && null != password &&
!username.equals("") && !password.equals("")) {
if (username.equals("admin") && password.equals("admin")) {
result = "恭喜:登录成功!";
} else {
result = "登录失败,用户名或密码输入错误,请检查!";
}
} else {
result = "非法参数!";
}
resp.setContentType("text/html; charset=utf-8");
// 3.将结果返回给前端
resp.getWriter().write(result);
}
}
输入正确的用户名和密码:
输入错误的用户名和密码:
(2)ajax提交
Ajax 即 Asynchronous Javascript And XML(异步JavaScript和XML),使用Ajax 不需要刷新整个页面,这使得程序能够更快地回应⽤户的 *** 作。
login-ajax.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录系统</title>
<script src="js/jquery-1.9.1.min.js"></script>
</head>
<body>
<div style="margin-top:50px;margin-left:40%">
<h1 style="padding-left:50px">用户登录</h1>
姓名:<input id="username" type="text" name="username">
<p>
密码:<input id="password" type="password" name="password">
<p>
<div style="padding-left:50px">
<input type="button" value="提 交" onclick="mySubmit()">
<input type="reset" value="重 置">
</div>
</div>
<script>
function mySubmit(){
<!-- 非空效验 -->
var username=jQuery("#username");
var password=jQuery("#password");
if("" == username.val()){
alert("请先输入用户名!")
return;
}
if(""==password.val()){
alert("请先输入密码!");
return;
}
jQuery.ajax({
url:"login",
type:"POST",
data:{"username":username.val(),"password":password.val()},
success:function(data){
alert(data);
}
});
}
</script>
</body>
</html>
关于乱码问题:
如果我们在响应代码中写入中文,例如:
resp.getWriter().write("GET 响应");
此时在浏览器访问的时候,就会看到乱码现象:
我们可以在代码中,通过resp.setContentType("text/html;charset=utf-8");
显式的指定编码方式。
在 MethodServlet.java 中, 新增 doPost ⽅法.
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().write("POST 响应");
}
在 testMethod.html 中, 新增⼀个按钮, 和对应的点击事件处理函数:
<!doctype html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Document</title>
<script src="js/jquery-1.9.1.min.js"></script>
</head> <body> <button type="submit" onclick="sendGet()">发送 GET 请求</button> <br> <button onclick="sendPost()">发送 POST 请求</button> <script>
function sendGet() {
jQuery.ajax({
url: "method",
type: "GET",
// data: {"name": "Java"},
// contentType:"application/json", // 请求参数类型
// dataType: "json", // 响应类型
success: function (data) {
console.log(data)
}
});
}
function sendPost() {
jQuery.ajax({
url: "method",
type: "POST",
// data: {"name": "Java"},
// contentType:"application/json", // 请求参数类型
// dataType: "json", // 响应类型
success: function (data) {
console.log(data)
}
});
}
</script>
</body>
</html>
2.2 HttpServletRequest
2.2.1核心方法
通过这些方法可以获取到一个请求中的各个方面的信息。
请求对象是服务器收到的内容,不应该修改,因此上面的方法也都只是读方法而不是写方法。
MyReqServlet.java:
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.Enumeration;
@WebServlet("/myreq")
public class MyReqServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
StringBuilder builder = new StringBuilder();
// 得到请求的协议和版本号
builder.append("协议:" + req.getProtocol() + "
");
// 得到请求的类型
builder.append("Method:" + req.getMethod() + "
");
// 得到 uri
builder.append("URI:" + req.getRequestURI() + "
");
builder.append("URL:" + req.getRequestURL() + "
");
builder.append("ContextPath:" + req.getContextPath() + "
");
builder.append("QueryString:" + req.getQueryString() + "
");
builder.append("
请求头");
// 得到所有的请求类型(headerNames)和请求值
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) { // 判断还有没有 head name
String headName = headerNames.nextElement();
// 得到 head value
String headValue = req.getHeader(headName);
builder.append(headName + ": " + headValue + "
");
}
builder.append("
");
builder.append("参数:" + req.getParameter("name") + "
");
resp.getWriter().write(builder.toString());
}
}
使用Postman软件查看body:
创建ShowRequest类:
@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
StringBuilder respBody = new StringBuilder();
respBody.append(req.getProtocol());
respBody.append("
");
respBody.append(req.getMethod());
respBody.append("
");
respBody.append(req.getRequestURI());
respBody.append("
");
respBody.append(req.getContextPath());
respBody.append("
");
respBody.append(req.getQueryString());
respBody.append("
");
respBody.append("headers:");
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
respBody.append(headerName + " ");
respBody.append(req.getHeader(headerName));
respBody.append("
");
}
resp.getWriter().write(respBody.toString());
}
}
运行程序,在浏览器输入url地址,可以看到:
GET请求中的参数一般都是通过query string传递给服务器的,形如:
http://localhost:8080/first-servlet/postjson/student?userId=1111&classId=100
此时在浏览器通过query string给服务器传递了两个参数,userId和classid值分别为"userId"和"classid"在服务器端就可以通过getParameter来获取参数的值。
创建GetParameter类:
重新部署程序,在浏览器通过http://127.0.0.1:8080/ServletHelloWorld/getParameter访问,可以看到
当没有query string的时候,getParameter获取的值null,如果通过http://127.0.0.1:8080/ServletHelloWorld/getParameter?userId=123&classId=456 访问, 可以看到:
此时说明服务器以及获取到客户端传递过来的参数。
2.2.4 获取POST请求中的参数(1)getParameter的返回值类型为String,必要时需要手动把String转成int.
使用postman查看GET请求中的参数:
POST 请求的参数⼀般通过 body 传递给服务器. body 中的数据格式有很多种. 如果是采⽤ form 表单的形 式, 仍然可以通过 getParameter 获取参数的值:
创建类JsonPostServlet.java:
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("/postjson")
public class JsonPostServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置返回的类型和编码
resp.setContentType("text/html;charset=utf-8");
String username=req.getParameter("username");
String password=req.getParameter("password");
resp.getWriter().write("username"+username+","+"password"+password);
}
}
testJson.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="postParameter" method="POST">
<input type="text" name="userId">
<input type="text" name="classId">
<input type="submit" value="提交">
</form>
</body>
</html>
使用postman查看:
使⽤之前 getParameter 的⽅式是获取不了 JSON 格式的数据的。
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("/postjson")
public class JsonPostServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置返回的类型和编码
resp.setContentType("text/html;charset=utf-8");
String username=req.getParameter("username");
String password=req.getParameter("password");
resp.getWriter().write("username"+username+","+"password"+password);
}
}
body中带有JSON格式的数据,方法使⽤之前 getParameter不能获取到:
使用InputStream获取JSON参数:
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
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("/postjson")
public class JsonPostServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置返回类型和编码
resp.setContentType("text/html; charset=utf-8");
int length=req.getContentLength();
// 1.得到数据流
ServletInputStream inputStream = req.getInputStream();
// 2.使用数组接收流信息
byte[] bytes = new byte[length];
inputStream.read(bytes);
// 3.将数组转换成字符串(或对象)
String result = new String(bytes, "utf-8");
resp.getWriter().println(result);
}
}
注意: 到⽬前为⽌, 服务器拿到的 JSON 数据仍然是⼀个整体的 String 类型, 如果要想获取到 userId 和 classId 的具体值, 还需要搭配 JSON 库进⼀步解析.
2.2.6获取JSON格式参数(2)java JSON对象 *** 作:
1.阿里巴巴 fast json/fast json2
2.阿帕奇 jackson
(a)将对象转换成JSON字符串。
(b)将JSON字符串转换成对象。
引入Jackson这个库,进行JSON解析:
1.在中央仓库搜索Jackson,选择Jackson Databind:
(1)
把中央仓库中的依赖配置添加到 pom.xml 中:
(2)在项目为了避免写太多的getter和setter方法,有一种更简便的写法。
首先在pom.xml配置lombok:
把lombok依赖复制到pom.xml中:
可以更加简便的使用get和set方法:
安装lombok插件:
使用代码实现json字符串和对象之间的转换:
a.将json对象转换成字符串:
b.将字符串转化为对象:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.ToString;
public class App {
public static void main(String[] args) throws JsonProcessingException {
//1.创建一个json对象
ObjectMapper objectMapper=new ObjectMapper();
// //2.1将对象转换成json字符串
// Student student=new Student();
// student.setId(1);
// student.setName("zhangsan");
// student.setPassword("123");
// String result=objectMapper.writeValueAsString(student);
// System.out.println(result);
//------------2.2将json字符串转换为对象---
String jsonStr="{\"id\":1,\"name\":\"zhangsan\",\"password\":\"123\"}";
Student zhangsan=objectMapper.readValue(jsonStr,Student.class);
System.out.println(zhangsan);
}
@Data
static class Student{
private int id;
private String name;
private String password;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
}
(3)实现获取JSON格式的代码:
JSON后端读取代码:
JsonPostServlet.java:
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
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.HashMap;
@WebServlet("/postjson")
public class JsonPostServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置返回类型和编码
resp.setContentType("text/html; charset=utf-8");
int length=req.getContentLength();
// 1.得到数据流
ServletInputStream inputStream = req.getInputStream();
// 2.使用数组接收流信息
byte[] bytes = new byte[length];
inputStream.read(bytes);
// 3.将数组转换成字符串(或对象)
String result = new String(bytes, "utf-8");
System.out.println(result);
//4.字符串转换成对象(或字典)
ObjectMapper objectMapper=new ObjectMapper();
HashMap<String,String> map=objectMapper.readValue(result,HashMap.class);
System.out.println("用户名:"+map.get("username"));
System.out.println("密码:"+map.get("password"));
resp.getWriter().println("用户名:"+map.get("username")+"|密码:"+map.get("password"));
}
}
JSON前端请求代码:
login-ajax-json.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录系统</title>
<script src="js/jquery-1.9.1.min.js"></script>
</head>
<body>
<div style="margin-top:50px;margin-left:40%">
<h1 style="padding-left:50px">用户登录</h1>
姓名:<input id="username" type="text" name="username">
<p>
密码:<input id="password" type="password" name="password">
<p>
<div style="padding-left:50px">
<input type="button" value="提 交" onclick="mySubmit()">
<input type="reset" value="重 置">
</div>
</div>
<script>
function mySubmit(){
<!-- 非空效验 -->
var username=jQuery("#username");
var password=jQuery("#password");
if("" == username.val()){
alert("请先输入用户名!")
username.focus();
return;
}
if(""==password.val()){
alert("请先输入密码!");
return;
}
jQuery.ajax({
url:"postjson",//设置请求地址
type:"POST",//设置请求方法类型
contentType:"application/json; charset=utf-8",//请求类型
//dataType:"",//响应的类型
//将对象转换成json字符串
data:JSON.stringify({"username":username.val(),"password":password.val()}),
success:function(data){
alert(data);
}
});
}
</script>
</body>
</html>
注意:
(1)Jackson 库的核⼼类为ObjectMapper
. 其中的readValue
⽅法把⼀个 JSON 字符串转成 Java 对象. 其中的writeValueAsString
⽅法把⼀个 Java 对象转成 JSON 格式字符串.
(2)readValue
的第⼆个参数为 JsonData 的 类对象. 通过这个类对象, 在 readValue 的内部就可以借助 反射机制来构造出 JsonData 对象, 并且根据 JSON 中key 的名字, 把对应的 value 赋值给 JsonData 的对应字段.
使用Fiddler抓包:
postman常用方法:
核心方法:
设置状态码注意:
响应对象是服务器要返回给浏览器的内容, 这⾥的重要信息都是自己设置的. 因此上⾯的⽅法都 是 “写” 方法.
对于状态码/响应头的设置要放到 getWriter / getOutputStream 之前. 否则可能设置失效.
实现一个程序,用户在浏览器通过参数指定要返回响应的状态码。
state=200:
使用Fiddler抓包:
state=404:
state=500:
1.实现一个程序,让浏览器每秒钟自动刷新一次,并显示当前的时间戳。
RefreshServlet.java:
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.time.LocalDateTime;
@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Refresh","1");
resp.getWriter().println(""+LocalDateTime.now());
}
}
重定向2.配置servlet的jdk版本:
(1) project:
(2)Modules:
(3)java Compiler:
(4)pom.xml:
实现一个程序,返回一个重定向HTTP响应,自动跳转到另外一个页面。
1.第一个例子:
LoginServlet.java:
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("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String result = "未知错误";
// 1.得到参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 2.业务处理
// 非空效验
if (null != username && null != password &&
!username.equals("") && !password.equals("")) {
if (username.equals("admin") && password.equals("admin")) {
result = "恭喜:登录成功!";
} else {
result = "登录失败,用户名或密码输入错误,请检查!";
}
} else {
result = "非法参数!";
}
resp.setContentType("text/html; charset=utf-8");
// 3.将结果返回给前端
resp.getWriter().write(result);
}
}
MainServlet.java:
import utils.StringUtils;
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("/main")
public class MainServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String token = req.getParameter("token");
if (!StringUtils.hasLength(token) && "admin".equals(token)){
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("欢迎您:系统管理员!");
}else{
//未授权,调转到登录页面
resp.sendRedirect("http://localhost:8080/first-servlet/login.html");
}
}
}
运行结果:
如果用户名错误就会重定向到登录页面:
用Fiddler抓包观察重定向:
2.第二个例子:
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("/redirectServlet")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.sendRedirect("http://www.sogou.com");
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)