【JavaWeb开发】前后端交互万字总结

目录

一. 服务器

二. Servlet程序

三. http请求

▐ get请求

▐ post请求

四. 过滤器 

➱ 创建过滤器(以编码过滤器为例)

五. 同步请求与异步请求

同步请求

异步请求

▐ 跨域问题

后端解决

▐ Axios框架

在普通html中导入axios

在vue项目中安装axios

六. JSON数据格式

七. 路由导航守卫

八. Web会话跟踪

▐ 理论流程

▐ 代码实现


一. 服务器


▐ 什么是服务器?

服务器是一个容器,是一个连接用户与程序之间的中间件,严格意义上的服务器指的是一款软件,里面可以放置文件,让别人可以远程访问,并且有请求必有响应。

▐ Tomcat服务器搭建?

关于Tomcat服务器的搭建和部署在之前的文章已经写到,这里不再阐述,不会的小伙伴可以参考此链接文章:

Tomcat服务器搭建与部署 一条龙全教程icon-default.png?t=N7T8https://blog.csdn.net/2301_79263365/article/details/139155094?spm=1001.2014.3001.5501

二. Servlet程序


▐ 什么是Servlet?

  •  Servlet程序也就是我们运行在服务器端的Java程序.

▐ Servlet的创建和使用?

  •  创建一个类并继承HttpServlet,这样我们的类也就遵守了JavaEE规范

  •  重写父类中的方法(post请求就重写doPost方法,get请求就重写doGet方法)

  •  在web.xml文件中配置Servlet 

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
 
public class LoginServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("init");
    }
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service");
    }
    @Override
    public void destroy() {
        System.out.println("destory");
    }
}

<!--    注册Servlet-->
    <servlet>
        <servlet-name>login</servlet-name> <!-- 为Servlet对象定义名称-->
        <servlet-class>webserver.servlet.LoginServlet</servlet-class>
    </servlet>
<!--    为Servlet配置访问地址-->
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/login</url-pattern> <!-- 前端访问地址,必须/开头-->
    </servlet-mapping>

 ▐ Servlet的方法和生命周期?

  •  无参构造:  用来初始化Servlet,可以不写,只被调用一次.

  •  init( ):        也是用来初始化Servlet的,在构造方法执行完毕后执行,只执行一次。

  •  server( ):    多次被执行,是提供服务的.

  •  destory( ):  在服务器关闭时调用.

▐ Servlet程序的作用?

我们的后端Servlet程序主要做三件事:

接收前端请求,调用dao层与数据库交互,最后向前端做出响应即可。

三. http请求


请求中包含:

http请求的两种方式: 

 get请求
  • 数据是作为 URL 的一部分进行传输的,通常附加在 URL 地址之后,以 “?” 分隔 URL 和传输数据,多个参数之间用 “&” 连接。
  • 例如:https://www.example.com/search?q=keyword&page=2,其中 “q=keyword&page=2” 就是通过 GET 方式传递的参数。
  • 常用于获取 服务器上的资源,如获取网页内容、查询数据等;适用于对安全性要求不高、数据量较小的请求,比如搜索引擎的查询。
 post请求
  • 数据是放在 HTTP 请求的请求体中进行传输的,不会显示在 URL 中。
  • 这样对于一些敏感信息或者大量数据的传输,POST 方式相对更安全和合适。
  • 通常用于向服务器提交 数据,进行数据的添加、修改、删除等操作;比如用户注册、提交表单、上传文件等场景。

一次请求的流程:

四. 过滤器 


▐ 什么是过滤器?

过滤器是JavaEE规范中定义的一种技术,可以让请求达到目标Servlet之前,先进入到过滤器中,在过滤器中统一进行一些拦截处理,当处理完成后,可以继续向后执行到达目标Servlet,如果配置了多个过滤器,也可以进入到下一个过滤器。

一个过滤器可以配置给多个资源使用,一个资源也可以配置多个过滤器,按照配置顺序调用。

