SpringMVC
什么是SpringMVC
Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一部分,它和Struts2一样都属于表现层的框架。
MVC可参考之前的文章 mvc架构
第一个SpringMVC程序
新建一个maven项目,取个名字一路next即可。
添加web的支持
在pom.xml导入依赖
1
2
3
4
5
6
7
8<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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<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
1
2
3
4
5
6
7
8
9
10
11
12
13public 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的信息
1
2
3
4
5
6
7
8
9<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>配置tomcat启动就好
结构的目录为
执行原理
跳转至该文章。springmvc执行原理
注解的使用
与上面的第一个Springmvc程序来对比
首先是sprngmvc的配置程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<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:default-servlet-handler/>
因为之前配置DispatcherServlet的时候配置了拦截方式为“/”,故包括了静态资源,所有springmvc会将静态资源的请求当成是普通的请求,所以会找不到对应的处理器而导致错误。这条语句将把静态资源和非静态资源的请求分开,从而避免错误。
<mvc:annotation-driven/>
这个帮我们注册了很多的类 ,包括之前的BeanNameUrlHandlerMapping和SimpleControllerHandlerAdapter,并告知spring,启用了注解。
然后是Controller类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
//自动视为一个Controller的类
//@RequestMapping("/1"),这里也可以添加路径,这里加上了那下面的路径就是/1/hello了
public class HelloController {
// 访问的路径
public String hello(Model model){
model.addAttribute("msg","hello springmvc");
return "hello";
//返回给视图解析器拼接,然后寻找视图
}
}web.xml用之前的就好,再写jsp页面就可以运行了。
springmvc-servlet.xml和web.xml基本都是不用怎么改变的,除了改一些路径。
简单的标签详解
@Controller
告诉spring该类为一个控制器,并交给spring来托管@RequestMapping
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class HelloController {
//表示获取的路径,放在类上为父级,方法上为子级。全标签是这样@RequestMapping(value="/hello2")
//访问路径为http://localhost:8080/项目名/hello1/hello2
public String hello(Model model){
model.addAttribute("msg","hello springmvc");
return "hello";
}
//@PathVariable表示绑定参数,method默认为GET,所以通过get方法就能访问,换成其他方法比如delete就会报错。
//通过访问路径http://localhost:8080/项目名/hello1/hello2/1/2就能获取a和b的值了
public String hello1(int a, 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}")
*/
public String hello1(int a, int b, Model model) {
int c = a + b;
model.addAttribute("msg",c);
return "hello";
}
}
关于重定向和转发
使用视图解析器
在SpringMvc的配置文件下注册了视图解析器,即下面的这段代码,就可以通过视图解析器来进行转发。
1 | <!--在springmvc的配置文件中注册视图解析器--> |
1 |
|
不使用视图解析器
直接使用servlet的方法
1 |
|
因为实质是servlet,所以是可以直接使用servlet的方法的,但是不推荐这么使用,过于繁琐。
使用前缀
1 |
|
前缀的优先级是比视图解析器大的,有前缀的前提下是不经过视图解析器的,建议还是注册视图解析器,转发不用前缀,重定向使用前缀进行。
数据处理
获取数据
通过url相同的参数名获取数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class HelloController {
//输入http://localhost:8080/项目名/hello?msg01=hello world!
public String hello1(String msg01, Model model){
model.addAttribute("msg",msg01);
return "hello";
}
//输入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不相同的参数名获取数据
1
2
3
4
5
6
7
8
9
10
public class HelloController {
//输入http://localhost:8080/项目名/hello?msg0=hello world!
//通过RequestParam标签绑定参数名字可以修改名字,但不能用回原来的参数名来获取了,即只能用msg0来获取
public String hello( String msg01, Model model){
model.addAttribute("msg",msg01);
return "hello";
}
}通过url来获取一个对象
首先创建一个实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public 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;
}
public String toString() {
return "user{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}获取对象
1
2
3
4
5
6
7
8
9
10
public class HelloController {
//输入http://localhost:8080/项目名/hello?name=he&id=2
//注意的是,输入的参数要与构造器的顺序一样
public String hello(User user, Model model){
model.addAttribute("msg",user);
return "hello";
}
}解析到前端页面
使用ModelAndView
1
2
3
4
5
6
7
8
9
10public 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
1
2
3
4
5
6
7
8
9
10
public class HelloController {
public String hello(Model model){
//封装数据
model.addAttribute("msg","Hello World!");
//返回跳转视图
return "hello";
}
}使用ModelMap
1
2
3
4
5
6
7
8
public class HelloController {
public String hello(ModelMap modelMap){
modelMap.addAttribute("msg","Hello World!");
return "hello";
}
}Model其实是一个接口实现类,一定程度上是继承了ModelMap,因为Model的实现也是要用到ModelMap的方法的,而ModelMap继承了LinkedHashMap,所以方法比Model多一些。
Json的处理
添加jackson-databind的依赖
1
2
3
4
5<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>实体测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public 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;
}
public String toString() {
return "user{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}Controller类
1
2
3
4
5
6
7
8
9
10//作用为跳过视图解析器,返回json字符串
public class HelloController {
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报错