html: 链接标签, 点击跳转
js代码: window.location.href = "跳转路径";
服务端Servlet跳转页面:
url路径没有变
只有一次http请求
(1) url会发生变化
(2) 两次http请求
客户端js代码发送ajax异步请求
使用主流前端框架实现 Vue.js(前端js框架, dom元素和变量等双向绑定) + axios(发ajax框架)
请求数据, 响应数据格式: json(Content-Type绑定的body中的数据类型)
var person = {
firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
java 代码完成对象和 json 字符串转变为 java 对象
// 反序列化. 把json 字符串转变为 java 对象
String s ="{\"username\":\"猴哥和我\",\"password\":\"救救我\"}";
User u2 = mapper.readValue(s, User.class);
// 序列化, 把 java对象转变为 json 对象
String json = mapper.writeValueAsString(user);
对于HttpServletRequest, 回去请求数据:
application/json: 使用 json 框架来解析
文件上传: 把输入流二进制获取就是获取文件
登录页面 + 后端登录功能, 存在问题?
未登录不允许访问:
前段页面 | 跳转到登录页面 |
---|---|
后端接口(Servlet) | 返回 401 状态码 (Unauthorized未授权访问)/ 返回json数据 |
Session 和 Cookie
目前比较好的解决方案: Filter
其他方案:
(1)提供一个校验用户是否登录的接口, 每次前段都请求
(2)每个Servlet都去验证一下用户是否登录
Main
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws JsonProcessingException {
// 序列化, 把 java对象转变为 json 对象
ObjectMapper mapper = new ObjectMapper();
User user = new User();
user.setUsername("猴哥");
user.setPassword("救救我");
String json = mapper.writeValueAsString(user);
System.out.println(json);
// 反序列化. 把json 字符串转变为 java 对象
String s ="{\"username\":\"猴哥和我\",\"password\":\"救救我\"}";
User u2 = mapper.readValue(s, User.class);
System.out.println(u2);
// 反序列化, json键必须对应类中的成员变量, 找不到就会报错
// String s3 = "{\" username1\":\"猴哥和你\",\"password\":\"救救我\"}";
// User u3 = mapper.readValue(s3, User.class);
// System.out.println(u3);
}
}
login.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面title>
head>
<body>
<h2>登录页面h2>
<form action="login" method="post">
用户名:<input type="text" name="username">
<br><br>
密码:<input type="password" name="password">
<br><br>
<input type="submit" value="登录">
form>
<br><br>
<button onclick="goto()">点我跳转button>
<br><br>
<button onclick="goto2(1)">服务端转发button>
<button onclick="goto2(2)">服务端重定向button>
body>
<script>
function goto() {
window.location.href = "home.html";
}
function goto2(type) {
window.location.href = "goto?type=" + type;
}
script>
html>
home.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>登录成功h1>
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;
import java.io.PrintWriter;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html");
// 解析请求: header, method, url, 请求数据
// 通过键获取值, 如果改键没有值, 返回 null
String username = req.getParameter("username");
String password = req.getParameter("password");
PrintWriter pw = resp.getWriter();
// 数据库根据客户端用户输入的账号密码, 查询有没有该数据
// 简单的模拟
if ("abc".equals(username) && "123".equals(password)) {
pw.println("欢迎你 "
+ username + "");
} else {
pw.println("用户名或密码错误"
);
}
}
}
GotoServlet.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("/goto")
public class GotoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("UTF-8");
// resp.setCharacterEncoding("UTF-8");
// 解析请求数据: 键为type, 为1转发. 为2重定向
String type = req.getParameter("type");
if ("1".equals(type)) {
// 转发
req.getRequestDispatcher("home.html")
.forward(req, resp);
} else {
// 重定向
resp.sendRedirect("home.html");
}
}
}
login2.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录title>
head>
<body>
<h2>用户登录h2>
<div id="app">
用户名:<input type="text" v-model="username">
<br><br>
密码:<input type="password" v-model="password">
<br><br>
<button v-on:click="login()">登录button>
{
{msg}}p>
div>
<script src="https://cdn.jsdelivr.net/npm/vue">script>
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<script>
new Vue({
el: "#app",
data: {
username: "",
password: "",
msg: false
},
methods: {
login: function () {
let vm = this;
this.msg = false;
// alert("用户名:"+this.username+"\n密码:"+this.password)
//Content-Type:application/json, 请求数据为json字符串(body)
axios.post("login2",{
username: vm.username,
password: vm.password
}).then(function (resp) {
// 200 状态码执行
// 获得响应体
// console.log(resp)
let json = resp.data;
if (json.ok) {
// 业务操作成功, 页面跳转
window.location.href="home.html";
} else {
// 业务操作失败, 显示错误信息
alert("错误码:" + json.code + "\n错误信息:" + json.msg);
vm.msg = json.msg;
}
}).catch(function (err) {
console.error(err)// 打印对象
console.error(JSON.stringify(err))
})
}
}
})
script>
body>
html>
Login2Servlet.java
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.demo.User;
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.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@WebServlet("/login2")
public class Login2Servlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Servlet 返回json字符串, 统一代码
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json");
/**
* 1. 解析请求数据
* (1) request.getParameter("键") 获取值
* queryString, body格式 和 queryString 一样
* (2) 请求头 Content-Type 为 application/json
* 此时请求体 (body) 为json字符串
* request.getInputStream()获取属土流
* 通过输入流来获取body数据
*/
// 目前是 json 字符串作为请求体内容, 需要反序列化为 java对象
ObjectMapper mapper = new ObjectMapper();
// 通过 request 获取输入流(包含body数据)
InputStream is = req.getInputStream();
// 请求数据反序列化为java对象, 其实就是用户输入的数据
User input = mapper.readValue(is, User.class);
PrintWriter pw = resp.getWriter();
Map<String, Object> map = new HashMap<>();
// 2. 根据请求数据执行业务
if ("abc".equals(input.getUsername()) && "123".equals(input.getPassword())) {
// 业务操作成功, 有些接口需要返回业务数据
map.put("ok", true);
} else {
// 业务操作失败, 返回错误码(开发人员), 错误信息(用户看)
map.put("ok", false);
map.put("code", "LOG001");
map.put("msg", "用户名或密码错误");
}
// 3. 返回响应的业务数据
pw.println(mapper.writeValueAsString(map));
}
}