Spring MVC学习 | 注解配置Spring MVC&总结

2023-05-16

文章目录

  • 一、注解配置Spring MVC
    • 1.1 初始化类
    • 1.2 Spring MVC配置类
    • 1.3 完整配置过程
  • 二、总结
    • 2.1 常用组件
    • 2.2 执行流程


学习视频🎥:https://www.bilibili.com/video/BV1Ry4y1574R

一、注解配置Spring MVC

1.1 初始化类

🔑注解配置的原理

  • 在servlet3.0之后的环境中,服务器(或者说容器)会在类路径(src目录下)中查询javax.servlet.ServletContainerInitializer接口的实现类,如果找到该实现类就用他来配置服务器
  • 而Spring中就提供了ServletContainerInitializer接口的一个实现类——SpringServletContainerInitializer,该实现类中又会查询WebApplicationInitializer接口的实现类,在Spring3.2之后,对WebApplicationInitializer创建了一个便利的基础实现类——AbstractAnnotationConfigDispatcherServletInitializer,因此我们创建的初始化配置类WebInit只需继承AbstractAnnotationConfigDispatcherServletInitializer并重写其方法,此时服务器会自动查找到我们创建的初始化类WebInit,然后用它来配置服务器

🔑初始化类需要重写的几个方法

方法方法返回值类型解释
getRootConfigClasses()Class<?>[]指定Spring配置类;将Spring配置类的class对象添加到Class数组中返回即可;可以指定多个Spring配置类,也可以不指定(因为方法的默认返回值是长度为0的数组)
getServletConfigClasses()Class<?>[]指定Spring MVC配置类;将Spring MVC配置类的class对象添加到Class数组中返回即可;同样可以指定多个Spring MVC配置类
getServletMappigs()String[]指定前端控制器DispatcherServlet的映射规则(资源路径);将资源路径添加到String数组中返回即可;相当于web.xml中<url-pattern>标签的作用,可以设置多个资源路径
getServletFilters()Filter[]配置过滤器;将过滤器类的class对象添加到Class数组中返回即可,过滤器的class在数组中位置决定了过滤器的配置顺序;也可以配置多个过滤器

❓ 关于Spring配置类

  • 在Spring的学习中,可以创建一个类,类上添加@Configuration@ComponnetScan等注解,将类标识为配置类,然后在类中通过@Bean注解添加其他配置,用于代替Spring的配置文件,Spring MVC配置类与之类似
  • 在Spring MVC中添加Spring配置类属于SSM整合部分,这里只是简单创建一个被@Configuration标识的类作为Spring配置类,不添加其他功能实现;或者不添加也可以

1.2 Spring MVC配置类

💬概述:Spring MVC配置类命名为WebConfig,用于代替Spring MVC的核心配置文件——springmvc.xml,springmvc.xml中配置过的功能就是WebConfig类中需要实现的功能

🔑WebConfig的具体实现

