當前位置:
首頁 > 知識 > SpringMVC常用配置3

SpringMVC常用配置3

我們的案例都會有一個MvcConfig的類用來做一個簡單的配置,主要是通過ViewResolver來解決映射路徑和實際頁面的位置,這個類我們還可以繼續擴展,讓其解決更多的問題,我列舉幾個:

  • 靜態資源映射
  • 攔截器使用
  • 全局配置問題

等等。這些問題我們可以重新定義一個新的類來解決,也可以擴展MvcConfig來解決。我們來一個個看看。


靜態資源映射

我們都知道在SpringMVC中靜態資源文件都是直接訪問的,而不需要映射,這些靜態資源主要包括js文件、css文件、圖片文件等,那麼這個需要我們單獨處理,否則系統會找不到路徑。OK,這個問題的解決也很容易,假設我有一張圖片放在src/main/resources/assets/img目錄下,然後想在jsp頁面中將其展示出來,我們先來看看jsp頁面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Hello Sang!</title>
</head>
<body>
<p>Welcome To SpringMVC World!</p>
<p>
<img src="../assets/img/1.png">
</p>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

然後我們創建MVCConfig類,作用還是和上文一樣,不同的是這次我們繼承自WebMvcConfigurerAdapter,然後重寫WebMvcConfigurerAdapter類中的addResourceHandlers方法來解決這個問題。如下:

@Configuration
@EnableWebMvc
@ComponentScan("org.sang")
public class MVCConfig extends WebMvcConfigurerAdapter{
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/classes/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}

/**
* /**的意思是所有文件,包括文件夾中的子文件
* /*是所有文件,不包含子文件
* /是web項目的根目錄
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//兩個*表示以/assets開始的任意層級的路徑都可以訪問得到圖片,如<img src="../assets/img/1.png">
//一個*表示只可以訪問assets目錄下的圖片文件
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

OK,這裡繼承WebMvcConfigureAdapter之後,我們可以重寫它裡邊的很多方法,重寫這些方法我們可以對SpringMVC進行配置,addResourceHandler指的是訪問路徑,addResourceLocations指的是文件放置目錄。


攔截器

攔截器在JavaEE開發中還是非常重要的,亂碼解決、許可權控制等等都會用到,使用Servlet的時候有一個Filter類用來進行過濾,那麼SpringMVC也在這方面給我們提供了相應的解決方案。

  • 定義攔截器

攔截器的定義我們可以通過繼承HandlerInterceptorAdapter或者實現HandlerInterceptor介面,我這裡以實現介面為例:

public class MyInterceptors implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle");
return true;
}

public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}

public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion");
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

preHandle方法發生在請求發生前執行,postHandle發生在請求發生後執行,afterCompletion在請求完成時執行,實際上執行時機緊挨著postHandle這個方法。然後在MVCConfig類中添加addInterceptors方法註冊攔截器,如下:

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptors());
}
@Bean
public MyInterceptors myInterceptors() {
return new MyInterceptors();
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

這樣註冊成功之後,我們在瀏覽器中訪問時,列印日誌如下:

SpringMVC常用配置3


全局配置

全局資源的配置問題,我們可以通過@ControllerAdvice來把控制器的全局配置放在同一個位置,這樣我們可以統一處理下面幾個問題:


1 .全局異常處理

2 .預設鍵值對綁定到Model中

3 .預處理前台請求參數

OK,下面來一個一個看一下。

全局異常處理

全局異常主要是通過@ExceptionHandler這個註解來解決。如下:

@ControllerAdvice
public class ExceptionHandlerAdvice {
//@ExceptionHandler用來設置攔截條件,這裡表示攔截所有的Exception
@ExceptionHandler(value = Exception.class)
public ModelAndView exception(Exception e, WebRequest request) {
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("errorMsg", e.getMessage());
return modelAndView;
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

首先通過@ControllerAdvice聲明一個控制器建言,由於這個註解組合了@Component註解,這個這個類會自動註冊為Spring容器中的Bean。@ExceptionHandler可以定義全局處理,其中Value屬性用來表示過濾攔截條件,Exception.class表示攔截所有的Exception。構造ModelAndView時傳入的error表示出錯的頁面。OK,我們來看一下控制器,我在控制器中添加如下方法:

@RequestMapping("/user")
public String user(@ModelAttribute("msg") String msg, UserBean userBean) {
System.out.println("username is :" + userBean.getUsername() + ";and id is :" + userBean.getId());
throw new IllegalArgumentException("抱歉,參數異常/ 來自@ModelAttribute:" + msg);
}

  • 1
  • 2
  • 3
  • 4
  • 5

當我訪問/user這個地址的時候,直接拋一個異常,這個異常會被使用了@ExceptionHandler註解並且滿足過濾條件的方法接收並處理,我們這裡當然是來到了exception這個方法中,在這個方法中我們又定位到了error.jsp頁面。同時這裡的參數還使用了@ModelAttribute註解,這個註解我在下一小節再來說。我們再來看看這個error.jsp頁面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>出錯啦</title>
</head>
<body>
<p>
<h1>${errorMsg}</h1>
</p>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

這個頁面很簡單,就顯示一下錯誤信息就行了。我們來看看訪問結果:

SpringMVC常用配置3

控制台輸出的錯誤信息:

SpringMVC常用配置3

預設鍵值對綁定到Model中

有的時候我們需要預設鍵值對到Model中,就像上面那個案例那樣,這個時候我們可以在ExceptionHandlerAdvice類中再添加一個方法:

@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "額外信息");
}

  • 1
  • 2
  • 3
  • 4

在這個方法中我們向Model中綁定鍵值對,綁定完成之後,在任何Controller中我們都可以通過給方法的參數設定@ModelAttribute註解來訪問這裡存入的值,相當於這裡的值是一個全局變數。OK ,這裡的訪問案例和上文一致,我就不再贅述了。

預處理前台請求參數

OK,還有一種需求,有的時候我們需要預處理前台傳來的參數,比如說禁止掉某一個參數,這個也可以統一處理,OK,繼續在ExceptionHandlerAdvice方法中添加方法

@InitBinder
public void initBinder(WebDataBinder webDataBinder) {
webDataBinder.setDisallowedFields("id");
}

  • 1
  • 2
  • 3
  • 4

這個表示將客戶端傳來的id參數忽略掉,但是注意接收的方式,這裡通過對象來接收參數的時候才有效(通過對象接收這個參數的時候才會屏蔽掉id),如果直接提取還是可以提取到的,我們來看一下控制器方法,還是剛才拋異常那個方法,但是在拋異常之前我先列印一下日誌:

@RequestMapping("/user")
public String user(@ModelAttribute("msg") String msg, UserBean userBean) {
System.out.println("username is :" + userBean.getUsername() + ";and id is :" + userBean.getId());
throw new IllegalArgumentException("抱歉,參數異常/ 來自@ModelAttribute:" + msg);
}

  • 1
  • 2
  • 3
  • 4
  • 5

我們看看控制台的輸出:

SpringMVC常用配置3

OK, id已經被屏蔽掉了。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

druid中 如何從本地批(batch)導入與從hdfs 批導入數據 實戰
hue配置使用mysql

TAG:程序員小新人學習 |