JavaWeb:(练习)十一、Servlet数据交互与Session技术最终优化练习
JavaWeb:(练习)十一、Servlet数据交互与Session技术最终优化练习
一、练习目标
使用过滤器与Web会话跟踪机制优化练习八、练习九、练习十。
练习八链接:JavaWeb:(练习)八、Servlet前端发送数据到后端练习
练习九链接:JavaWeb:(练习)九、Servlet数据交互、XMLHttpRequest、JSON、AJAX、AXIOS练习
练习十链接:JavaWeb:(练习)十、Servlet数据交互与过滤器与Web会话跟踪机制练习
目标:制作一个前端登录界面,制作一个简单的web服务器,连接数据库,验证从前端界面提交的表单数据。
二、最终优化说明
在经过练习八、练习九、练习十的逐步学习过程后,一步一步开发出基于Servlet及其他相关技术的前后端数据交互的登录界面,并且逐步优化。
在本次联系优化中,主要基于Session技术,安全的保护客户端的数据,使用过滤器等,增加验证,保护数据安全。
三、代码优化
1、前端代码
1)common.js
var serverPath = "http://127.0.0.1:8080/WebBack";
axios.defaults.withCredentials = true;
2)login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>登录</title>
<style type="text/css">
body{
background-image: url(img/login_bg.jpg);
background-size: 100%;
}
.box{
background-color: whitesmoke;
width: 400px;
height: 300px;
border-radius: 30px;
margin: auto;
margin-top: 200px;
text-align: center;
}
span,input{
float: left;
}
.account_label_class,.password_label_class{
margin-top: 40px;
margin-left: 40px;
}
.account_class,.password_class,.account_tips_class,.password_tips_class{
margin-top: 40px;
margin-left: 10px;
}
.submit_button_class{
width: 80px;
height: 40px;
background-color: skyblue;
border-radius: 10px;
margin-left: 160px;
margin-top: 40px;
}
</style>
<script src="js/axios.min.js" type="text/javascript" charset="UTF-8"></script>
<script src="js/common.js" type="text/javascript"></script>
<script type="text/javascript">
function login(){
var account = document.getElementById("account_id").value;
var password = document.getElementById("password_id").value;
//表单验证
// 使用 axios 技术
axios.post(serverPath + "/login",
"account=" + account + "&password=" + password)
.then( function(resp) {
console.log(resp.data.name);
console.log(resp.data.password);
if (resp.data == 0) {
document.getElementById("account_tips_id").innerHTML = "不正确";
} else {
sessionStorage.setItem("name",resp.data.name);
sessionStorage.setItem("password",resp.data.password);
location.assign("main.html");
}
})
}
</script>
</head>
<body>
<div class="box">
<form action="http://127.0.0.1:8080/WebBack/login" method="get" >
<span class="account_label_class">账户:</span>
<input type="text" name="account_name" id="account_id" class="account_class" />
<span class="account_tips_class" id="account_tips_id"></span>
<div style="clear: left;"></div>
<br />
<span class="password_label_class">密码:</span>
<input type="password" name="password_name" id="password_id" class="password_class" />
<span class="password_tips_class"></span>
<div style="clear: left;"></div>
<br />
<input type="button" value="登录" class="submit_button_class" onclick="login()" />
<!-- <input type="submit" value="登录" class="submit_button_class" /> -->
</form>
</div>
</body>
</html>
3)main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/axios.min.js" type="text/javascript"></script>
<script src="js/common.js" type="text/javascript"> </script>
<script type="text/javascript">
function show(){
axios.get(serverPath + "/back/student").then(function(resp){
if (resp.data == 2) {
alert("登录失效");
location.replace("login.html");
} else {
var name = sessionStorage.getItem("name");
var password = sessionStorage.getItem("password");
if (name == null ) {
location.replace("login.html");
return;
}
document.getElementById("name").innerHTML = name;
document.getElementById("password").innerHTML = password;
}
});
}
function test(){
axios.get(serverPath + "/back/student").then(function(resp){
if (resp.data == 2) {
alert("登录失效");
location.replace("login.html");
}
});
}
function logOut() {
axios.get(serverPath + "/back/logout").then(function(resp){
alert("退出登录");
// location.replace("login.html");
});
}
</script>
</head>
<body onload="show()">
<h1>登陆后页面</h1>
账户:<span id="name"></span> <br />
密码:<span id="password"></span> <br />
<input type="button" value="测试" onclick="test()" /> <br />
<input type="button" value="退出" onclick="logOut()" />
</body>
</html>
2、后端代码-model包
User.java
package com.ffyc.webback.model;
public class User {
private String name;
private String password;
public User() {
}
public User(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
3、后端代码-Dao包
LoginDao.java
package com.ffyc.webback.Dao;
import com.ffyc.webback.model.User;
import java.sql.*;
public class LoginDao {
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/feifan_test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
// 数据库的用户名与密码,需要根据自己的设置
static final String USER = "root";
static final String PASS = "root";
public static User getUserObject(String name, String password){
Connection conn = null;
Statement stmt = null;
User user = null;
try{
// 打开链接
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL,USER,PASS);
// 执行查询
// 实例化Statement对象
stmt = conn.createStatement();
PreparedStatement ps = conn.prepareStatement("SELECT * FROM usertest WHERE name = ? AND password = ?");
ps.setObject(1,name);
ps.setObject(2,password);
ResultSet rs = ps.executeQuery();
// 将数据添加进集合中
while(rs.next()){
user = new User();
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
}
// 完成后关闭
rs.close();
stmt.close();
conn.close();
return user;
}catch(SQLException se){
// 处理 JDBC 错误
se.printStackTrace();
return user;
}catch(Exception e){
// 处理 Class.forName 错误
e.printStackTrace();
return user;
}finally{
// 关闭资源
try{
if(stmt!=null) {
stmt.close();
return user;
}
}catch(SQLException se2){
}// 什么都不做
try{
if(conn!=null) {
conn.close();
return user;
}
}catch(SQLException se){
se.printStackTrace();
return user;
}
}
}
}
4、后端代码-servlet包
1)LoginServlet.java
package com.ffyc.webback.servlet;
import com.ffyc.webback.Dao.LoginDao;
import com.ffyc.webback.model.User;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println("doGet");
resp.setContentType("text/html;charset=utf-8");
// 得到表单数据
String name = req.getParameter("account");
String password = req.getParameter("password");
System.out.println(name + "-------------" + password);
User user = LoginDao.getUserObject(name, password);
System.out.println(user);
// if (user == null) {
// resp.getWriter().println(0);
// } else {
// 会话机制
HttpSession session = req.getSession();
System.out.println("doGet" + session.getId());
session.setAttribute("user",user);
Gson gson = new Gson();
// 把 user 对象转为 json 对象,发送给html前端
String json = gson.toJson(user);
resp.getWriter().println(json);
// }
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println("doPost");
resp.setContentType("text/html;charset=utf-8");
// 得到表单数据
String name = req.getParameter("account");
String password = req.getParameter("password");
System.out.println(name + "-------------" + password);
User user = LoginDao.getUserObject(name, password);
System.out.println(user);
if (user == null) {
resp.getWriter().println(0);
} else {
// 会话机制
HttpSession session = req.getSession();
System.out.println("doPost" + session.getId());
session.setAttribute("user",user);
Gson gson = new Gson();
// 把 user 对象转为 json 对象,发送给html前端
String json = gson.toJson(user);
resp.getWriter().println(json);
}
}
}
2)StudentServlet.java
package com.ffyc.webback.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class StudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
System.out.println("doPost" + session.getId());
System.out.println("学生管理操作");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
System.out.println("doPost" + session.getId());
System.out.println("学生管理操作");
}
}
3)LogOutServlet.java
package com.ffyc.webback.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LogOutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("退出操作");
req.getSession().invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("退出操作");
req.getSession().invalidate();
}
}
5、后端代码-filter包
1)CorsFilter.java
package com.ffyc.webback.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CorsFilter implements Filter {
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
System.out.println("跨域过滤器");
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
//允许携带Cookie时不能设置为* 否则前端报错
httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("origin"));//允许所有请求跨域
httpResponse.setHeader("Access-Control-Allow-Methods", "*");//允许跨域的请求方法GET, POST, HEAD 等
httpResponse.setHeader("Access-Control-Allow-Headers", "*");//允许跨域的请求头
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");//是否携带cookie
filterChain.doFilter(servletRequest, servletResponse);
}
}
2)EncodingFilter.java
package com.ffyc.webback.filter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
String charset;
//init()
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("编码过滤器初始化");
charset = filterConfig.getInitParameter("charset");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("编码过滤器");
servletRequest.setCharacterEncoding(charset);
filterChain.doFilter(servletRequest,servletResponse);
}
//destroy()
}
3)IsLoginFilter.java
package com.ffyc.webback.filter;
import com.ffyc.webback.model.User;
import com.sun.deploy.net.HttpRequest;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class IsLoginFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("失效验证过滤器");
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpSession session = request.getSession();
User user = (User)session.getAttribute("user");
if (user == null) {
servletResponse.getWriter().print(2);
} else {
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
6、配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 登录 -->
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.ffyc.webback.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<!-- 学生管理(测试) -->
<servlet>
<servlet-name>student</servlet-name>
<servlet-class>com.ffyc.webback.servlet.StudentServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>student</servlet-name>
<url-pattern>/back/student</url-pattern>
</servlet-mapping>
<!-- 退出登录 -->
<servlet>
<servlet-name>logOut</servlet-name>
<servlet-class>com.ffyc.webback.servlet.LogOutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>logOut</servlet-name>
<url-pattern>/back/logout</url-pattern>
</servlet-mapping>
<!-- 编码过滤器 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.ffyc.webback.filter.EncodingFilter</filter-class>
<init-param>
<param-name>charset</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 跨域过滤器 -->
<filter>
<filter-name>cross</filter-name>
<filter-class>com.ffyc.webback.filter.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cross</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 失效过滤器 -->
<filter>
<filter-name>isLogin</filter-name>
<filter-class>com.ffyc.webback.filter.IsLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>isLogin</filter-name>
<url-pattern>/back/*</url-pattern>
</filter-mapping>
</web-app>