什么是SpringMVC
Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一部分,它和Struts2一样都属于表现层的框架。
MVC可参考之前的文章 mvc架构
第一个SpringMVC程序
-
新建一个maven项目,取个名字一路next即可。
-
添加web的支持

-
在pom.xml导入依赖
<dependencies> <!--spring-webmvc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.6.RELEASE</version> </dependency> </dependencies> -
在resources下创建配置springmvc的配置文件,我这里是springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/beans "> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!--注册并配置视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> <!--hello的Handler,匹配到创建的HelloController--> <bean id="/hello" class="com.chen.HelloController"/> </beans> -
配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--注册并配置DispatcherServlet--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 关联springmvc的配置文件,这里是springmvc-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别-1--> <load-on-startup>1</load-on-startup> </servlet> <!--匹配请求--> <!--/ 匹配了除了jsp页面的所有请求--> <!--/* 匹配所有的请求--> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app> -
在Java文件夹下创建HelloController
public class HelloController implements Controller { //在idea有两个Controller接口,导入的是org.springframework.web.servlet.mvc下 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { //ModelAndView ModelAndView mv = new ModelAndView(); //封装对象 mv.addObject("msg","HelloSpringMVC!"); //封装要跳转的视图 mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp return mv; } } -
然后在WEB-INF的jsp的文件夹下创建hello.jsp文件,显示msg的信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html> -
配置tomcat启动就好
结构的目录为

执行原理
跳转至该文章。springmvc执行原理
注解的使用
与上面的第一个Springmvc程序来对比
-
首先是sprngmvc的配置程序
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--使用注解要添加扫描的包--> <context:component-scan base-package="com.yw.controller"/> <mvc:default-servlet-handler/> <mvc:annotation-driven/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>-
<mvc
/>因为之前配置DispatcherServlet的时候配置了拦截方式为“/”,故包括了静态资源,所有springmvc会将静态资源的请求当成是普通的请求,所以会找不到对应的处理器而导致错误。这条语句将把静态资源和非静态资源的请求分开,从而避免错误。
-
<mvc
/>这个帮我们注册了很多的类 ,包括之前的BeanNameUrlHandlerMapping和SimpleControllerHandlerAdapter,并告知spring,启用了注解。
-
-
然后是Controller类
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; //自动视为一个Controller的类 //@RequestMapping("/1"),这里也可以添加路径,这里加上了那下面的路径就是/1/hello了 @Controller public class HelloController { // 访问的路径 @RequestMapping("/hello") public String hello(Model model){ model.addAttribute("msg","hello springmvc"); return "hello"; //返回给视图解析器拼接,然后寻找视图 } } -
web.xml用之前的就好,再写jsp页面就可以运行了。
::: success
springmvc-servlet.xml和web.xml基本都是不用怎么改变的,除了改一些路径。
:::
简单的标签详解
-
@Controller 告诉spring该类为一个控制器,并交给spring来托管
-
@RequestMapping
@Controller @RequestMapping("/hello1") public class HelloController { //表示获取的路径,放在类上为父级,方法上为子级。全标签是这样@RequestMapping(value="/hello2") @RequestMapping("/hello2") //访问路径为http://localhost:8080/项目名/hello1/hello2 public String hello(Model model){ model.addAttribute("msg","hello springmvc"); return "hello"; } //@PathVariable表示绑定参数,method默认为GET,所以通过get方法就能访问,换成其他方法比如delete就会报错。 @RequestMapping(value="/hello2/{a}/{b}",method = RequestMethod.GET) //通过访问路径http://localhost:8080/项目名/hello1/hello2/1/2就能获取a和b的值了 public String hello1(@PathVariable int a,@PathVariable int b, Model model){ int c = a + b; model.addAttribute("msg",c); return "hello"; } //通过method参数就会有以下的衍生注解代表不同方法,不同的是衍生注解只能放在方法上 /* @GetMapping("/hello2/{a}/{b}") @PostMapping("/hello2/{a}/{b}") @PutMapping("/hello2/{a}/{b}") @DeleteMapping("/hello2/{a}/{b}") @PatchMapping("/hello2/{a}/{b}") */ @GetMapping("/hello2/{a}/{b}") public String hello1(@PathVariable int a,@PathVariable int b, Model model){ int c = a + b; model.addAttribute("msg",c); return "hello"; } }
关于重定向和转发
使用视图解析器
在SpringMvc的配置文件下注册了视图解析器,即下面的这段代码,就可以通过视图解析器来进行转发。
<!--在springmvc的配置文件中注册视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id = "internalResourceViewResolver">
<!--前缀和后缀,前缀需手动索引-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","Hello World!");
return "hello";
//返回给视图解析器就会拼接成/WEB-INF/jsp/hello.jsp
}
}
不使用视图解析器
直接使用servlet的方法
@Controller
public class HelloController {
//转发
@GetMapping("/hello1")
public void hello1(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.getWriter().println("Hello World!");
}
//转发
@GetMapping("/hello2")
public void hello2(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.sendRedirect("index.jsp");
}
//重定向
@GetMapping("/hello3")
public void hello3(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setAttribute("msg","Hello World!");
request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request,response);
}
}
因为实质是servlet,所以是可以直接使用servlet的方法的,但是不推荐这么使用,过于繁琐。
使用前缀
@Controller
public class HelloController {
//forward前缀 转发
@GetMapping("/hello1")
public String hello1(Model model){
model.addAttribute("msg","Hello World!");
return "forward:/WEB-INF/jsp/hello.jsp";
}
//forward前缀 跳转到目标方法
@GetMapping("/hello2")
public String hello2(Model model){
model.addAttribute("msg","Hello World!");
return "forward:/hello1";
}
//redirect前缀 重定向
@GetMapping("/hello3")
public String hello3(Model model){
model.addAttribute("msg","Hello World!");
return "redirect:/index.jsp";
}
}
前缀的优先级是比视图解析器大的,有前缀的前提下是不经过视图解析器的,建议还是注册视图解析器,转发不用前缀,重定向使用前缀进行。
数据处理
获取数据
-
通过url相同的参数名获取数据
@Controller public class HelloController { @GetMapping("/hello1") //输入http://localhost:8080/项目名/hello?msg01=hello world! public String hello1(String msg01, Model model){ model.addAttribute("msg",msg01); return "hello"; } @GetMapping("/hello2") //输入http://localhost:8080/项目名/hello?msg01=hello&msg02= world! public String hello2(String msg01,String msg02,Model model){ model.addAttribute("msg",msg01+msg02); return "hello"; } } -
通过url不相同的参数名获取数据
@Controller public class HelloController { @GetMapping("/hello") //输入http://localhost:8080/项目名/hello?msg0=hello world! //通过RequestParam标签绑定参数名字可以修改名字,但不能用回原来的参数名来获取了,即只能用msg0来获取 public String hello(@RequestParam("msg0") String msg01, Model model){ model.addAttribute("msg",msg01); return "hello"; } } -
通过url来获取一个对象
-
首先创建一个实体类
public class user { String name; int id; public user(String name, int id) { this.name = name; this.id = id; } public String getName() { return name; } public int getId() { return id; } @Override public String toString() { return "user{" + "name='" + name + '\'' + ", id=" + id + '}'; } } -
获取对象
@Controller public class HelloController { @GetMapping("/hello") //输入http://localhost:8080/项目名/hello?name=he&id=2 //注意的是,输入的参数要与构造器的顺序一样 public String hello(User user, Model model){ model.addAttribute("msg",user); return "hello"; } }
-
解析到前端页面
-
使用ModelAndView
public class HelloController implements Controller { public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //封装数据 mv.addObject("msg", "Hello World!"); //封装跳转页面 mv.setViewName("hello"); return mv; } } -
使用Model
@Controller public class HelloController { @GetMapping("/hello") public String hello(Model model){ //封装数据 model.addAttribute("msg","Hello World!"); //返回跳转视图 return "hello"; } } -
使用ModelMap
@Controller public class HelloController { @GetMapping("/hello") public String hello(ModelMap modelMap){ modelMap.addAttribute("msg","Hello World!"); return "hello"; } }
Model其实是一个接口实现类,一定程度上是继承了ModelMap,因为Model的实现也是要用到ModelMap的方法的,而ModelMap继承了LinkedHashMap,所以方法比Model多一些。
Json的处理
-
添加jackson-databind的依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.0</version> </dependency> -
实体测试类
public class User { String name; int id; public User(String name, int id) { this.name = name; this.id = id; } public String getName() { return name; } public int getId() { return id; } @Override public String toString() { return "user{" + "name='" + name + '\'' + ", id=" + id + '}'; } } -
Controller类
@RestController//作用为跳过视图解析器,返回json字符串 public class HelloController { @RequestMapping("/hello") public String json() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); User user = new User("yww", 2); String res = mapper.writeValueAsString(user); return res; } }
注意的是新加依赖要刷新project setting里的lib目录,不然没添加会直接500报错