💡 前5个必须配置,后面的选择配置

  • 将WebConfig标识为配置类:在类上添加@Conguration注解

  • 开启组件扫描:在WebConfig配置类上添加@ComponnetScan注解,注解的basePackages属性中添加需要扫描的包或类(basePackages是数组,可以添加多个扫描包或类)

  • 开启注解驱动:在WebConfig类上添加@EnableWebMvc注解,表示开启注解驱动的意思,无需添加属性

  • 开放对静态资源的访问(配置默认servlet):在springmvc.xml中开放对静态资源的访问使用的是<mvc:default-servlet-handler>标签,不是简单的<bean>标签,所以在配置类中实现该功能需要先实现WebMvcConfigurer接口,然后实现接口的configureDefaultServletHandling()方法,在方法中直接通过形参configurer调用enable()方法即可

    /**
     * 1. 开放对静态资源的访问(配置默认servlet)
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
    
  • 配置thymeleaf视图解析器(了解):在springmvc.xml文件配置thymeleaf时需要添加两个属性内部Bean,所以在配置类配置thymeleaf需要先创建出两个内部Bean,然后给thymeleafView视图解析器的属性赋值

    /**
     * 2.1 配置模板解析器
     */
    @Bean
    public ITemplateResolver templateResolver() {
        WebApplicationContext webApplicationContext = 
            ContextLoader.getCurrentWebApplicationContext();
        // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
            webApplicationContext.getServletContext());
    
        // 设置视图前缀
        templateResolver.setPrefix("/WEB-INF/templates/");
        // 设置视图后缀
        templateResolver.setSuffix(".html");
        // 设置编码方式
        templateResolver.setCharacterEncoding("UTF-8");
        // 设置模板
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }
    
    /**
     * 2.2 配置模板引擎,并为模板引擎注入模板解析器属性
     */
    @Bean
    public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }
    
    /**
     * 2.3 配置thymeleaf视图解析器,并为解析器注入模板引擎属性
     */
    @Bean
    public ViewResolver getThymeleafView(SpringTemplateEngine templateEngine) {
        // 先创建一个thymeleaf视图解析器对象
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    
        // 设置编码方式
        viewResolver.setCharacterEncoding("utf-8");
    
        // 注入模板引擎属性
        viewResolver.setTemplateEngine(templateEngine);
    
        return viewResolver;
    }
    
  • 配置拦截器:与开放对静态资源的访问类似,在springmvc.xml文件中配置拦截器使用的同样是mvc名称空间中的标签<mvc:interceptors>,所以配置拦截器同样需要实现WebMvcConfigurer接口,然后实现addInterceptors()方法,配置拦截器需要创建拦截器对象以及设置拦截路径

    • 创建拦截器对象:先创建好拦截器类TestInterceptor,然后在方法中直接new一个拦截器类对象即可

    • 设置拦截路径:调用形参registryaddInterceptor()方法,并将拦截器对象TestInterceptor传入,然后addInterceptor()方法后通过addPathPatterns()方法设置拦截路径

  • 配置异常处理器

    • 配置异常处理器有两种方式

      ① 异常处理器在springmvc.xml中是通过<bean>标签配置的,所以在配置类中需要使用@Bean标识对应方法即可,然后在方法中直接new一个异常处理器对象(即SimpleMappingExceptionResolver类型的对象)
      ② 异常处理器的配置还有另外一种方法——实现WebMvcConfigurer接口的方法configureHandlerExceptionResolvers()或者extendedHandlerExceptionResolvers(),同样需要在方法中new一个SimpleMappingExceptionResolver类型的对象,该方法的形参就是一个异常处理器集合resolvers,通过异常处理器对象对属性赋值后,最后将该对象添加到resolvers集合中,由此可见,该方法可以配置多个异常处理器

    • 配置异常处理器时需要实现的两个功能,即给异常处理器对象的两个属性(exceptionMappingsexceptionAttribute)赋值

      ① 创建异常与视图名的映射关系:先创建一个Properties类型的对象prop,然后通过prop对象调用setProperty()方法,将异常对应的全类名与视图名建立映射关系(形成键值对),然后调用异常处理器对象中exceptionMappings属性对应的set方法,即setExceptionMappongs(),将prop传入即可

      ❓ 关于Properties类:Properties类继承Hashtable类,而Hashtable类实现了Map接口,所以Properties类也是通过键值对的形式对数据进行存储,一般用于操作.properties文件(也是键值对形式存储数据)

      ② 设置request域中异常信息的数据名(键):直接调用exceptionAttribute属性对应的set方法——setExceptionAttribute()方法给属性赋值即可,属性值就对应request域中异常信息的键

    /**
     * 4. 方式一配置异常处理器
     */
    @Bean
    public SimpleMappingExceptionResolver getExResolver() {
        // 创建异常处理器对象
        SimpleMappingExceptionResolver exResolver = new SimpleMappingExceptionResolver();
    
        // 创建一个Properties对象,用于建立异常与视图名的映射关系
        Properties prop = new Properties();
    
        // 将数学异常与视图名error进行绑定
        prop.setProperty("java.lang.ArithmeticException", "error");
    
        // 给异常处理器的exceptionMappings属性赋值
        exResolver.setExceptionMappings(prop);
    
        // 给exceptionAttribute赋值,设置request域中异常信息的键
        exResolver.setExceptionAttribute("ex");
    
        return exResolver;
    }
    
    /*+---------------------------------------------------------------------------------+*/
    
    /**
     * 4. 方式二配置异常处理器
     */
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
        // 创建异常处理器对象
        SimpleMappingExceptionResolver exResolver = new SimpleMappingExceptionResolver();
    
        // 创建一个Properties对象,用于建立异常与视图名的映射关系
        Properties prop = new Properties();
    
        // 将数学异常与视图名error进行绑定
        prop.setProperty("java.lang.ArithmeticException", "error");
    
        // 给异常处理器的exceptionMappings属性赋值
        exResolver.setExceptionMappings(prop);
    
        // 给exceptionAttribute赋值,设置request域中异常信息的键
        exResolver.setExceptionAttribute("ex");
    
        resolvers.add(exResolver);
    }
    
  • 使用视图控制器:视图控制器同样需要实现WebMvcConfigurer接口的方法addViewControllers(),方法中直接通过形参registry调用方法addViewController()设置请求路径,然后在addViewController()方法后直接调用setViewName()方法设置请求路径对应的视图名

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 首页
        registry.addViewController("/").setViewName("index");
    }
    

