SpringMvc 纯注解搭建和 Request 小结
SpringMvc 是一种底层基于 Servlet 实现 MVC 模型的轻量级 Web 开发框架,是一种侧重于表现层的开发技术。
SpringMvc 使用起来比 Servlet 要方便很多,性能也很不错,常用于小型项目的快速搭建和开发。本篇博客不会介绍有关 MVC 的理论知识,主要侧重于代码实践,采用纯注解的方式快速搭建 SpringMvc 工程,并展示常用的接收请求参数的方式。在本篇博客的最后会提供 Demo 的源代码。
有关 SpringMvc 的详细使用可参考官网:
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc
一、搭建工程
新建一个 maven 项目,导入相关 jar 包,我所导入的 jar 包都是最新的,内容如下:
有关具体的 jar 包地址,可以在 https://mvnrepository.com 上进行查询。
<dependencies> <!--导入 servlet 相关的 jar 包--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!--导入 Spring 核心 jar 包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.18</version> </dependency> <!--导入 SpringMvc 的 jar 包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency> </dependencies>
配置好引用的 jar 包后,打开右侧的 Maven 窗口,刷新一下,这样 Maven 会自动下载所需的 jar 包文件。
搭建好的项目工程整体目录比较简单,具体如下图所示:
项目工程结构简单介绍:
com.jobs.config 包下存储的是 SpringMvc 的配置文件和 Servlet 的初始化文件
com.jobs.controller 包下存储的是用于提供 http 请求的类
com.jobs.domain 包下存储的是 JavaBean 实体类
web 目录下放置的是网站文件,其中 statics 目录下存放是静态资源文件
二、SpringMvc 配置相关
com.jobs.config 下的 SpringMvcConfig 类是 SpringMvc 的配置类,具体内容如下:
package com.jobs.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @ComponentScan("com.jobs") //启用 mvc 功能,配置了该注解之后,SpringMvc 拦截器放行相关资源的设置,才会生效 @EnableWebMvc public class SpringMvcConfig implements WebMvcConfigurer { //配置 SpringMvc 拦截器放行的资源类型 /*@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/statics/**").addResourceLocations("/statics/"); //registry.addResourceHandler("/statics/css/**").addResourceLocations("/statics/css/"); //registry.addResourceHandler("/statics/img/**").addResourceLocations("/statics/img/"); //registry.addResourceHandler("/statics/js/**").addResourceLocations("/statics/js/"); }*/ //配置 SpringMvc 连接器放行常用资源的格式(图片,js,css) @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } //注解配置 SpringMvc 返回配置的字符串所表示的页面,从哪些去找 //可以注释掉下面的方法,这样需要在 SpringMvc 方法返回时,指定全局路径的页面地址 //这里配置的是:根据 SpringMvc 方法返回的字符串,到 /WEB-INF/pages/ 下找对应名称的 jsp 页面 @Bean public InternalResourceViewResolver getViewResolver(){ InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/pages/"); viewResolver.setSuffix(".jsp"); //如果页面需要使用JSTL标签库的话 //viewResolver.setViewClass(JstlView.class); return viewResolver; } }
这里需要注意以下几项:
- 使用注解 @ComponentScan 中的 includeFilters 指定 SpringMvc 只扫描装载带有 @Controller 注解的类,其它的注解不需要给 SpringMvc 扫描,其它的注解全部交给 Spring 来扫描装载。
- 必须在 SpringMvc 的配置类上添加 @EnableWebMvc 注解,这样才能够有机会访问到静态资源(图片、css、js)。
- 可以重写 configureDefaultServletHandling 方法,只需要一句代码 configurer.enable() 即可让 SpringMvc 拦截器放行静态资源的访问限制。
SpringMvc 技术底层是基于 Servlet 实现的,因此必须让 Servlet 装载才能实现,我们编写 ServletInitConfig 类初始化 Servlet 容器,装载 SpringMvc 的配置,具体内容如下:
package com.jobs.config; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer; import javax.servlet.DispatcherType; import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import java.util.EnumSet; public class ServletInitConfig extends AbstractDispatcherServletInitializer { //初始化 Servlet 容器,加载 SpringMvc 配置类 //创建 web 专用的 Spring 容器对象:WebApplicationContext @Override protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext cwa = new AnnotationConfigWebApplicationContext(); //装载 SpringMvc 的配置 cwa.register(SpringMvcConfig.class); return cwa; } //配置 SpringMvc 的 DispatcherServlet 拦截地址,拦截所有请求 @Override protected String[] getServletMappings() { return new String[]{"/"}; } @Override protected WebApplicationContext createRootApplicationContext() { return null; } //在servlet容器启动时进行配置统一字符编码,防止接收到的中文参数值是乱码 @Override public void onStartup(ServletContext servletContext) throws ServletException { //这行代码不能省略 super.onStartup(servletContext); //设置【获取到的请求】的统一字符编码过滤器, //无论是【请求、转发、包含】统一使用 UTF-8 编码 CharacterEncodingFilter cef = new CharacterEncodingFilter(); cef.setEncoding("UTF-8"); //注意:这里的过滤器名称必须是 characterEncodingFilter FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef); registration.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/*"); } }
经过上面两个类的处理,SpringMvc 纯注解方式已经配置完毕,下面就可以使用 SpringMvc 技术处理请求了。
三、验证搭建成果
我们编写 ReqController1 类来验证 SpringMvc 搭建成果,具体内容如下:
package com.jobs.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; //@RequestMapping 注解可以在类上使用,也可以在类中具体的方法上使用 @RequestMapping("/req1") @Controller public class ReqController1 { //使用配置的前缀和后缀 @RequestMapping("/test1") public String SpringMvcTest1() { System.out.println("SpringMvc 搭建成功...默认使用所配置的前缀和后缀"); //由于在 SpringMvcConfig 类中的 getViewResolver 方法,配置了前缀和后缀 //因此这里如果返回字符串的话,默认会到 /WEB-INF/pages/ 下找对应名称的 jsp 页面 //由于这里返回字符串 success,因此直接找 /WEB-INF/pages/success.jsp 页面 return "success"; } //临时不想使用所配置的前缀和后缀 @RequestMapping("test2") public String SpringMvcTest2() { System.out.println("SpringMvc 如果不想使用所配置的前缀和后缀,可以使用 forward 或 redirect"); //当使用了 forward 或 redirect 时,将不使用所配置的前缀和后缀 return "forward:/ok.html"; //return "redirect:/ok.html"; } //访问静态资源 @RequestMapping(value = "test3") public String SpringMvcTest3() { System.out.println("SpringMvc 查看静态资源"); //由于在 SpringMvcConfig 类中重写了 configureDefaultServletHandling 方法, //启用了常用的静态资源访问,所以 SpringMvc 不会拦截静态资源的访问 //在 picture.jsp 页面,可以看到 css 样式效果,图片展示,以及外部 js 引用后可以运行 return "picture"; } }
上面用到的静态资源内容如下:
test.css 的内容为:
h1{ color: coral; }
test.js 的内容为:
function testalert() { alert('努力学习,天天向上!!!'); }
所用到的页面内容如下:
success.jsp 页面代码为:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>请求成功</title> <link rel="stylesheet" href="${pageContext.request.contextPath}/statics/css/test.css"> </head> <body> <h1>这里是 jsp 动态页面:success.jsp</h1> <h1>请求成功,请查看控制台上打印的结果...</h1> </body> </html>
picture.jsp 页面代码为:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <link rel="stylesheet" href="${pageContext.request.contextPath}/statics/css/test.css"> </head> <body> <h1>这里是 picture.jsp 展示静态资源(图片,css,js)的访问:</h1> <img src="${pageContext.request.contextPath}/statics/img/study.jpg"/> <input type="button" onclick="testalert()" value="点击我,运行js弹出框"/> <!--建议把 js 文件放在网页的最下面,提高网页的打开速度--> <script src="${pageContext.request.contextPath}/statics/js/test.js"></script> </body> </html>
ok.html 静态页面的代码为:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>请求成功</title> <link rel="stylesheet" href="/statics/css/test.css"> </head> <body> <h1>这里是静态页面:ok.html</h1> <h1>请求成功,请查看控制台上打印的结果...</h1> </body> </html>
四、请求参数的接收
首先列出 Employee 实体类,因为下面的代码会演示使用实体类作为接收参数,来接收请求参数中的值,然后编写 ReqController2 类,来演示在实际开发中,常用的一些请求参数的接收方式,具体细节如下:
package com.jobs.domain; import java.util.List; public class Employee { //姓名 private String name; //年龄 private Integer age; //爱好 private List<String> hobby; //这里省略了各个字段的 get 和 set 方法... @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age='" + age + '\'' + ", hobby=" + hobby + '}'; } }
package com.jobs.controller; import com.jobs.domain.Employee; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; //@RequestMapping 注解可以在类上使用,也可以在类中具体的方法上使用 //@RequestMapping("req2") @Controller public class ReqController2 { //请求参数与接收参数,名称必须一致,如果参数缺少,则参数取类型默认值 //http://localhost:8080/request1?name=jobs //http://localhost:8080/request1?name=jobs&age=33 @RequestMapping("/request1") public String request1(String name, Integer age) { String result = "name=" + name + ",age=" + age; System.out.println(result); return "success"; } //设置请求参数的名称,以及是否为必须提供的参数,以及设置参数的默认值 //http://localhost:8080/request2 报错,没有提供必填参数 userName //http://localhost:8080/request2?name=jobs //http://localhost:8080/request2?name=jobs&age=33 @RequestMapping("/request2") public String request2( @RequestParam(value = "userName", required = true) String name, @RequestParam(value = "userAge", defaultValue = "30") Integer age) { String result = "name=" + name + ",age=" + age; System.out.println(result); return "success"; } //请求参数名称,与接收参数的 JavaBean 类的字段名称相同的话, //则 SpringMvc 会根据请求参数自动给 JavaBean 实例化的对象属性赋值 //http://localhost:8080/request3?name=jobs //http://localhost:8080/request3?name=jobs&age=33 @RequestMapping("/request3") public String request3(Employee emp) { String result = "name=" + emp.getName() + ",age=" + emp.getAge(); System.out.println(result); return "success"; } //如果接收参数中,普通参数名称 与 JavaBean 类的字段名称相同的话,则都会进行赋值 //http://localhost:8080/request4?name=jobs&age=33 @RequestMapping("/request4") public String request4(Employee emp, String name, Integer age) { StringBuilder sb = new StringBuilder(); sb.append("使用 JavaBean 类作为参数,获取的结果:"); sb.append("name=" + emp.getName() + ",age=" + emp.getAge()); sb.append("\r\n"); sb.append("使用普通参数获取的结果:"); sb.append("name=" + name + ",age=" + age); String result = sb.toString(); System.out.println(result); return "success"; } //使用数组作为参数,接收传入的数组数据 //http://localhost:8080/request5?hobby=唱歌&hobby=跳舞&hobby=打游戏 @RequestMapping("/request5") public String request5(String[] hobby) { if (hobby != null && hobby.length > 0) { for (String h : hobby) { System.out.println(h); } } else { System.out.println("未获取到所传入的 hobby 数据"); } return "success"; } //使用集合作为参数,接收传入的数组数据,无法直接获取数组数据 //必须要使用 @RequestParam 注解将请求参数与接收参数进行名称映射 //http://localhost:8080/request6?hobby=唱歌&hobby=跳舞&hobby=打游戏 @RequestMapping("/request6") public String request6( @RequestParam(value = "hobby") List<String> hobbylist) { if (hobbylist != null && hobbylist.size() > 0) { for (String hobby : hobbylist) { System.out.println(hobby); } } else { System.out.println("未获取到所传入的 hobby 数据"); } return "success"; } //使用 JavaBean 类作为接收参数,接收数组数据 //http://localhost:8080/request7?hobby=唱歌&hobby=跳舞&hobby=打游戏 @RequestMapping("/request7") public String request7(Employee emp) { List<String> hobbylist = emp.getHobby(); if (hobbylist != null && hobbylist.size() > 0) { for (String hobby : hobbylist) { System.out.println(hobby); } } else { System.out.println("未获取到所传入的 hobby 数据"); } return "success"; } //发来的请求数据,如果是日期类型,如果想直接使用日期类型的参数进行接收的话, //可以根据传入数据的日期格式,明确指定好接收数据的对应格式,就可以接收到具体的日期数据 //http://localhost:8080/request8?date=2022-01-21 15:20:30 @RequestMapping("/request8") public String request8(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒"); String dateString = sdf.format(date); System.out.println(dateString); return "success"; } //可以接收提交过来的 body 数据,必须使用 Post 请求方式 //默认情况下,各种请求方式都支持,可以通过 method 指定允许的请求方式 //这里可以使用 PostMan 来请求该接口,必须使用 Post 请求方式从 body 中获取数据 //http://localhost:8080/request9 @RequestMapping(value = "/request9", method = RequestMethod.POST) public String request9(@RequestBody String json) { System.out.println(json); return "success"; } }
上面的请求方式代码中,最后一个请求方法,从 body 中获取数据,需要采用 Post 请求才可以。这里可以使用 PostMan 工具进行测试,在 PostMan 工具中可以 Post 发送各种类型的数据,这里仅仅以 Post 发送 Json 数据为例,因为在实际开发中,向服务器发送 Json 格式的数据比较常用,使用 PostMan 工具请求最后一个接口的细节如下所示:
在 IDEA 工具的控制台上打印出 Post 请求发送过来的数据:
到此为止,SpringMvc 采用纯注解方式快速搭建已经介绍完毕。在 SpringMvc 的纯注解配置中实现了监控所有请求,并忽略和放行常见静态资源的请求,通过配置前缀和后缀,实现通过返回的字符串自动查找对应路径下的 jsp 页面。最后列出了常用的接收传入的参数值的几种方式。
本篇博客的 demo 源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/SpringMVC_Request.zip
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南