SpringMVC

1、简单介绍一下你对SpringMVC的理解?

是基于java的MVC设计模式的轻量级MVC框架,通过对Model、view、Controller分离,把web应用分成逻辑清晰的几部分,简化了开发,方便了开发人员的配合。

2、SpringMVC工作流程?

①用户发送请求,前端控制器接到请求。 ②前端控制器把请求分发给处理器映射器。 ③处理器映射器根据url去找对应的处理器。 ④获取处理器,返回给处理器映射器。 ⑤处理器映射器返回给前端控制器。 ⑥前端控制发给处理器适配器,请求执行处理器。 ⑦处理器适配器通知处理器执行业务逻辑。 ⑧然后处理器返回ModelAndView。 ⑨处理器适配器把ModelAndView返回给前端控制器。 ⑩前端控制器发给视图解析器,视图解析器根据视图名称去查询视图。 ⑪返回真正的视图。 ⑫渲染视图。 ⑬返回视图,给前端控制器。 ⑭然后响应用户的请求。

3、SpringMVC常用注解?

@RequestMapping:用于处理请求的URL,可以用于方法或类。 @RequestBody:接受请求的json数据,转换成java对象。 @ResponseBody:将controller返回对象,转成json响应回去。 @RestController:相当于@Controller和@ResponseBody。 @PathVariable:用于接收路径参数,比如@RequestMapping("/hello/{name}")声明的路径,将注解放在参数前,即可获取该值

4、怎么实现SpringMVC拦截器?

1、实现HandlerInterceptor接口;

2、继承适配器类。

5、在SpringMVC中,拦截器的使用步骤是什么?

定义拦截器类: SpringMVC 为我们提供了拦截器规范的接口,创建一个类实现HandlerInterceptor接口,重写接口中的抽象方法。 preHandle 方法:

调用时间:Controller方法处理之前

执行顺序:链式Intercepter情况下,Intercepter按照声明的顺序一个接一个执行,若返回false,则中断执行,注意:不会进入afterCompletion

postHandle方法:

调用前提:preHandle返回true

调用时间:Controller方法处理完之后,DispatcherServlet进行视图的渲染之前,也就是说在这个方法中你可以对ModelAndView进行操作

执行顺序:链式Intercepter情况下,Intercepter按照声明的顺序倒着执行。

afterCompletion 方法:

调用前提:preHandle返回true

调用时间:DispatcherServlet进行视图的渲染之后

多用于清理资源

例子:

TokenInterceptor.class

复制代码
package com.orm.mybatis.token.interceptor;
​
import com.alibaba.fastjson.JSON;
import com.orm.mybatis.token.annotation.PassToken;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.HashMap;
​
/**
 * 添加拦截器
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
    throws Exception {
        System.out.println("preHandle");
        //如果不是映射到方法直接放行
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(PassToken.class)) { //方法上面是否有注解?
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.value()){
                return true;
            }else {
                HashMap<String,String> hashMap = new HashMap<String,String>();
                hashMap.put("passTokenFalse","passTokenFalse");
                String resultJson = JSON.toJSONString(hashMap);
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().print(resultJson);
                return false;
            }
        }
        HashMap<String,String> hashMap = new HashMap<String,String>();
        hashMap.put("noPass","noPass");
        String resultJson = JSON.toJSONString(hashMap);
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(resultJson);
        return false;
    }
​
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
     Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, 
    HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

PassToken.class

复制代码
package com.orm.mybatis.token.annotation;
​
import java.lang.annotation.*;
​
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
    boolean value() default true;
}

TestLoginController.class

复制代码
package com.orm.mybatis.token.controller;
​
import com.orm.mybatis.token.annotation.PassToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
​
import java.util.HashMap;
​
@RestController
public class TestLoginController {
​
    @GetMapping("/test/one")
    public HashMap<String,String> login(){
      HashMap<String,String> hashMap = new HashMap<>();
      hashMap.put("one","one");
      return hashMap;
    }
​
    @PassToken
    @GetMapping("/test/two")
    public HashMap<String,String> login1(){
        HashMap<String,String> hashMap = new HashMap<>();
        hashMap.put("two","two");
        return hashMap;
    }
​
    @PassToken(value = false)
    @GetMapping("/test/three")
    public HashMap<String,String> login2(){
        HashMap<String,String> hashMap = new HashMap<>();
        hashMap.put("three","three");
        return hashMap;
    }
}

实验结果:

分析:由preHandle方法的解释我们知道这个方法包括后面要说到的afterCompletion和postHandle方法都只能是在当前所属的Interceptor的preHandle方法的返回值为true时才能被调用。所以没有调用。

分析:由preHandle方法的解释我们知道这个方法包括后面要说到的afterCompletion和postHandle方法都只能是在当前所属的Interceptor的preHandle方法的返回值为true时才能被调用。所以调用了。

分析:由preHandle方法的解释我们知道这个方法包括后面要说到的afterCompletion和postHandle方法都只能是在当前所属的Interceptor的preHandle方法的返回值为true时才能被调用。没有调用。因为@PassToken(value = false),后台判断了value为false的话return false。

6、SpringMVC是不是单例模式?如果是,会存在什么问题?怎么解决?

是单例模式,在多线程访问的时候有线程安全问题。 解决方案是不在控制器里面写可变状态量,如果需要使用这些可变状态,可以使用ThreadLocal机制解决,为每个线程单独生成一份变量副本,独立操作,互不影响。

7、SpringMVC优点?
  • 支持各种视图。JSP、PDF等

  • 可以与spring集成。

  • 各个组件分工明确。解耦。

相关推荐
曹牧24 分钟前
文档格式:OFD
java
豆角焖肉1 小时前
Maven进阶与搭建私服
java·maven
空中湖1 小时前
Spring AI Agent 编排:ReAct 模式 + 多 Agent 协作实战
人工智能·spring·react.js
大不点wow1 小时前
Java序列化与反序列化:让对象走出JVM
java·开发语言·jvm
止语Lab1 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活1 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
噢,我明白了1 小时前
Java中日期和字符串的处理
java·开发语言·日期
程序员天天困1 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn1 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
dkbnull1 小时前
Spring Boot请求处理组件对比详解
java·spring boot