spring?boot使用攔截器修改請求URL域名?換?IP?訪問的方法
Interceptor 介紹
攔截器(Interceptor)同 Filter 過濾器一樣,它倆都是面向切面編程——AOP 的具體實(shí)現(xiàn)(AOP切面編程只是一種編程思想而已)。
你可以使用 Interceptor 來執(zhí)行某些任務(wù),例如在 Controller 處理請求之前編寫日志,添加或更新配置…
在 Spring中,當(dāng)請求發(fā)送到 Controller 時(shí),在被Controller處理之前,它必須經(jīng)過 Interceptors(0或多個(gè))。
Spring Interceptor是一個(gè)非常類似于Servlet Filter 的概念 。
Interceptor 作用
日志記錄:記錄請求信息的日志,以便進(jìn)行信息監(jiān)控、信息統(tǒng)計(jì)、計(jì)算 PV(Page View)等;
權(quán)限檢查:如登錄檢測,進(jìn)入處理器檢測是否登錄;
性能監(jiān)控:通過攔截器在進(jìn)入處理器之前記錄開始時(shí)間,在處理完后記錄結(jié)束時(shí)間,從而得到該請求的處理時(shí)間。(反向代理,如 Apache 也可以自動(dòng)記錄)
通用行為:讀取 Cookie 得到用戶信息并將用戶對(duì)象放入請求,從而方便后續(xù)流程使用,還有如提取 Locale、Theme 信息等,只要是多個(gè)處理器都需要的即可使用攔截器實(shí)現(xiàn)。
自定義 Interceptor
如果你需要自定義 Interceptor 的話必須實(shí)現(xiàn) org.springframework.web.servlet.HandlerInterceptor接口或繼承 org.springframework.web.servlet.handler.HandlerInterceptorAdapter類,并且需要重寫下面下面 3 個(gè)方法:
preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) 方法在請求處理之前被調(diào)用。該方法在 Interceptor 類中最先執(zhí)行,用來進(jìn)行一些前置初始化操作或是對(duì)當(dāng)前請求做預(yù)處理,也可以進(jìn)行一些判斷來決定請求是否要繼續(xù)進(jìn)行下去。該方法的返回至是 Boolean 類型,當(dāng)它返回 false 時(shí),表示請求結(jié)束,后續(xù)的 Interceptor 和 Controller 都不會(huì)再執(zhí)行;當(dāng)它返回為 true 時(shí)會(huì)繼續(xù)調(diào)用下一個(gè) Interceptor 的 preHandle 方法,如果已經(jīng)是最后一個(gè) Interceptor 的時(shí)候就會(huì)調(diào)用當(dāng)前請求的 Controller 方法。
postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 方法在當(dāng)前請求處理完成之后,也就是 Controller 方法調(diào)用之后執(zhí)行,但是它會(huì)在 DispatcherServlet 進(jìn)行視圖返回渲染之前被調(diào)用,所以我們可以在這個(gè)方法中對(duì) Controller 處理之后的 ModelAndView 對(duì)象進(jìn)行操作。
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法需要在當(dāng)前對(duì)應(yīng)的 Interceptor 類的 postHandler 方法返回值為 true 時(shí)才會(huì)執(zhí)行。顧名思義,該方法將在整個(gè)請求結(jié)束之后,也就是在 DispatcherServlet 渲染了對(duì)應(yīng)的視圖之后執(zhí)行。此方法主要用來進(jìn)行資源清理。
接下來結(jié)合實(shí)際代碼進(jìn)行學(xué)習(xí)。
案例1 :域名換IP訪問
package com.config; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.support.HttpRequestWrapper; import org.springframework.stereotype.Component; import org.springframework.web.util.UriComponentsBuilder; import java.io.IOException; import java.net.URI; @Component public class Interceptor implements ClientHttpRequestInterceptor { /** * Intercept the given request, and return a response. The given {@link ClientHttpRequestExecution} allows * the interceptor to pass on the request and response to the next entity in the chain. * * <p>A typical implementation of this method would follow the following pattern: * <ol> * <li>Examine the {@linkplain HttpRequest request} and body</li> * <li>Optionally {@linkplain HttpRequestWrapper wrap} the request to filter HTTP attributes.</li> * <li>Optionally modify the body of the request.</li> * <li><strong>Either</strong> * <ul> * <li>execute the request using {@link ClientHttpRequestExecution#execute(HttpRequest, byte[])},</li> * <strong>or</strong> * <li>do not execute the request to block the execution altogether.</li> * </ul> * <li>Optionally wrap the response to filter HTTP attributes.</li> * </ol> * * @param request the request, containing method, URI, and headers * @param body the body of the request * @param execution the request execution * @return the response * @throws IOException in case of I/O errors */ @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { String str = request.getURI().toString(); String str1 = str.replace("https://baidu.com", "http://39.156.66.10:8080"); URI newUri = UriComponentsBuilder.fromUri(URI.create(str)).build().toUri(); return execution.execute(new UriModifyHttpRequestWrapper(request, newUri), body); } private static class UriModifyHttpRequestWrapper extends HttpRequestWrapper { private final URI uri; public UriModifyHttpRequestWrapper(HttpRequest request, URI uri) { super(request); this.uri = uri; } @Override public URI getURI() { return uri; } } }
案例2: erverWebExchange通過攔截器修改請求url
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest str = exchange.getRequest(); //新url String newPath ="/system/loanOrg/list"; ServerHttpRequest newRequest = str.mutate().path(newPath).build(); exchange.getAttributes().put("path", newRequest.getURI()); return chain.filter(exchange.mutate() .request(newRequest).build()); }
案例3: 將請求路徑中/idea都去掉
1.定義攔截器
import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; @Component public class GlobalInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpServletResponseWrapper httpResponse = new HttpServletResponseWrapper((HttpServletResponse) response); System.out.println(request.getRequestURI()); String path=request.getRequestURI(); if(path.indexOf("/idea")>-1){ path = path.replaceAll("/idea",""); request.getRequestDispatcher(path).forward(request,response); } return true; } }
2.定義WebMvcConfig
import com.GlobalInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired GlobalInterceptor globalInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(globalInterceptor).addPathPatterns("/idea/**"); } }
案例4: SpringBoot 利用過濾器Filter修改請求url地址
要求:
代碼中配置的url路徑為http://127.0.0.1/api/asso
現(xiàn)在要求http://127.0.0.1/asso 也可以同樣訪問同一個(gè)conroller下面的method,并且要求參數(shù)全部跟隨
代碼:
package com.framework.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; /** * 修改請求路由,當(dāng)進(jìn)入url為/a/b時(shí),將其url修改為/api/a/b * **/ public class UrlFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest)request; HttpServletResponseWrapper httpResponse = new HttpServletResponseWrapper((HttpServletResponse) response); System.out.println(httpRequest.getRequestURI()); String path=httpRequest.getRequestURI(); if(path.indexOf("/api/")<0){ path="/api"+path; System.out.println(path); httpRequest.getRequestDispatcher(path).forward(request,response); } else { chain.doFilter(request,response); } return; } }
這個(gè)類必須繼承Filter類,這個(gè)是Servlet的規(guī)范。有了過濾器類以后,以前的web項(xiàng)目可以在web.xml中進(jìn)行配置,但是spring boot項(xiàng)目并沒有web.xml這個(gè)文件,那怎么配置?在Spring boot中,我們需要FilterRegistrationBean來完成配置。
其實(shí)現(xiàn)過程如下:
package com.shitou.huishi.framework.filter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Created by qhong on 2018/5/16 15:28 **/ @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new UrlFilter()); registration.addUrlPatterns("/*"); registration.setName("UrlFilter"); registration.setOrder(1); return registration; } }
案例5.攔截器: WebMvcConfigurerAdapter攔截器
攔截所有請求
@Configuration public class CustMvcConfigurerAdapter extends WebMvcConfigurerAdapter { @Autowired private CustInterceptor custInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(custInterceptor).addPathPatterns("/**"); } }
排除指定路徑 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(custInterceptor).addPathPatterns("/**").excludePathPatterns("/select/**"); }
攔截指定路徑
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(custInterceptor).addPathPatterns("/user/**"); }
CustInterceptor具體攔截類
@Component public class CustInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { boolean needLogin = needLogin(request); if (!needLogin) { return true; } boolean isLogin = checkLogin(request, response); return isLogin; } }
結(jié)語
到此這篇關(guān)于spring boot使用攔截器修改請求URL域名 換 IP 訪問的文章就介紹到這了,更多相關(guān)spring boot攔截器修改請求URL域名內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis批量插入更新xml方式和注解方式的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于Mybatis批量插入更新xml方式和注解方式的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12JVM內(nèi)存結(jié)構(gòu):程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧
JVM 基本上是每家招聘公司都會(huì)問到的問題,它們會(huì)這么無聊問這些不切實(shí)際的問題嗎?很顯然不是。由 JVM 引發(fā)的故障問題,無論在我們開發(fā)過程中還是生產(chǎn)環(huán)境下都是非常常見的2021-06-06Java用POI導(dǎo)入導(dǎo)出Excel實(shí)例分析
在本篇文章里小編給大家整理的是一篇關(guān)于Java用POI導(dǎo)入導(dǎo)出Excel實(shí)例分析內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。2021-11-11jxl操作excel寫入數(shù)據(jù)不覆蓋原有數(shù)據(jù)示例
網(wǎng)上很多例子,都是用Jxl讀或者寫excel,本文實(shí)現(xiàn)的功能就是將數(shù)據(jù)源in.xls的第幾行第幾列數(shù)據(jù)寫入到out.xls的第幾行第幾列,不覆蓋out.xls其他原有的數(shù)據(jù)。2014-03-03IDEA實(shí)現(xiàn) springmvc的簡單注冊登錄功能的示例代碼
這篇文章主要介紹了IDEA實(shí)現(xiàn) springmvc的簡單注冊登錄功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06SpringCloud Feign隔離與降級(jí)詳細(xì)分析
Feign是Netflix公司開發(fā)的一個(gè)聲明式的REST調(diào)用客戶端; Ribbon負(fù)載均衡、 Hystrⅸ服務(wù)熔斷是我們Spring Cloud中進(jìn)行微服務(wù)開發(fā)非?;A(chǔ)的組件,在使用的過程中我們也發(fā)現(xiàn)它們一般都是同時(shí)出現(xiàn)的,而且配置也都非常相似2022-11-11JavaMail實(shí)現(xiàn)郵件發(fā)送的方法
這篇文章主要介紹了JavaMail實(shí)現(xiàn)郵件發(fā)送的方法,實(shí)例分析了java實(shí)現(xiàn)郵件發(fā)送的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04Redis 訂閱發(fā)布_Jedis實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猂edis 訂閱發(fā)布_Jedis實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06springboot整合mybatis-plus實(shí)現(xiàn)多表分頁查詢的示例代碼
這篇文章主要介紹了springboot整合mybatis-plus實(shí)現(xiàn)多表分頁查詢的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03