1.3 完整配置过程

  1. 先删掉web.xml配置文件和springmvc.xml核心配置文件

  2. 创建出初始化类WebInit

    public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        /**
         * 指定Spring配置类
         * @return 返回Class数组,数组元素为配置类的class对象
         */
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[]{SpringConfig.class};
        }
    
        /**
         * 指定Spring MVC配置类
         * @return 返回Class数组,数组元素为配置类的class对象
         */
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{WebConfig.class};
        }
    
        /**
         * 指定DispatcherServlet的映射规则,即资源路径
         * @return 返回资源路径的字符串数组
         */
        @Override
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    
        /**
         * 配置过滤器
         * @return 返回过滤器数组
         */
        @Override
        protected Filter[] getServletFilters() {
            // 1. 创建字符集过滤器CharacterEncodingFilter
            CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
            // 1.1 设置encoding属性为utf-8
            encodingFilter.setEncoding("utf-8");
    
            // 2. 创建请求方式过滤器
            HiddenHttpMethodFilter httpMethodFilter = new HiddenHttpMethodFilter();
    
            // 3. 创建过滤器数组并返回
            return new Filter[]{encodingFilter, httpMethodFilter};
        }
    }
    
  3. 创建Spring配置类SpringConfig(这里只是简单的创建,并无具体实现)

    @Configuration
    public class SpringConfig {
        
        // coding..
    }
    
  4. 创建Spring MVC配置类WebConfig

    @Configuration
    @ComponentScan(basePackages = "com.key.mvc")
    @EnableWebMvc
    public class WebConfig implements WebMvcConfigurer {
    
        /**
         * 1. 开放对静态资源的访问(配置默认servlet)
         */
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    
        /* 2. 配置thymeleaf视图解析器 */
    
        /**
         * 2.1 配置模板解析器
         */
        @Bean
        public ITemplateResolver templateResolver() {
            WebApplicationContext webApplicationContext = 
                ContextLoader.getCurrentWebApplicationContext();
            // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
            ServletContextTemplateResolver templateResolver = 
                new ServletContextTemplateResolver(webApplicationContext.getServletContext());
    
            // 设置视图前缀
            templateResolver.setPrefix("/WEB-INF/templates/");
            // 设置视图后缀
            templateResolver.setSuffix(".html");
            // 设置编码方式
            templateResolver.setCharacterEncoding("UTF-8");
            // 设置模板
            templateResolver.setTemplateMode(TemplateMode.HTML);
            return templateResolver;
        }
    
        /**
         * 2.2 配置模板引擎,并为模板引擎注入模板解析器属性
         */
        @Bean
        public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
            SpringTemplateEngine templateEngine = new SpringTemplateEngine();
            templateEngine.setTemplateResolver(templateResolver);
            return templateEngine;
        }
    
        /**
         * 2.3 配置thymeleaf视图解析器,并为解析器注入模板引擎属性
         */
        @Bean
        public ViewResolver getThymeleafView(SpringTemplateEngine templateEngine) {
            // 先创建一个thymeleaf视图解析器对象
            ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    
            // 设置编码方式
            viewResolver.setCharacterEncoding("utf-8");
    
            // 注入模板引擎属性
            viewResolver.setTemplateEngine(templateEngine);
    
            return viewResolver;
        }
    
        /**
         * 3. 配置拦截器
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 创建拦截器对象
            TestInterceptor testInterceptor = new TestInterceptor();
    
            // 添加拦截器对象,并设置拦截路径
            registry.addInterceptor(testInterceptor).addPathPatterns("/**");
        }
    
        /**
         * 4. 配置异常处理器
         */
        @Bean
        public SimpleMappingExceptionResolver getExResolver() {
            // 创建异常处理器对象
            SimpleMappingExceptionResolver exResolver = new SimpleMappingExceptionResolver();
    
            // 创建一个Properties对象,用于建立异常与视图名的映射关系
            Properties prop = new Properties();
    
            // 将数学异常与视图名error进行绑定
            prop.setProperty("java.lang.ArithmeticException", "error");
    
            // 给异常处理器的exceptionMappings属性赋值
            exResolver.setExceptionMappings(prop);
    
            // 给exceptionAttribute赋值,设置request域中异常信息的键
            exResolver.setExceptionAttribute("ex");
    
            return exResolver;
        }
    
    
        /**
         * 5. 配置视图控制器
         */
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            // 首页
            registry.addViewController("/").setViewName("index");
            // 用户测试页面
            registry.addViewController("/testUser").setViewName("test-user");
            // 测试成功页面
            registry.addViewController("/success").setViewName("success");
            // 测试报文信息转换页面
            registry.addViewController("/testHttpMsg").setViewName("test-httpMsg");
        }
    }
    
  5. 对xml文件测试过的功能进行再测试一次:异常处理、拦截器、报文信息转换、域对象共享数据等


