尝试真正的前后端分离
笔者在此前有做过一些小项目,不过大抵都侧重后端这方面,还未真正做过要把前端同时考虑在内的实践。即便是有,但所用技术也是比较落后的JSP(JSP本身也不是前端领域,来进行前后端数据传输尚且有点作用),并不能和后端解耦,做到真正的分离。
真正要想做到解耦、做到一般业务场景的前后端分离,就需要强调接口思想,前后端之间的交互都交由接口来解决,过程只需要传递相关的请求参数就可以了。这样才算做到分离,前后端的任务也能更为明晰,也不会出现笔者完成当初JSP项目时的一大堆代码冲突了()。
所需要的技术自然就必须淘汰JSP,而需要利用到Vue做数据绑定,axios进行异步请求------当然,在前端领域,所用技术还远不止这些,这里只是结合笔者最近的一次的实践。
同源策略
然而,前后端做完分离后,又该考虑一个问题了------前后端设置的URL默认往往是不一样的,这也就是为什么在使用Axios发送请求时,url都写成绝对路径的原因。
vue
axios({
method:"post",
url:"http://localhost:8080/brand_case_war/brand/update",//绝对路径
data:_this.brand
}).then(function (resp){
if(resp.data==="success"){
//更新成功
//关闭窗口
_this.dialogVisible=false;
_this.select();
_this.$message({
message:'更新成功',
type:'success'
})
}
})
这样做也符合解耦、分离的原则嘛。但是如果不做任何其他处理就直接运行整个项目的话,我们很快就能发现前端传递的参数,后端程序总是接收不到,页面打开F12,我们能发现这样的报错:
报错信息表明了一个跨源资源共享(CORS) 问题,当我们尝试从浏览器的某个源(这里是 http://localhost:8080
)发起请求到另一个源时就会出现这样的问题。
那么想了解跨源资源共享,首先就必须先知道同源策略(SOP)是怎么一回事:
同源策略(Same-Origin Policy) 是 Web 浏览器中的一项安全机制,旨在防止不同源(协议、域名或端口不同的网站)之间的恶意交互。这个策略的核心思想是,如果两个资源(如网页、图片、脚本等)来自同一个源,那么它们可以自由地相互通信和操作;如果来自不同的源,浏览器会限制它们之间的交互,以防止潜在的安全风险,如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)。
同源策略的主要目的是保护用户数据和隐私,防止恶意网站通过脚本窃取或篡改其他网站的数据。例如,如果一个用户在一个银行网站上操作,而另一个恶意网站试图通过 JavaScript 来获取这个银行网站的数据,由于同源策略的存在,这种尝试通常会被浏览器阻止。
SOP为我们带来了安全,但同时也为Web开发多了一项新增的环节:在安全的前提下,允许跨源资源共享,就是和SOP相对的CORS。
利用过滤器解决跨源问题
笔者对于SOP和CORS都只处于认识层次,且本文侧重也不在这两者上,因此对于这两者的介绍就只能停留到这儿。
回到笔者最近的实践上,在了解了CORS后,再来看这一处报错,这其中还提到了在即将发送的response当中,有名为Access-Control-Allow-Headers
的一个字段。
再去查阅资料,发现这一字段是CORS的核心,跨源资源共享失败的很大原因可以在这个字段中找到。
- 服务器未正确设置 CORS 头部 :如果服务器没有在响应中包含正确的
Access-Control-Allow-Origin
头部,或者该头部的值不正确,浏览器会阻止跨域请求。- 请求方法或头部不被允许 :如果请求使用了非简单 HTTP 方法(如 PUT、DELETE 等)或者自定义头部,服务器需要在
Access-Control-Allow-Methods
和Access-Control-Allow-Headers
头部中明确允许这些方法和头部,否则浏览器也会阻止跨域请求。
因此,我们有必要对这个字段进行设置,最常见的操作是这样的:
java
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
//这里的IP和端口可以改成你自己的
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Max-Age", "3600");
由于这样的跨源问题几乎都发生在Web上,因此我们使用主要作用在Java Web上的过滤器(Filter),注解写上拦截路径。
java
@WebFilter("/*")//处理所有资源请求
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init CorsFilter......");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Max-Age", "3600");
chain.doFilter(req, res);
}
@Override
public void destroy() {
System.out.println("destroy CorsFilter......");
}
}
解决跨域问题,这种方法很常用。
过滤器(Filter)和中间件(Middleware)
之前做用户鉴权的时候也用过中间件,此次实践不由得将它和过滤器对比了下,发现两者作用有些相似------都是到达目标资源之前先进行一趟数据处理,再放行。
但细想,过滤器更多的用在Java Web中,处理HTTP请求尤其是;而中间件范围更加宽泛,不只在Web当中扮演角色,更可以用于路由、数据校验、会话管理、错误处理等多种任务当中。
查询资料,两者的对比比较详细一点是这样的: