1. 程式人生 > >Java面試題2018---J2EE後端---Spring MVC 技術

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 等,需要做什麼處理