红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. SpringMVC 学习笔记
  3. 正文

SpringMVC 学习笔记1:基础

2023年8月27日 926点热度 0人点赞 0条评论

1.简介

SpringMVC 是一种基于 Java 实现的 MVC 模型的轻量级 Web 框架,可以用它替换 Servlet 技术。

关于 SpringMVC 的详细介绍,可以观看这个视频。

2.快速入门

先用 Maven 创建一个 Web 应用,具体方式可以参考这篇文章。

2.1.依赖

开发的 Web 应用最终要部署在 Tomcat 上,依赖于 Servlet API。所以需要添加相关依赖:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>

要注意,这里 servlet-api 的版本与 Tomcat 版本是相关的,具体可以查看官方文档。

这里的 scope 范围是 provided,因为 Tomcat 自己就包含 servlet-api,打包时必须排除,否则会引发冲突。

其中 Servlet Spec Servlet 一列就是对应的 Servlet-api 版本,这里因为项目整合了 Tomcat7 的 Maven 插件,所以在开发阶段是运行在 Tomcat7 上的,这里就是用 3.0+ 的 servlet-api 依赖。

添加 Spring MVC 依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.10.RELEASE</version>
</dependency>

可以看到,spring-webmvc 是包含了 spring-context 依赖的:

image-20230827172010523

所以这里我们不需要额外添加对 spring-context 依赖的引用。

因为这里使用 Spring MVC 进行配置和管理 Web 应用,所以可以删除/WEB-INF/web.xml配置文件。

2.2.配置类

添加配置类:

@Configuration
@ComponentScan("cn.icexmoon.mvcdemo.controller")
public class SpringMvcConfig {
}

2.3.Controller

添加 Controller:

@Controller
public class UserController {
    @RequestMapping("/save")
    @ResponseBody
    public String save() {
        return "{'result':true,'msg':'user saved.'}";
    }
}

2.4.ServletInitializer

要让 Tomcat 能正确加载 Web 应用,还需要添加一个 Servlet 容器初始化类:

public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
    /**
     * 加载 Spring MVC 容器配置
     * @return
     */
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringMvcConfig.class);
        return context;
    }
​
    /**
     * 哪些路径请求由 Spring MVC 进行处理
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
​
    /**
     * 加载 Spring 容器配置
     * @return
     */
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}

Spring 提供一个抽象类AbstractDispatcherServletInitializer,通过实现这个类的相应方法,我们可以让 Tomcat 的 Web 容器加载 Spring MVC 容器,并告诉 Tomcat 哪些请求路径由 Spring MVC 进行响应。

2.5.测试

通过插件启动项目。

一切 OK 的话访问 Tomcat 页面(比如 http://localhost/save)就能看到响应。

如果出现 404 或其它错误,可以检查各种组件(包括 JDK)的版本是否兼容,比如 Spring 6 应当使用 Java 17 以上的版本, Spring 6 以下应当使用 Java 8(JDK 1.8)。Tomcat7 对应的 Java 版本是 7+,对应的 servlet-api 是 3.0 等等。

3.Bean 加载控制

上面的简单示例仅仅包含控制层代码,如果还包含服务层和持久层,就需要添加一个 Spring 容器来进行管理。

3.1.Spring 配置类

添加 Spring 配置类:

@Configuration
@ComponentScan(value = "cn.icexmoon.mvcdemo",
        excludeFilters = {
                @ComponentScan.Filter(
                        type = FilterType.ANNOTATION,
                        value = Controller.class
                ),
                @ComponentScan.Filter(
                        type = FilterType.ANNOTATION,
                        value = NoSpringScan.class)
        })
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
}

我们现在设想的是:Spring MVC 容器加载 controller 包下的 Bean,Spring 容器加载其余的 Bean。

所以这里需要在 Spring 的包扫描(@ComponentScan)中设置排除,具体可以用excludeFilters属性实现。

在这里除了排除@Controller注解标记的 Bean,还额外添加了一个排除自定义注解@NoSpringScan。这是因为我们还需要排除 Spring MVC 的配置类SpringMvcConfig才行,否则就会因为SpringMvcConfig中的包扫描导致 Spring 容器加载了 controller 包下的 Bean。

自定义注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoSpringScan {
}

用自定义注解标记 Spring MVC 配置类:

@NoSpringScan
@Configuration
@ComponentScan("cn.icexmoon.mvcdemo.controller")
public class SpringMvcConfig {
}

除了这种排除方式外,还可以选择让包扫描加载指定的包而非整个项目的包。

3.2.修改 ServletContainerInitConfig

在 Servlet 容器初始化类中添加 Spring 容器初始化内容:

public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
    // ...
    /**
     * 加载 Spring 容器配置
     * @return
     */
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringConfig.class);
        return context;
    }
}

3.3.测试

之后就可以在代码中整合 MyBatis,并编写服务层和持久层代码,并最终在控制层中实现对服务层的调用。具体可以参考这篇文章。

示例:

@Controller
public class UserController {
	// ...
    @RequestMapping("/user/{id}")
    @ResponseBody
    public String getUserInfo(@PathVariable("id") Integer id) {
        User user = userService.getById(id);
        System.out.println(user);
        return JSON.toJSONString(user);
    }
}

再次部署应用后请求http://localhost/user/1就能看到返回内容:

{"addr":"??","gender":"?","id":1,"password":"123","userName":"zhangsan"}

乱码是因为返回报文头中的报文格式和编码方式不对。

3.4.ServletInitializer

出了用AbstractDispatcherServletInitializer创建 Servlet 容器初始化类以外,还可以用它的一个子类AbstractAnnotationConfigDispatcherServletInitializer:

public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    /**
     * spring 容器的配置类
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    /**
     * spring MVC 容器的配置类
     * @return
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    /**
     * 哪些请求由 spring MVC 进行处理和响应
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

代码会简洁一些。

The End,谢谢阅读。

可以从这里获取本文完整的代码示例。

4.参考资料

  • 黑马程序员SSM框架教程

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: mvc spring
最后更新:2023年8月30日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
下一篇 >

文章评论

取消回复

*

code

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号