二、总结

2.1 常用组件

常用组件组件的实现和使用作用
前端控制器(中心控制器) DispatcherServlet由框架提供类型,开发人员只需在配置文件或配置类进行配置对请求和相应进行统一处理,是整个控制层的中心,调用其他组件对请求进行处理
处理器映射器 HandlerMapping直接由框架提供,无需创建和配置根据请求路径、请求方式等信息查找对应的处理器Handler,即控制器方法,然后获取控制器方法中所有相关对象(包括控制器对象及其对应的拦截器对象等),最后返回一个HandlerExecutionChain对象(处理执行链)
处理器 Handler直接由框架提供,无需创建和配置相当于控制器方法,对用户的请求做具体的处理,并将视图名交给视图解析器
处理器适配器 HandlerAdapter直接由框架提供,无需创建和配置执行Handler(控制器方法),并返回一个ModelAndView对象
视图解析器 ViewResolver/ThymeleafView由框架或其他依赖jar包提供类型,开发人员只需在配置文件或配置类进行配置根据视图名对视图进行解析,返回解析后的视图对象
视图 View框架提供视图类View,开发人员只需设置视图名将视图数据展示到页面

2.2 执行流程

📚常见八股文:Spring MVC执行流程

🔑文字描述

  1. 浏览器向服务器发起请求,交给前端控制器DispatcherServlet统一处理,DispatcherServlet对获取的请求路径进行解析,然后根据请求路径查找对应的请求映射(与@RequestMappingvalue值进行匹配)

  2. 如果匹配失败,即没有找到对应的请求映射,则DispatcherServlet将当前请求路径(或资源)交给服务器默认servletDefaultServlet处理,如果请求是一些静态资源(.css、.js等),则默认servlet能够处理,并成功发送给浏览器;如果请求是其他资源或路径,则默认servlet也无法处理,最终页面可能报404错误

  3. 如果匹配成功,此时DispatcherServlet会调用处理器映射器HandlerMapping对象进一步根据请求路径查找到对应的处理器Handler(即控制器方法),然后把与Handler相关的对象(包括控制器对象及其拦截器对象等)封装成一个HandlerExecutionChain对象(处理执行链,用于调用拦截器相关方法)并返回

  4. 在查找到请求路径对应的Handler(控制器方法)后,DispatcherServlet再根据Handler查找合适的处理器适配器HandlerAdapter来执行Handler

  5. 如果配置了拦截器,则在执行Handler前,会前执行拦截器的preHandle()方法,如果方法返回值为true,则继续执行Handler

  6. 处理器适配器HandlerAdapter调用handle()方法来间接执行Handler,并将Handler中所设置的模型数据和视图数据封装成一个ModelAndView对象返回。在这个过程中,除了完成请求的具体处理,Spring MVC还会对控制器方法中已有的配置(添加的形参、其他的注解)进行额外的处理

    ❓ 额外的处理

    • 报文信息转换(HttpMessageConveter):将请求报文信息(Json数据、xml等)转换成Java对象,将Java对象转换成响应报文信息
    • 数据类型转换:如果控制器方法中与请求参数对应的形参类型不是String,则Spring MVC会将String类型的请求参数转换成对应的形参类型
    • 数据格式化:对请求消息进行数据格式化,如将字符串转换成格式化数字或格式化日期等
    • 数据校验: 验证数据的有效性(长度、格式等)
  7. 如果配置了拦截器,则执行完Handler后会执行拦截器的postHandle()方法

  8. 执行完Handler后会获取到一个ModelAndView对象,DispatcherServlet会先判断此时是否出现异常,如果出现异常,会调用异常处理器改变此时的视图名,根据新的视图名更新ModelAndView对象

  9. 获取到最终的ModelAndView对象后,DispatcherServlet会将该对象传给processDispatchResult()方法,对模型数据和视图数据做进一步处理

  10. processDispatchResult()方法中调用render()方法,根据视图名采用对应的视图解析器,对视图进行解析和渲染,最后返回一个视图对象view

  11. 如果配置了拦截器,则在渲染视图后会执行拦截器的afterCompletion()方法

  12. 最后根据视图对象view将视图数据展示到页面上