▐ 过滤器的作用?

提高代码复用性,提高可维护性。

▐ 过滤器的使用场景?

统一编码过滤、权限验证、跨域过滤。

▐ 代码实现?

➱ 创建过滤器(以编码过滤器为例)

结合类名,让这个类实现 Filter接口,并重写 Filter接口中的抽象方法,在 doFilter方法中设置字符集,并让过滤器继续向后执行

import javax.servlet.*;
import java.io.IOException;
 
public class EncodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("编码过滤器");
        //设置请求编码集
        servletRequest.setCharacterEncoding("utf-8");
        //设置响应编码集
        servletResponse.setContentType("text/html;charset=utf-8");
        //让请求离开过滤器继续向下执行,下一个可能是过滤器或目标访问的servlet
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

➱ 在web.xml文件中配置过滤器

    <!--    注册编码过滤器-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>stuServer.filter.EncodingFilter</filter-class>
    </filter>
    <!--    配置哪些地址可以进入到编码过滤器-->
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>  <!-- /* 表示所有向后端发送的请求,都进入到编码过滤器中-->
    </filter-mapping>

通过编码过滤器的设置,我们就不需要在每个Servlet接收post请求时都设置解码字符编码了,前端发送的请求会先进入到我们的编码过滤器,提高代码复用性.

五. 同步请求与异步请求


同步请求

之前在网页中通过超链接或者表单就可以向后端发送请求,后端也可以正常响应内容,但当网页与后端交互时,前端不能再进行其他操作,服务器端响应回来的内容会把整个浏览器中的内容覆盖掉,这种请求方式称为同步请求。

例如登录案例,同步请求响应的结果会将浏览器原本的登录界面覆盖掉。

这种请求方式在前后端交互时显得很不友好,现在的前后端交互请求都使用的是异步请求。

异步请求

 •  异步请求则同时可以做多件事情,前端与服务器交互时,不影响前端网页其他操作。

 •  异步请求是使用js中提供的XMLHtttpRequest对象实现发送异步请求和接受服务器响应的。

<script>		
	function checkAccount(account){		
		//异步请求,使用js对象发送请求
		var httpobj = new XMLHttpRequest();
		//封装请求地址和数据
		httpobj.open("get","http://127.0.0.1:8088/stuServer/reg?account="+account,true);
		//发送请求
		httpobj.send();
		//接收请求
		httpobj.onreadystatechange=function(){
			document.getElementById("msg").innerHTML = httpobj.responseText;//获取到响应的内容
		}	
	} 	
</script>

但是我们会发现这样做之后还是不能实现我们想要的结果,浏览器会报错,这个错也就是接下来将要提到的跨域问题。

▐ 跨域问题

异步请求时,会出现跨域访问问题:也就是浏览器默认不允许js对象接收来自其他服务器响应的内容,跨域问题是一个前端问题,既可以在前端解决,也可以在后端解决

什么是跨域?

 •  跨域是指从一个域名的网页去请求另一个域名的资源。

 •  比如从 www.baidu.com页面去请求 www.google.com 的资源。但是一般情况下不能这么做,它是由浏览器的同源策略造成的,是浏览器对 JavaScript 施加的安全限制。

 •  所谓同源是指:域名,协议,端口均相同,只要有一个不同,就是跨域。

 •  跨域的严格一点的定义是:只要协议域名端口有任何一个的不同,就被当作是跨域。

为什么要跨域访问?

由于现在的前后端分离开发,前端和后端各自在不同的服务站,同一家公司不同项目之间要交互,比如一个location.company.com,而应用是放在app.company.com,这时想从app.company.com去访问location.company.com的资源就属于跨域。

浏览器为什么要阻止跨域访问?

为了安全,不能让其他服务器的内容肆意的响应到自己的服务中.

后端解决

➱ 具体操作如下:

在后端添加一个跨域过滤器,这样后端在向前端响应时,就会告诉浏览器我们本次响应是安全的. 

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
@WebFilter(urlPatterns = "/*")
public class CorsFilter implements Filter {
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        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);
    }
}

 解决跨域问题后,就可以通过异步请求来达到我们想要的效果了:

▐ Axios框架

异步请求的原始写法比较复杂,所以我们通过Axios框架来封装简化这部分代码。

官方网址:

axios中文网|axios API 中文文档 | axios

在普通html中导入axios

进入官网选择使用cdn下载 :

如图访问axios.min.js文件,将此文件下载下来,在html文件中导入即可。

​ 

<script src="js/axios.min.js"></script>
在vue项目中安装axios

 1. 在vue项目中通过指令安装axios

npm install axios

📖 若安装过程出现卡顿,可以在命令行中更换镜像源,这里推荐使用华为云镜像源,本人亲测好用,检查更换成功后再通过命令安装就可以了。

//使用华为云镜像源加速 NPM
npm config set registry https://mirrors.huaweicloud.com/repository/npm/
//查看当前的镜像源
npm config get registry

2. 导入axios

import axios from 'axios';

3. 定义后端基本的地址,后面发送请求时只需要写Servlet地址即可,自动将这部分拼接过去

axios.defaults.baseURL = "http://127.0.0.1:8088/dorm/";

4. 将axios对象挂载到vue对象中,$http是在vue对象中自定义的属性  

Vue.prototype.$http = axios;

六. JSON数据格式


▐ 概念

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,后端一般情况下将数据封装到对象中,但是 js不认识 java对象。java中toString方法将对象转为字符串,js接收到后只是普通的字符串,不能使用面向对象的方式操作,为了让 js能够方便的进行操作,需要在 java中将对象转为json格式的字符串,传递给前端 js,目前json格式已成为公认的前后端交互的标准数据格式。

json是一种公认的 js识别的对象表示方式,对于java而言就是一种特定格式的字符串;

所以简单来说,json就是一种固定格式的字符串

  • 对象: { 键:值 , 键:值 , ...}
  • 集合:[ { 键:值 , 键:值 , ...} , { 键:值 , 键:值 , ...} , ...]

▐ Jackson 库中的关键类和方法 

  • ObjectMapper 是 Jackson 库中的核心类,主要用于 Java 对象和 JSON 之间的相互转换。它提供了一系列的方法来实现不同格式的数据转换和处理。
  • writeValueAsString 方法的作用是将一个 Java 对象序列化为 JSON 字符串格式。用于将 Java 对象序列化为 JSON 字符串进行传输。
     import com.fasterxml.jackson.databind.ObjectMapper;

     public class JacksonExample {
         public static void main(String[] args) throws Exception {
             // 创建一个简单的 Java 对象
             Person person = new Person("Alice", 30);

             // 创建 ObjectMapper 实例
             ObjectMapper objectMapper = new ObjectMapper();

             // 使用 writeValueAsString 方法将 Java 对象转换为 JSON 字符串
             String jsonString = objectMapper.writeValueAsString(person);
             System.out.println(jsonString);
         }
     }

     class Person {
         private String name;
         private int age;

         public Person(String name, int age) {
             this.name = name;
             this.age = age;
         }

         // 省略 getter 和 setter 方法
     }

 我们要将数据转换成json格式,需要在后端pom.xml文件中导入jackson组件

        <!-- jackson-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.14.2</version>
        </dependency>

七. 路由导航守卫


▐ 添加路由导航守卫的作用?

路由导航守卫是 Vue Router 提供的一种强大的机制,用于控制路由的导航过程。

可以根据用户的登录状态、角色等信息来决定是否允许用户访问某个路由,例如,当用户未登录时,阻止其访问需要登录权限的页面,并将其重定向到登录页面。

▐ 代码实现

在前端vue项目的index.js中添加一个路由导航守卫。

//配置路由导航守卫,每当进行一次组件路由时,自动执行此段代码
rout.beforeEach((to, from, next) => {
	if (to.path == '/login') {    //访问的路由地址
		return next();            //继续正常访问目标地址
	} else {
		var token = window.sessionStorage.getItem("account");//获取到浏览器中存储的管理员信息
		if (token == null) {   //如果信息为空,说明没有登录
			return next("/login");
		} else {   //说明已经登录,可以正常访问
			next();
		}
	}
})

📖全局前置守卫(beforeEach)

  • 在路由切换之前被调用。接收三个参数:to(即将要进入的目标路由对象)、from(当前导航正要离开的路由对象)、next(函数,用于决定是否继续导航)。
  • 可以在这个守卫中进行权限验证、全局数据预取等操作。如果 next () 没有被调用,导航将被中断。

八. Web会话跟踪


▐ 为什么需要会话跟踪?

因为http请求是无状态的,不携带用户信息,当用户登录成功后,之后再次与服务器交互时,服务器并不知道是哪个用户发送的请求,所以在Web开发中,必须要解决此问题,即之后的请求还需要让后端知道是哪个账号发送的请求,而会话跟踪就是解决此问题的。

理论流程

代码实现

1. 在后端中pom.xml文件中导入JWT组件

        <!--         JWT组件-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.8.2</version>
        </dependency>

➱ JWT是生成token的一种组件,它生成的token有三部分:

       •  第一部分:生成类型和加密算法.(声明)

       •  第二部分:载荷,包含用户信息.(id,账号,头像)

       •  第三部分:加密生成的的,也是最重要的.

2. 在后端添加JWT工具类,让工具为我们生成一个token字符串。

 

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.ffyc.dormserver.model.Admin;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 */
public class JWTUtil {

