Java面試題2018---J2EE後端---Spring MVC 技術
1、畫圖並描述 Spring MVC 的工作流程
2、如何配置 Spring MVC 的核心控制器
3、什麼是 Spring MVC 對映器?有哪幾種
BeanNameUrlHandlerMapping (預設)
SimpleUrlHandlerMapping
ControllerClassNameHandlerMapping
根據類名進行匹配:
本題參考部落格:https://blog.csdn.net/cckevincyh/article/details/71405346
4、什麼是 Spring MVC 介面卡?有什麼作用
Spring定義了一個適配介面,使得每一種Controller有一種對應的介面卡實現類, 讓介面卡代替controller執行相應的方法。這樣在擴充套件Controller 時,只需要增加一個介面卡類就完成了
注:每一種controller指controller中寫的方法不同,就是不同的controller
此題可參考部落格:https://www.cnblogs.com/lulu638/p/4474698.html ,來弄清楚介面卡和controller之間的關係,以及核心控制器DispatchServlet是如何來呼叫這些介面卡的。
5、Spring MVC 的 Handler 有幾種實現方式
6、Spring MVC 將資料攜帶到前臺的方式有哪些
7、如何使用 Handler 進行請求轉發,程式碼如何實現 Handler 進行重定向
8、Spring MVC 中 406 、505等請求碼的含義
9、Spring MVC 與 AJAX 互動的註解有那幾個
10、 Spring MVC 實現檔案上傳
spring提供了CommonsMultipartResolver類來處理檔案上傳,進行如下配置:
<!-- 多部分檔案上傳 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="104857600" /> <property name="maxInMemorySize" value="4096" /> <property name="defaultEncoding" value="UTF-8"></property> </bean>
自己寫上傳的程式碼:
/*
* 採用file.TransferTo 來儲存上傳的檔案
*/
@RequestMapping("fileUpload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file) throws IOException {
long startTime=System.currentTimeMillis();
System.out.println("fileName:"+file.getOriginalFilename());
String path="E:/"+new Date().getTime()+file.getOriginalFilename();
File newFile=new File(path);
//通過CommonsMultipartFile的方法直接寫檔案(注意這個時候)
file.transferTo(newFile);
long endTime=System.currentTimeMillis();
System.out.println("方法二的執行時間:"+String.valueOf(endTime-startTime)+"ms");
return "/success";
}
此題參考部落格:https://www.cnblogs.com/fjsnail/p/3491033.html
11、Spring MVC 攔截器有什麼作用
Spring web MVC的處理器攔截器類似於Servlet開發中的過濾器Filter,用於對處理器 進行預處理和後處理。
常見的應用場景:
1、日誌記錄 :記錄請求資訊的日誌
2、許可權檢查,如登入檢查
3、效能檢測:檢測方法的執行時間
如果自己寫攔截器需實現HandlerInterceptor介面,見下題:
12、Spring MVC 怎樣自定義攔截器
例子,實現一個日誌列印的攔截器
spring中攔截器的配置:
<!-- 配置攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.yaspeed.web.interceptor.LogInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
攔截器:
package com.yaspeed.web.interceptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* 日誌攔截器 <br>
* 記錄資訊:訪問時間-Controller路徑-對應方法名-請求引數資訊-請求相對路徑-請求處理時長
*
* @author Administrator
*
*/
public class LogInterceptor implements HandlerInterceptor {
public static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class);
private static final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("ThreadLocal StartTime");
private String getParamString(Map<String, String[]> map) {
StringBuilder sb = new StringBuilder();
for (Entry<String, String[]> e : map.entrySet()) {
sb.append(e.getKey()).append("=");
String[] value = e.getValue();
if (value != null && value.length == 1) {
sb.append(value[0]).append("\t");
} else {
sb.append(Arrays.toString(value)).append("\t");
}
}
return sb.toString();
}
/**
* 將ErrorStack轉化為String.
*/
public static String getStackTraceAsString(Throwable e) {
if (e == null) {
return "";
}
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
@Override
/**
* 該方法將在請求處理之前進行呼叫<br>
* 多個Interceptor,然後在SpringMVC會根據宣告的前後順序一個接一個的執行,而且所有的Interceptor中的preHandle方法都會在<br>
* COntroller方法之前呼叫。SpringMVC的這種Interceptor鏈式結構也是可以中斷的,這種中斷方式時令preHandler的返回值為false<br>
* 當prehandler的返回值為false的時候整個請求就結束了。
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
startTimeThreadLocal.set(startTime); // 執行緒繫結變數(該資料只有當前請求的執行緒可見)
if (HandlerMethod.class.equals(handler.getClass())) {
StringBuilder sb = new StringBuilder(1000);
sb.append("-----------------------開始計時:").append(new SimpleDateFormat("hh:mm:ss.SSS").format(startTime))
.append("-------------------------------------\n");
HandlerMethod h = (HandlerMethod) handler;
sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n");
sb.append("Method : ").append(h.getMethod().getName()).append("\n");
sb.append("Params : ").append(getParamString(request.getParameterMap())).append("\n");
sb.append("URI : ").append(request.getRequestURI()).append("\n");
LOGGER.debug(sb.toString());
}
return true;
}
/**
* 在當前請求進行處理之後,也就是Controller 方法呼叫之後執行,但是它會在DispatcherServlet
* 進行檢視返回渲染之前被呼叫,所以我們可以在這個方法中對Controller 處理之後的ModelAndView 物件進行操作。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
if (HandlerMethod.class.equals(handler.getClass())) {
StringBuilder sb = new StringBuilder(1000);
sb.append("CostTime : ").append(executeTime).append("ms").append("\n");
sb.append("-------------------------------------------------------------------------------");
LOGGER.debug(sb.toString());
}
}
/**
* 該方法將在整個請求結束之後,也就是在DispatcherServlet 渲染了對應的檢視之後執行。這個方法的主要作用是用於進行資源清理工作的。
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// 列印JVM資訊。
if (LOGGER.isDebugEnabled()) {
long beginTime = startTimeThreadLocal.get();// 得到執行緒繫結的區域性變數(開始時間)
long endTime = System.currentTimeMillis(); // 2、結束時間
// 如果controller報錯,則記錄異常錯誤
if (ex != null) {
LOGGER.debug("Controller異常: " + getStackTraceAsString(ex));
}
LOGGER.debug("計時結束:" + new SimpleDateFormat("hh:mm:ss.SSS").format(endTime) + " 耗時:" + (endTime - beginTime)
+ " URI:" + request.getRequestURI());
startTimeThreadLocal.remove();
}
}
}
此題參考部落格:
https://www.cnblogs.com/jianjianyang/p/5009457.html
https://blog.csdn.net/fd2025/article/details/80564584
13、Spring MVC 的控制器是不是單例模式,如果是,有什麼問題,怎麼解決
14、如果前臺有很多個引數傳入,並且這些引數都是一個物件的,那麼怎麼樣快速得到這
個物件
15、怎麼樣在方法裡面得到 request,或者 Session
在spring的普通類中:
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
request.getSession();
在Struts的普通類中:
HttpServletRequest request = ServletActionContext.getRequest();
request.getSession();
此題參考部落格:https://blog.csdn.net/u012255097/article/details/53092628
16、怎麼樣把 ModelMap 裡面的資料放入 Session 裡面
17、當一個方法向 AJAX 返回特殊物件,譬如 Object,List 等,需要做什麼處理