🔑图解springmvc-execution-flow

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring MVC学习 | 注解配置Spring MVC&总结 的相关文章

随机推荐

  • 使用JPofiler工具分析OOM原因

    在一个项目中 xff0c 突然出现了OOM故障 xff0c 那么该如何排除 能够看到代码第几行出错 xff1a 内存快照分析工具 xff0c MAT xff0c Jprofiler Dubug xff0c 一行行代码分析 xff01 MAT
  • lambda表达式,函数式接口,链式编程,Stream流式计算

    新时代的程序员 xff1a lambda表达式 xff0c 函数式接口 xff0c 链式编程 xff0c Stream流式计算 函数式接口 函数式接口 xff1a 只有一个方法的接口 简化编程模型 xff0c 在新版本框架底层中大量应用 x
  • ForkJoin

    什么是ForkJoin ForkJoin在JDK1 7 xff0c 并行执行任务 xff01 提高效率 xff0c 大数据量 xff01 大数据 xff1a Map Reduce xff08 把大任务拆分为小任务 xff09 ForkJoi
  • 异步回调

    Future Future设计的初衷 xff1a 对将来的某个事件的结果进行建模 没有返回值的runAsync异步回调 import java util concurrent CompletableFuture import java ut
  • 记录安卓,IOS安装kali的办法

    纯做记录 xff0c 不要用此技术做违法的事情 xff0c 仅供研究 xff0c 概不负责 一年前的小日记 xff0c 照抄过来记录一下 现在安卓有一个ZeroTermux更好用 xff0c 可以傻瓜式安装kali xff0c 三星S10完
  • Java 案例大全(详细)一

    一直在更新 案例汇总比身高判断奇偶数考试评价春夏秋冬正反输出数据求和1逢七过不死神兔百钱买百鸡输出所有时间珠穆朗玛峰求和2猜数字数组直接操作比较最大值获取最小值数组内容相同查找元素反转元素评委打分用户登录遍历字符串统计字符次数字符串的拼接1
  • 一次完整的http请求过程

    浏览器输入一个URL回车后 xff0c 会发生什么呢 一 http请求的完整过程简述 1 域名解析 xff1a 使用DNS协议进行域名解析 2 建立连接 xff1a 发起TCP三次握手 3 发起http请求 xff1a 建立TCP连接成功后
  • 《上海滩》命运的真实

    上海滩 命运的真实 小时候 xff0c 家里没电视 xff0c 像80年周润华版 上海滩 这样的经典 xff0c 通常也会很难一集不漏地看全 当然 xff0c 那个时候也看不懂那个冯程程的漂亮 许文强的帅气 xff0c 更看不懂冯敬尧的强横
  • C语言实现温度转换

    例1 xff1a 有人用温度计测量出用华氏温度98 F xff0c 现在要求用C语言实现把它转换为以摄氏法表示的温度 解题思路 xff1a 这个问题的算法很简单 xff0c 关键在于找到二者之间的转化公式 xff0c 摄氏度等于九分之五乘以
  • Java的集合类有哪些?

    集合 Java的集合主要有两种 xff0c 一种是单列集合Collection xff0c 一种是双列集合Map Collection Collection是单列集合包含List和Set List List包含ArrayList LinkL
  • 《SSM医疗管理系统》计算机毕业设计|Java毕设项目|医疗管理|医疗服务|医疗系统|

    SSM医疗管理系统 项目含有源码 文档 配套开发软件 软件安装教程 项目发布教程 技术路线 xff1a 该项目采用技术jsp SpringMVC Spring Mybatis tomcat服务器 mysql数据库 开发工具eclipse 主
  • 【笔记】lamp架构框图

    一 lamp架构 1 lamp基础结构 2 分布式lamp架构 3 实际运用 二 OSI七层和TCP IP五层关系 这部分具体可以参考网址 1 OSI七层 OSI xff08 Open System Interconnect xff09 x
  • SpringBoot( 扩展篇 ==> 使用枚举完成前后端数据传输规范

    本章导学 xff1a Result类设计enum设计controller层设计service与mapper层设计 在我们平时的开发中 xff0c 后端响应回给前端的请求一般都需要规范成统一的格式 xff0c 比如下图的这种格式 xff0c
  • AD软件学习

    AD软件学习 基本快捷键 电气画线 xff1a crtl 43 W放大缩小 xff1a 鼠标滚轮 crtl 43 鼠标右键旋转 xff1a space空格键1D 2D 3D切换 xff1a 数字键1 2 3清除 xff1a T 43 M测量
  • Ubuntu 2004 鼠标可以移动但是点击无响应 排查流程

    今天工作机遇到了这个问题 xff0c 就记录一下 解决方案看这里 span class token function sudo span span class token function apt span span class token
  • SSM项目的pom,springmvc,spring,mybatis配置文件

    1 pom配置文件 一个基本上完整的pom文件 xff0c 集成了常见的spring springmvc mybatis的依赖 xff0c 同时增加了json 分页 文件上传依赖 xff0c 作为一个ssm的初学者 xff0c 使用此pom
  • 再见 Pycharm,这款开箱即用的轻量级神器你值得拥有

    文 豆豆 来源 xff1a Python 技术 ID pythonall 如果你问我最好用的 IDE 是什么 xff0c 那我肯定会毫不犹豫的告诉你 Pycharm 毕竟 jetbrains 出品必属精品 但对于很多初学者来讲 xff0c
  • Springmvc pom.xml

    lt xml version 61 34 1 0 34 encoding 61 34 UTF 8 34 gt lt project xmlns 61 34 http maven apache org POM 4 0 0 34 xmlns x
  • 中国房价不可能下降的19个理由

    中国房价不可能下降的19 个理由 2014 年01月26日 根据 腾讯房产 资料整理 在 腾讯房产 频道看到的 xff0c 所谓专家解释说的房价不可能下降有N 个无以辩驳理由 虽然少数内容缺乏数据依据 xff0c 但总体来看 xff0c 分
  • Spring MVC学习 | 注解配置Spring MVC&总结

    文章目录 一 注解配置Spring MVC1 1 初始化类1 2 Spring MVC配置类1 3 完整配置过程 二 总结2 1 常用组件2 2 执行流程 学习视频 x1f3a5 xff1a https www bilibili com v