    /**
     * 根据用户id,账号生成token
     * @param
     * @return
     */
    public static String getToken(Admin admin) {
        String token = "";
        try {
            //过期时间 为1970.1.1 0:0:0 至 过期时间  当前的毫秒值 + 有效时间
            Date expireDate = new Date(new Date().getTime() + 3600*1000);
            //秘钥及加密算法
            Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
            //设置头部信息
            Map<String,Object> header = new HashMap<>();
            header.put("typ","JWT");
            header.put("alg","HS256");
            //携带id,账号信息,生成签名
            token = JWT.create()
                    .withHeader(header)//第一部分
                    .withClaim("id",admin.getId())//第二部分
                    .withClaim("account",admin.getAccount())//第二部分
                    .withExpiresAt(expireDate)//第二部分
                    .sign(algorithm);//第三部分:秘钥
        }catch (Exception e){
            e.printStackTrace();
            return  null;
        }
        return token;
    }

    /**
     * 验证token是否有效
     * @param token
     * @return
     */
    public static boolean verify(String token){
        try {
            //验签
            Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception e) {//当传过来的token如果有问题,抛出异常
            return false;
        }
    }

    /**
     * 获得token 中playload部分数据,按需使用
     * @param token
     * @return
     */
    public static DecodedJWT getTokenInfo(String token){
        return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
    }

}

3. 在前端vue项目main.js中添加请求拦截器

//axios 请求拦截
axios.interceptors.request.use(config => {
	//为请求头对象,添加 Token 验证的 token 字段
	config.headers.token = window.sessionStorage.getItem('adminToken');
	return config;
})

4. 在vue项目main.js中添加响应拦截器

// 添加响应拦截器
axios.interceptors.response.use((resp) => { //正常响应拦截
	if (resp.data.code == 500) {
		ElementUI.Message({message: resp.data.desc,type: "error"})
	}
	if (resp.data.code == 401) {
		ElementUI.Message({message: resp.data.desc,type: "warning"})
		router.replace("/login");
	}
	return resp;
});



本次的分享就到此为止了,希望我的分享能给您带来帮助,创作不易也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见

海漫浩浩,我亦苦作舟!大家一起学习,一起进步!    本人微信:g2279605572(欢迎大家与我交流)   

  • 20
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值