Spring Boot Spring Mvc

一、Spring Mvc

1.1 概念

Spring mvc是Spring框架的一个模块,他是基于Servlet API和mvc设计模式构建的原始Web框架,从一开始就包含在Spring框架中,

1.2 工作原理

在这里插入图片描述 * DispatcherServlet:前端控制器,不用程序员编写,springmvc提供

  • HandlerMapping:处理器映射器,负责查找处理请求的Handler,不用程序员编写,springmvc提供
  • HandlerAdapter:处理器适配器,负责调用对应Handler的功能方法处理器请求,不用程序员编写,springmvc提供
  • Handler:处理器(后端控制器),负责真正处理请求的类,需要程序员编写,编程时通常会将Handler叫Controller(控制器)
  • ModelAndView:模型数据和逻辑视图的综合体,不需要程序员编写,springmvc提供
  • ViewResolver:视图解析器,负责将逻辑视图解析成真正的视图,真正的视图=前缀+逻辑视图名+后缀,不需要程序员编写,springmvc提供
  • View:视图,程序员要编写。视图可以是jsp html等。

a. 用户向服务器发送请求,请求被 springMVC 前端控制器 DispatchServlet 捕获;
b. DispatcherServle 对请求 URL 进行解析,得到请求资源标识符(URL),然后根据该 URL 调用 HandlerMapping
将请求映射到处理器 HandlerExcutionChain;
c. DispatchServlet 根据获得 Handler 选择一个合适的 HandlerAdapter 适配器处理;
d. Handler 对数据处理完成以后将返回一个 ModelAndView()对象给 DisPatchServlet;
e. Handler 返回的 ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet 通过
ViewResolver 试图解析器将逻辑视图转化为真正的视图 View;
h. DispatcherServle 通过 model 解析出 ModelAndView()中的参数进行解析最终展现出完整的 view 并返回给客户端;

1.3 Controller方法的返回值类型

  • ModelAndView
  • String
  • void

二、参数绑定

2.1 概念

将请求参数中的值绑定到Controller方法中

2.2 支持的类型

  • 默认数据类型:

HttpServletRequest、HttpServletResponse、HttpSession、Model/ModelMap:ModelMap是Model接口的实现类
Model:模型,保存数据的对象就是Model,可以将Model当成一个和request session一样的容器。

  • 基础数据类型

byte short int long char boolean float double

  • 基础数据类型的封装类

Byte Short Integer Long Character Boolean Float Double

  • String
  • 自定义java类型
  • 自定义java类型的封装类
  • 数组
  • springmvc不支持列表
  • 日期处理,日期类型添加注解

2.3 请求参数绑定

@RequestMapping(“name”),类似可以绑定参数

 @RequestMapping("/get/{name}/{age}")
    @ResponseBody
    public String getNameorAge(@PathVariable String name, @PathVariable String age){
        return name + " " + age;
    }

对请求参数做处理:

    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new Converter<String, String>() {
            @Override
            //处理前台传入参数是String类型,而后台接受的参数类型是Integer类型的参数
            public String convert(String s) {
                return s == null ? null : s + "hello";
            }
        });
    }

最终输出:
在这里插入图片描述

2.4 @RequestHeader注解

 @RequestMapping("/header")
    @ResponseBody
    public String get(@RequestHeader("hello") String hello){
        return hello;
    }

@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。
在这里插入图片描述

2.5 @CookieValue注解

@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。

2.6 @RequestParam注解

@RequestParam注解用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容。提交方式为get或post。(Http协议中,form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded);

@RequestParam注解实质是将Request.getParameter() 中的Key-Value参数Map利用Spring的转化机制ConversionService配置,转化成参数接收对象或字段,
get方式中queryString的值,和post方式中body data的值都会被Servlet接受到并转化到Request.getParameter()参数集中,所以@RequestParam可以获取的到;

该注解有三个属性: value、required、defaultValue; value用来指定要传入值的id名称,required用来指示参数是否必录,defaultValue表示参数不传时候的默认值。

  @RequestMapping("/param")
    @ResponseBody
    public String param(@RequestParam(value = "key",required = true,defaultValue = "0")String key){
        return key;
    }

