前言
本篇記錄一下使用前后端分離來開發(fā)SSM項目。
一、前后端分離技術(shù)和跨域
目前,前后端分離項目早已占據(jù)市場的主流開發(fā)方式。因為它能把web端的代碼和java業(yè)務實現(xiàn)的代碼完全分離開來,使得協(xié)同開發(fā)變得更加便捷。即,前端工程師和后端工程師只需要預先規(guī)定好統(tǒng)一的API,就可以同步開發(fā),大大降低項目的開發(fā)周期。
實現(xiàn)前后端分離需要解決的文體就是跨域傳輸。
我們都知道,在SSM項目中我們使用JSP來訪問Servlet接口,實現(xiàn)前后端的交互,歸根結(jié)底還是在同一個域進行傳輸,即端口號是相同的。但是在使用前后端分離開發(fā)的時候,我們需要在不同的域中間進行數(shù)據(jù)傳輸。最直觀的就是,后端我們一般使用8080端口,前端可能會使用5500端口,這就意味著,前端和后端處在不同的域內(nèi)。
跨域傳輸?shù)母驹蚴菫g覽器端的一種保護程序的機制。當前端域向后端域發(fā)送了請求,一般情況下,會有正常的響應數(shù)據(jù)。但是由于瀏覽器的保護機制,使得我們無法使用這些響應數(shù)據(jù)。瀏覽器需要的是后端必須返回給它一個允許跨域的請求頭,否則,返回的數(shù)據(jù)就無法呈現(xiàn)在前端。那么怎么讓后端返回的數(shù)據(jù)攜帶正確的請求頭就是我們需要解決的問題。
二、兩種不同的實現(xiàn)方案
1.使用注解實現(xiàn)簡單請求的跨域傳輸
代碼如下:
@Controller
@RequestMapping( "/login")
@CrossOrigin("*")
public class LoginController {
//自動注入業(yè)務層
@Autowired
private LoginService service;
@RequestMapping(value = "loginVerify",method = RequestMethod.POST)
@ResponseBody
public ResultLayUi<User> login(String username, String password, HttpServletRequest request){
createLoginSession(username,request);
return service.verifyLogin(username,password);
}
}
我們可以使用@CrossOrigin注解來實現(xiàn)一個臨時的跨域傳輸訪問。注解后邊的括號可以填寫允許跨域訪問的域,例如@CrossOrigin(" * ")表示,允許所有的域訪問。@CrossOrigin(“http://127.0.0.1:5500/login.html”)允許該IP訪問。但是這種解決方案只適合簡單請求。不適合復雜請求。
2.通過設置請求頭和參數(shù)實現(xiàn)復雜請求的跨域傳輸
通過注解,我們只能實現(xiàn)簡單的跨域請求,但無法實現(xiàn)復雜的跨域請求。但是我們可以通過在controller中設置請求頭和請求參數(shù)來實現(xiàn)復雜請求的跨域傳輸。代碼如下:
@Controller
@RequestMapping( "/login")
//@CrossOrigin("*")
public class LoginController {
//自動注入業(yè)務層
@Autowired
private LoginService service;
@RequestMapping(value = "loginVerify",method = RequestMethod.POST)
@ResponseBody
public ResultLayUi<User> login(String username, String password, HttpServletRequest request){
String origin = request.getHeader("Origin");
// 允許的跨域
response.setHeader("Access-Control-Allow-Origin",origin);
// 允許攜帶Cookie
response.setHeader("Access-Control-Allow-Credentials","true");
// 允許的請求頭 預檢請求需要這個設置
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,Access-Token,token");
response.setHeader("Access-Control-Expose-Headers", "*");//響應客戶端的頭部 允許攜帶Token 等等
response.setHeader("Access-Control-Max-Age", "3600"); // 預檢請求的結(jié)果緩存時間
if (request.getMethod().equals("OPTIONS")){
return false;
}
return service.verifyLogin(username,password);
}
}
通過這種方式,我們可以實現(xiàn)跨域請求。但是我們需要在每一個Controller方法中都設置這些代碼。
3.將跨域解決方案的代碼寫進攔截器,或者過濾器實現(xiàn)跨域。
上邊說到,我們需要在每一個controller中都配置如上代碼,造成大量的代碼冗余。我們可以把這些代碼放進攔截器或者過濾器來實現(xiàn)一個封裝的效果。文章來源:http://www.zghlxwxcb.cn/news/detail-457643.html
攔截器
package com.glls.java2212.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @date 2022/10/10
* @desc 攔截器 一個臨時的 跨域解決方案
*/
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String origin = request.getHeader("Origin");
// 允許的跨域
response.setHeader("Access-Control-Allow-Origin",origin);
// 允許攜帶Cookie
response.setHeader("Access-Control-Allow-Credentials","true");
// 允許的請求頭 預檢請求需要這個設置
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,Access-Token,token");
response.setHeader("Access-Control-Expose-Headers", "*");//響應客戶端的頭部 允許攜帶Token 等等
response.setHeader("Access-Control-Max-Age", "3600"); // 預檢請求的結(jié)果緩存時間
if (request.getMethod().equals("OPTIONS")){
return false;
}
return true;
}
}
過濾器
package com.glls.java2212.filter;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @date 2022/10/10
* @desc
*/
@Component
@WebFilter(urlPatterns = "/*", filterName = "CorsFilter")
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String origin = request.getHeader("Origin");
// 允許的跨域
response.setHeader("Access-Control-Allow-Origin",origin);
// 允許攜帶Cookie
response.setHeader("Access-Control-Allow-Credentials","true");
//
response.setHeader("Access-Control-Allow-Headers", "Content-Type,content-type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,Access-Token,token");
response.setHeader("Access-Control-Expose-Headers", "*");//響應客戶端的頭部 允許攜帶Token 等等
response.setHeader("Access-Control-Max-Age", "3600"); // 預檢請求的結(jié)果緩存時間
//
if (!request.getMethod().equals("OPTIONS")){
//非 預檢請求 放行 ,預檢請求 不放行 預檢請求 直接響應允許跨域的信息即可 無需訪問到后臺接口
filterChain.doFilter(request, response);
}
}
}
總結(jié)
跨域請求的方案有很多,此處只是簡單的介紹了兩種。分別對應簡單的請求跨域和復雜的請求跨域。文章來源地址http://www.zghlxwxcb.cn/news/detail-457643.html
到了這里,關(guān)于SSM前后端分離技術(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!