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 等,需要做什么处理

猜你喜欢

转载自blog.csdn.net/jinhaijing/article/details/84818026