在这里插入图片描述## 2.7 @RequestBody注解

@RequestBody注解用来处理HttpEntity(请求体)传递过来的数据,一般用来处理非Content-Type: application/x-www-form-urlencoded编码格式的数据;
GET请求中,因为没有HttpEntity,所以@RequestBody并不适用;
POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用HandlerAdapter配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。

2.8 参考

一篇文章弄懂Spring MVC的参数绑定

2.9 中文乱码处理

配置处理中文乱码的过滤器

三、Responsebody和RequestBody

3.1 responsebody

@ResponseBody使用在方法的声明上
作用:将java对象转成Json格式数据。

测试

 @RequestMapping("/response")
    @ResponseBody
    public User getUser(){
        User user = new User();
        user.setAge("23");
        user.setName("李四");
        return user;
    }

在这里插入图片描述

3.2 requestbody

@RequestBody使用在controller方法的参数上。
作用是将json格式的数据转成java对象。

测试:

  @RequestMapping("/request")
    @ResponseBody
    public String request(@RequestBody User user){
      return  user.getAge() + user.getName();
    }

在这里插入图片描述

四、在Spring Boot中整合

4.1 配置类

注意:添加@EnableWebMvc意味着全面接管Spring MVC,以前的自动配置失效了

@Configuration
@EnableWebMvc
public class Config implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        //如果路径是/test,设置成true,则如/test.也映射到/test目录下
        configurer.setUseSuffixPatternMatch(true);
        //如果设置成false,则只处理/test请求,否则会处理/test/和/test
        configurer.setUseTrailingSlashMatch(false);
        //为true的时候,下面的方法才起最用
        configurer.setUseRegisteredSuffixPatternMatch(false);
    }

    @Override
    //只有当后缀是pdf,如果是test.pdf才起效,其他事都是404
    //使用什么类型的工具去处理
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.mediaType("pdf", MediaType.APPLICATION_PDF);
        //是否忽略请求头中的类型
        configurer.ignoreAcceptHeader(false);
        //是否通过参数指定文件类型
        configurer.favorParameter(false);
        //是否只是用media指定的类型
        configurer.useRegisteredExtensionsOnly(true);
    }
    //当通过dispatcherServlet没有找到对应的Handle时,使用默认的DefaultServletHandler来处理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Override
    //添加对象转换Convert和格式化Format
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new Converter<String, String>() {
            @Override
            //处理前台传入参数是String类型,而后台接受的参数类型是Integer类型的参数
            public String convert(String s) {
                return s == null ? null : s + "hello";
            }
        });
    }

    @Override
    //配置静态资源的访问规则及查找静态资源的路径
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //处理所有html请求,到static目录下查找
        //registry.addResourceHandler("/**.html").addResourceLocations("ClassPath:/static/");
    }

    @Override
    //进行跨域访问相关配置
    public void addCorsMappings(CorsRegistry registry) {
        //可以跨域的路径,跨域访问的访问者,
        registry.addMapping("/test/**").allowedOrigins("http://localhost:8080/").
                //可以跨域的方法,跨域访问的Headers
                allowedMethods("Get","Post").allowedHeaders();
    }

    @Override
    //配置简单自动的Controller
    public void addViewControllers(ViewControllerRegistry registry) {
        //配置路径跳转
        registry.addRedirectViewController("/b", "/test");
        //将路径映射到某个视图上
        registry.addViewController("/c").setViewName("b");
        //指定某个请求的状态码
        registry.addStatusController("/badRequest", HttpStatus.BAD_REQUEST);
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        //添加html的视图解析器
        //将Controller返回的String类型的视图名称添加前缀和后缀
        //registry.viewResolver(new InternalResourceViewResolver("/",".html"));
    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        //配置当哪个异常时跳到哪个页面
        resolvers.add(new HandlerExceptionResolver() {
            @Override
            public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
                if(e instanceof NullPointerException){
                    ModelAndView a = new ModelAndView("a");
                    a.addObject("error","出现空指针异常");
                }
                //处理其他异常
                return new ModelAndView("error");
            }
        });
    }
}

