在以前的學習springBoot中,成功的實現了Restful風格的基本服務。可是想將以前的工程做爲一個項目來講,那些是僅僅不夠的。可能還須要獲取自定義的配置以及添加過濾器和攔截器。至於爲何將這些寫在一塊兒,只是由於這些比較簡單並且也會常常用到,因此乾脆就一塊兒寫出來了。java
在使用maven項目中,配置文件會放在resources根目錄下。
咱們的springBoot是用Maven搭建的,因此springBoot的默認配置文件和自定義的配置文件都放在此目錄。
springBoot的 默認配置文件爲 application.properties 或 application.yml,這裏咱們使用 application.properties。git
首先在application.properties中添加咱們要讀取的數據。
springBoot支持分層結構。
例如:github
web: pancm: title: SpringBoot description: test
注意前面的空格!web
在application.properties添加完以後,咱們便在代碼中進行讀取。
這裏咱們使用@Value 方式。
首先在類中添加 @Component、@ConfigurationProperties這兩個註解。
第一個註解表示這個類是獲取配置文件,第二個註解表示從配置文件中獲取的數據轉換爲對象。由於咱們使用了層級結構,獲取web.pancm目錄下的參數,因此咱們再加上prefix = "web.pancm"這個表示獲取這以後的數據,就避免了下面在重複書寫。
那麼代碼以下:spring
import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; /** * * Title: MyProperties * Description: * 從application.properties 獲取 配置 * Version:1.0.0 * @author pancm * @date 2018年1月11日 */ @Component @ConfigurationProperties(prefix = "web.pancm") public class MyProperties { /** * 獲取我的標題 * */ @Value("${title}") private String title; /** * 獲取我的描述 */ @Value("${description}") private String description; /** get和set略 */ }
本類中能夠直接獲取該屬性,不過在外部類調用的時候,須要添加@Autowired。json
例如:springboot
@Autowired MyProperties myProperties; System.out.println(myProperties.getTitle()); System.out.println(myProperties.getDescription());
上面的是獲取application.properties中的方法。
若是想自定義配置文件和屬性的話,只需再添加一個@PropertySource註解就可,而後添加 value屬性,指向文件路徑便可。
例如:app
import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; /** * * Title: MyConfig * Description: * 自定義配置文件 * Version:1.0.0 * @author pancm * @date 2018年1月20日 */ @Component @ConfigurationProperties(prefix = "myconfig") @PropertySource(value = "classpath:myconfig.proferties") public class MyConfig { @Value("${test}") private String test; public String getTest() { return test; } public void setTest(String test) { this.test = test; } }
調用方法同上!maven
注: 以前的springBoot版本的@ConfigurationProperties註解可使用 locations 方法來指定自定義配置文件路徑,不過在 springBoot 1.5以上的就已經不支持 location屬性,因此這裏使用的是PropertySource。ide
過濾器是什麼?
簡單的來講,過濾器就是過濾的做用,在web開發中過濾一些咱們指定的url。
過濾器主要作什麼?
過濾掉一些不須要的東西,例如一些錯誤的請求。
也能夠修改請求和相應的內容。
過濾器的代碼實現
過濾器(filter)有三個方法,其中初始化(init)和摧毀(destroy)方法通常不會用到,主要用到的是doFilter這個方法。
而至於怎麼過濾呢?
若是過濾經過,則在doFilter執行filterChain.doFilter(request,response);
該方法。
這裏咱們在過濾器中設置下請求的時間, 符合就經過。不然返回錯誤信息!
代碼示例:
class MyFilter implements Filter { @Override public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) srequest; //執行過濾操做... System.out.println("請求的url :"+request.getRequestURI()); // 獲取系統時間 Calendar ca = Calendar.getInstance(); int hour = ca.get(Calendar.HOUR_OF_DAY); // 設置限制運行時間 if (0<hour && hour < 18) { HttpServletResponse response = (HttpServletResponse) sresponse; response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); // 消息 Map<String, Object> messageMap = new HashMap<>(); messageMap.put("status", "1"); messageMap.put("message", "此接口能夠請求時間爲:18-24點"); ObjectMapper objectMapper=new ObjectMapper(); String writeValueAsString = objectMapper.writeValueAsString(messageMap); response.getWriter().write(writeValueAsString); return; } filterChain.doFilter(srequest, sresponse); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("參數初始化:"+filterConfig); } @Override public void destroy() { System.out.println("開始銷燬..."); } }
那麼在springBoot中如何使用過濾器呢?
通常是使用Component和WebFilter 這兩個註解,可是這裏咱們就直接方法調用。
在該方法中添加Bean註解,springBoot會在啓動的時候進行調用。並指定須要過濾的請求。
代碼示例:
@Bean public FilterRegistrationBean testFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new MyFilter()); //過濾掉 /getUser 和/hello 的請求 registration.addUrlPatterns("/getUser","/hello"); //過濾掉全部請求 // registration.addUrlPatterns("/*"); registration.setName("MyFilter"); registration.setOrder(1); return registration; }
說明: registration.setOrder() 方法是設置優先級,數值越大,優先級越高。
攔截器是什麼?
簡單的來講,就是一道閥門,攔截不須要的東西。
攔截器主要作什麼?
對正在運行的流程進行干預。
攔截器的代碼實現。
攔截器也主要有三個方法,其中preHandle是在請求以前就進行調用,若是該請求須要被攔截,則返回false,不然true; postHandle是在請求以後進行調用,無返回值;afterCompletion是在請求結束的時候進行調用,無返回值。
這裏咱們就簡單的模擬下攔截非白名單的IP請求。
代碼示例:
class MyInterceptor implements HandlerInterceptor { @Autowired private IpConfig ipconfig; public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { String ip = getIpAddr(request); // 獲取能夠訪問系統的白名單 String ipStr = ipconfig.getIpWhiteList(); String[] ipArr = ipStr.split("\\|"); List<String> ipList = Arrays.asList(ipArr); if (ipList.contains(ip)) { System.out.println("該IP: " + ip+"經過!"); return true; } else { System.out.println("該IP: " + ip+"不經過!"); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); // 消息 Map<String, Object> messageMap = new HashMap<>(); messageMap.put("status", "1"); messageMap.put("message", "您好,ip爲" + ip + ",暫時沒有訪問權限,請聯繫管理員開通訪問權限。"); ObjectMapper objectMapper=new ObjectMapper(); String writeValueAsString = objectMapper.writeValueAsString(messageMap); response.getWriter().write(writeValueAsString); return false; } } public String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("postHandle被調用"); } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("afterCompletion被調用"); } }
依舊再啓動springBoot的時候啓動攔截器,並指定攔截的請求。
代碼示例:
import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import com.fasterxml.jackson.databind.ObjectMapper; import com.pancm.springboot_config.config.IpConfig; @Configuration public class MyWebAppConfigurer extends WebMvcConfigurerAdapter { @Bean public HandlerInterceptor getMyInterceptor(){ return new MyInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { // addPathPatterns 用於添加攔截規則, 這裏假設攔截 /url 後面的所有連接 // excludePathPatterns 用戶排除攔截 registry.addInterceptor(getMyInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } }
關於springBoot配置文件的獲取以及過濾器和攔截器的使用暫時就介紹到這了。若是在某些方面描述的不夠清楚或者說的不太正確,但願讀者能指出。 該項目完整的代碼我放到github上了,有興趣的能夠看看。 https://github.com/xuwujing/springBoot