Spring MVC1
Table of Contents generated with DocToc (opens new window)
# SpringMVC
# 1. 原理时的步骤
# 1.1 编写实现了Controller接口的类并重写方法
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
//业务代码
String result="Hello World!";
modelAndView.addObject("msg", result);
//视图跳转
modelAndView.setViewName("test");
return modelAndView;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1.2 配置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">
<!-- 添加处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 添加处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器:DispatcherServlet给他的ModelAndView
1. 获取了ModelAndView中的数据
2. 解析ModelAndView的视图名字
3. 拼接视图名字,找到对应的视图 /WEB-INF/jsp/test.jsp
4. 将数据渲染到视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--Handler:处理的controller,BeanNameUrlHandlerMapping:bean-->
<bean id="/hello" class="com.com.zdk.controller.HelloController"/>
</beans>
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
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
# 1.3 配置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">
<!--1.注册DispatcherServlet:是springMvc的核心:请求分发器,前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-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>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- /和/*的区别
/:只匹配所有的请求,不去匹配jsp页面
/*:匹配所有的请求且包括jsp页面
-->
</web-app>
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
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
# 1.4 编写测试用的test.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Kuangshen</title>
</head>
<body>
${msg}
</body>
</html>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 1.5 总结
- HelloController类中的modelAndView对象可以设置数据,设置要跳转的视图的名字
- springmvc-servlet.xml中,配置视图解析器时,需要配置要访问的视图的前缀和后缀,并在中注册bean(自己写的controller类)
- web.xml中要注册DispatcherServlet,在其中利用初始化参数标签关联一个springmvc的配置文件:springmvc-servlet.xml
# 2.注解实现的步骤
# 2.1 配置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"
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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="com.com.zdk.controller"/>
<!-- 让springMVC不处理静态资源 .css,.js,.jpg,.mp3等等静态资源-->
<mvc:default-servlet-handler/>
<!--
支持mvc注解驱动
在springMVC中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效,必须向上下文中注册一个DefaultAnnotationHandlerMapping实例和一个
AnnotationMethodHandlerAdapter实例,而annotation-driven配置可以帮助我们自动完成上述两个实例的注入
-->
<mvc:annotation-driven/>
<!--视图解析器-->
<!-- 在视图解析器中,我们将所有视图都存放在/WEB-INF/目录下是为了保证视图安全,因为此目录下的文件,用户不能直接通过地址访问-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
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
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
# 2.2 配置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">
<!--1.注册DispatcherServlet:是springMvc的核心:请求分发器,前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-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>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- /和/*的区别
/:只匹配所有的请求,不去匹配jsp页面
/*:匹配所有的请求且包括jsp页面
-->
</web-app>
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
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
# 2.3 编写controller类 用注解实现1中的实现Controller,以及访问的路径
//在类上加上@RequestMapping("/hello")后请求路径变为了localhost:8080/hello/h1
@Controller
//@RequestMapping("/hello")
public class HelloController {
//请求的路径
@RequestMapping("/h1")
public String hello(Model model){
//封装数据
model.addAttribute("msg", "springMVC注解");
//返回hello字符串会被视图解析器处理
return "hello";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2.3 测试的hello.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hello</title>
</head>
<body>
${msg}
</body>
</html>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 2.4 总结
- springMVC要配置的三大件
处理器映射器 处理器适配器视图解析器,前两者在使用注解时已不需要再配置 - 取而代之的是配置注解驱动即可
<mvc:annotation-driven/>
1
# 3.Restful风格
即www.xxx.com/请求/请求/请求 而不是?参数形式
restful在springMVC中的用法
好处
代码示例
@Controller
public class RestfulController {
//第二个参数可以限定通过指定的请求方式才能请求到,如果请求方法不一致,就会报405错误
//a和b就是前端传来的参数的名字 要一致
//原:http://localhost:8080/add?a=1&b=2
//restful:在需要的那个参数前添加@PathVariable注解即可:http://localhost:8080/add/1/2
//@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET),与@GetMapping("/add/{a}/{b}")同
@PostMapping ("/add")
public String test1(int a, int b, Model model){
int result=a+b;
model.addAttribute("msg", "结果1为"+result);
return "test";
}
@GetMapping("/add/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model){
int result=a+b;
model.addAttribute("msg", "结果2为"+result);
return "test";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 4.重定向和转发
# 4.1 可以通过ServletAPI实现
- 重定向:resp.sendRedirect(/xxx.jsp)
- 转发:res.getRequestDispatcher("/WEB-INF/jsp/xxx.jsp").forward(req,resp);
- 转发可以将参数也带过去且地址栏URL不改变。重定向不可以,URL会改变
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public String test1(HttpServletRequest request, HttpServletResponse response){
System.out.println(request.getSession().getId());
return "test";
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 4.2 通过springMVC来实现
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public String test1(Model model){
model.addAttribute("msg", "ModelTest1");
//没配置视图解析器,需要全限定名,此种方式默认是转发 url不改变
return "/WEB-INF/jsp/test.jsp";
//重定向:return "forward:/WEB-INF/jsp/test.jsp";
//转发:return "redirect:/index.jsp";
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 5.接收请求参数以及数据回显
# 5.1接收请求参数
方法中的参数可自动接收与其同名的从前端传来的参数,但是当不同名时, 需要在参数前加上@RequestParam("username") String name注解, 来标注前端参数的名字,并提醒这是前端传来的参数,而不是这个方法的参数
建议在通常情况下都在参数前加上此注解,以分辨参数是否是从前端传来的
@Controller
@RequestMapping("/user")
public class UserController {
//localhost:8080/user/t1?name=xxx;
@GetMapping("t1")
public String test1(@RequestParam("username") String name, Model model){
//1. 接收前端参数
System.out.println("前端传来的参数为:"+name);
//2. 将返回的结果传递给前端
model.addAttribute("msg", name);
//3. 跳转视图
return "test";
}
//接收的是一个对象:id,name,age
//localhost:8080/user/t1?id=5&name=xxx&age=5
/**
* 1.接收前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用
* User(id=5, name=xxx, age=5)
* 2.假设传递的是一个对象User,匹配User对象中的字段名;如果名字一致则oK,否则,匹配失败
* User(id=5, name=null, age=5)(传的是username)
*/
@GetMapping("/t2")
public String test2(User user){
System.out.println(user);
return "test";
}
}
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
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
# 5.2数据回显
通过ModelAndView对象(定义在方法的参数里面)
通过Model接口(定义在方法的参数里面)
通过ModelMap!
ModelMap继承了LinkedHashMap
Model是ModelMap的精简,大部分时间用Model
# 5.2.1三者的区别
- Model 方法少,只适合用于储存数据,简化了初学者对Model对象的操作和理解
- ModelMap 继承了LinkedHashMap,除了实现了自身的一些方法,同样继承LinkedHashMap的方法和特性
- ModelAndView 可以在储存数据的同时,进行设置返回的逻辑视图,进行控制展示层的跳转
# 5.2.2乱码问题解决
- 可以自己写一个过滤器来实现
- 也直接使用springMVC自带的过滤器
- < url-pattern>/* < /url-pattern>此处,路径一定要是/*才能过滤jsp页面 单独的/就不能过滤jsp页面的乱码!!!!!
<!-- 配置springMVC的乱码过滤器,是springMVC自带的-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 6.JSON
# 6.1导包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
1
2
3
4
5
6
2
3
4
5
6
# 6.2解决乱码问题
- 方式1 原生:
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
1
- 方式2 springMVC:
<!-- JSON乱码问题统一解决-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 6.3返回JSON对象解决
- 方式1:方法中使用Jackson包提供的方法解决
@Controller
public class UserController {
@ResponseBody
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
public String json1() throws JsonProcessingException {
User user = new User(5,"张迪凯",20);
//jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper();
String str=mapper.writeValueAsString(user);
return str;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- 方式2:在类上直接使用@RestController注解,里面所有的方法都 只会返回json字符串了,不用在每一个方法上都添加@ResponseBody!
# 6.4写一个工具类返回JSON,实现日期格式转换
public class JsonUtils {
public static String getJson(Object object) throws JsonProcessingException {
return getJson(object, "yyyy-MM-dd:HH:mm:ss");
}
public static String getJson(Object object,String sdf) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//不使用时间戳的方式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sdf);
mapper.setDateFormat(simpleDateFormat);
return mapper.writeValueAsString(object);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 6.5使用阿里的fastjson
- 导包
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
1
2
3
4
5
6
2
3
4
5
6
# 6.6JSON全部示例
//@Controller
//在类上增加@RestController,类中所有的方法都只会返回json字符串,不用在每个方法上都加@ResponseBody了
@RestController
public class UserController {
//增加此注解,方法就不会走视图解析器,会直接返回字符串
//@ResponseBody
//原生的解决返回json时出现中文乱码的方式:@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
@RequestMapping(value = "/j1")
public String json1() throws JsonProcessingException {
User user = new User(5,"张迪凯",20);
//jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper();
String str=mapper.writeValueAsString(user);
return str;
}
@RequestMapping(value = "/j2")
public String json2() throws JsonProcessingException {
User user1 = new User(5,"张迪凯",20);
User user2 = new User(5,"张迪凯",20);
User user3 = new User(5,"张迪凯",20);
User user4 = new User(5,"张迪凯",20);
List<User> list=new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
return JsonUtils.getJson(list);
}
@RequestMapping(value = "/j3")
public String json3() throws JsonProcessingException {
Date date = new Date();
//ObjectMapper mapper = new ObjectMapper();
//转换时间格式方法1:传统Java方式
//SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss");
//return mapper.writeValueAsString(simpleDateFormat.format(date));
//方式2:使用ObjectMapper对象,关闭默认生成时间戳格式的Date
//mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//mapper.setDateFormat(simpleDateFormat);
return JsonUtils.getJson(date);
//ObjectMapper解析Date后默认格式为Timestamp,时间戳
//return mapper.writeValueAsString(date);
}
//fastjson示例
@RequestMapping(value = "/j4")
public String json4() throws JsonProcessingException {
User user1 = new User(1,"张迪凯",20);
User user2 = new User(2,"张迪凯",20);
User user3 = new User(3,"张迪凯",20);
User user4 = new User(4,"张迪凯",20);
List<User> list=new ArrayList<>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
return JSON.toJSONString(list);
}
}
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
在 GitHub 上编辑此页 (opens new window)
最后更新: 2022/10/04, 16:10:00