4.2 页面的跳转,重定向

    //转发
    @RequestMapping(value = "/data",method = RequestMethod.GET)
    public String data(){
        return "forward:/ad";
    }
    //重定向
    @RequestMapping(value = "direct", method = RequestMethod.GET)
    public String direct(){
        return "redirect:/ad";
    }

4.3 返回ModelAndView对象

    //转发
    @RequestMapping(value = "/data",method = RequestMethod.GET)
    public String data(){
        return "forward:/ad";
    }
    //重定向
    @RequestMapping(value = "direct", method = RequestMethod.GET)
    public String direct(){
        return "redirect:/ad";
    }

五、过滤器和拦截器

5.1 过滤器

  • 一定要在主类中加上扫描过滤器的注解:
@ServletComponentScan(value = "com.spring_mvc.demo.Filter.myFilter")
  • 过滤器实现
@WebFilter(urlPatterns = "/",filterName = "tiger")
public class myFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("过滤器初始化");
    }

    @Override
    public void destroy() {
        System.out.println("过滤器销毁了");

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest ser = (HttpServletRequest) servletRequest;
        String requestURI = ser.getRequestURI();
        if(requestURI.contains("no")){
            servletRequest.getRequestDispatcher("/failed").forward(servletRequest,servletResponse);
        }
        else {
            filterChain.doFilter(servletRequest, servletResponse);
        };
        System.out.println("filter处理中");
    }
}

  • Controller
  @RequestMapping("/failed")
    @ResponseBody
     public String failed(){
       return "来到了错误页面";
    }
}
  • 结果
    在这里插入图片描述

5.2 拦截器

  • 注册自己的拦截器,在配置类中的addInterceptors方法中添加
 @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new myInterceptor()).addPathPatterns("/**").excludePathPatterns("a.do");
    }
  • 测试:
public class myInterceptor implements HandlerInterceptor {
    @Override
    //请求处理之前调用
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        if(requestURI.contains("hello")){
            request.getRequestDispatcher("failed").forward(request,response);
            System.out.println("拦截器起作用");
            return false;
        }
        else {
            System.out.println("拦截器不起作用");
            return true;
        }
    }

    @Override
    //请求处理之后,视图被渲染之前调用
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("视图被渲染");
    }
    //视图渲染之后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("视图渲染之后");
    }
}

5.4 过滤器和拦截器的区别

不同点:

  • 拦截器是基于java的反射机制的(拦截器–>处理器(Controller)),而过滤器是基于函数回调。doFilter()
  • 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  • 拦截器只能对非.jsp的请求起作用,而过滤器则可以对几乎所有的请求起作用(包括.jsp)。
  • Filter是Servlet规范中定义的,拦截器是Spring框架中的
  • 触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的
  • 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,拦截器归Spring管理

相同点:

都是aop编程思想的体现,可以在程序执行前后做一些操作,如权限操作,日志记录等

SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系

5.5 注意事项

  • 使用过滤器的这时候,不能配置:
 public void addInterceptors(InterceptorRegistry registry) {
        //registry.addInterceptor(new myInterceptor()).addPathPatterns("/**").excludePathPatterns("a.do");
    }

否则过滤器会失效。

  • 使用过滤器不能加component注解

六、异常处理

6.1 在配置文件中添加异常处理逻辑

@Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        //配置当哪个异常时跳到哪个页面
        resolvers.add(new HandlerExceptionResolver() {
            @Override
            public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
                if(e instanceof NullPointerException){
                    ModelAndView a = new ModelAndView("NullPoint");
                    a.addObject("error","出现空指针异常");
                    return a;
                }
                if(e instanceof ArithmeticException){
                    ModelAndView byZero = new ModelAndView("ByZero");
                    byZero.addObject("Error","除数为0");
                    return byZero;
                }
                //处理其他异常
                return new ModelAndView("error");
            }
        });
    }

6.2 添加对应的视图

比如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>除数为0的异常</h1>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值