21.扩展SpringMVC的组件

 

2. 扩展SpringMVC的组件

1.在容器中注册视图控制器

在以前的开发中,我们想跳转到一个WEB-INF【templates】里面页面必须通过Controller,return

现在可以通过创建一个视图控制器ViewController来控制页面跳转

在pom.xml里添加thymeleaf依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

src/main/resources/templates/helloWorld.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
templates/helloWorld.html
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

@Override
public void addViewControllers(ViewControllerRegistry registry) {
// TODO Auto-generated method stub
WebMvcConfigurer.super.addViewControllers(registry);

/*
* 已经配置了默认的前缀和后缀,
* 所以setViewName()不用设置"classpath:/templates/helloWorld.html",
* 直接设置为html的文件名即可
*/
registry.addViewController("/index/hello").setViewName("helloWorld");
// 浏览器访问http://localhost:8080/index/hello,跳转到/templates/helloWorld.html页面
}

}

2.注册格式化器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.demo.controller;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.demo.vo.Student;

@Controller
@RequestMapping("index")
public class IndexController {

@RequestMapping("showDateTime")
public String showDateTime(Date date) {
System.out.println("controller date: " + date);
return "helloWorld";
}

}

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
package com.example.demo.config;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

/*
* 注册格式化器
*/
@Override
public void addFormatters(FormatterRegistry registry) {
// TODO Auto-generated method stub
WebMvcConfigurer.super.addFormatters(registry);

/*
* Formatter是一个接口,不能被实例化,
* 在这里创建一个内部类
*/
registry.addFormatter(new Formatter<Date>() {

@Override
public String print(Date object, Locale locale) {
// TODO Auto-generated method stub
return null;
}

@Override
public Date parse(String text, Locale locale) throws ParseException {
// TODO Auto-generated method stub
System.out.println("formatter text: " + text);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date paramDate = format.parse(text);
return paramDate;
}

});
}
}

浏览器访问:http://localhost:8080/index/showDateTime?date=2021-01-01 10:10:10

1
2
formatter text: 2021-01-01 10:10:10
controller date: Fri Jan 01 10:10:10 CST 2021

3.消息转化器扩展fastjson

3.1 Springmvc默认的json转换器为jackson

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
package com.example.demo.vo;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

private Integer id;
private String name;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@JsonProperty(value = "birth")
private Date birthday;
}
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
package com.example.demo.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.example.demo.vo.Student;

@Controller
@RequestMapping("index")
public class IndexController {

@RequestMapping(value = "getStudentInfo", method = RequestMethod.GET)
@ResponseBody
public Student getStudentInfo() throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date birthday = format.parse("2020-01-01 10:10:10");

Student student = new Student();
student.setId(1);
student.setName("John");
student.setBirthday(birthday);

return student;
}

}

浏览器访问http://localhost:8080/index/getStudentInfo

1
{"id":1,"name":"John","birth":"2020-01-01 10:10:10"}

以上的配置默认是jackson去作转换的

3.2 自定义Fastjson转化器

引入fastjson依赖

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>

HttpMessageConverter接口上Ctrl+T,寻找该接口的fastjson实现类

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
package com.example.demo.config;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.example.demo.vo.Student;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// TODO Auto-generated method stub
WebMvcConfigurer.super.configureMessageConverters(converters);

FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();

// 下面的配置可不设置,因为有默认值
FastJsonConfig fastJsonConfig = new FastJsonConfig();
// 设置序列化的方式
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);

converters.add(fastJsonHttpMessageConverter);
}
}
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
package com.example.demo.vo;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

private Integer id;
private String name;

// 下面的使用jackson的配置已经不生效了
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
// @JsonProperty(value = "birth")
@JSONField(format = "yyyy-MM-dd HH:mm:ss", name = "birth")
private Date birthday;

}

浏览器访问http://localhost:8080/index/getStudentInfo

1
{"birth":"2020-01-01 10:10:10","id":1,"name":"John"}

4.注册拦截器

创建拦截器

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
package com.example.demo.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInterceptor implements HandlerInterceptor {

/**
* 在调用controller的方法之前执行
* @param handler: 要访问的控制器对象
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
System.out.println("preHandle controller = " + handler.getClass().getName());
return HandlerInterceptor.super.preHandle(request, response, handler);
}

/**
* 在执行完controller的方法之后,进行转发/重定向之前执行
* @param handler: 要访问的控制器
* @param modelAndView: controller执行完之后返回的对象
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("postHandle controller = " + handler.getClass().getName() + " modelAndView = " + modelAndView.getViewName());
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}

/**
* 页面加载渲染完成之后执行
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("afterCompletion controller = " + handler.getClass().getName());
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

注册拦截器

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
package com.example.demo.config;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.example.demo.interceptor.MyInterceptor;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
// TODO Auto-generated method stub
WebMvcConfigurer.super.addInterceptors(registry);

List<String> excludePatternList = new ArrayList<String>();
excludePatternList.add("/index/hello");
excludePatternList.add("/index/getStudentInfo");

// 创建拦截器对象
MyInterceptor myInterceptor = new MyInterceptor();
// 注册拦截器
registry.addInterceptor(myInterceptor)
// 设置拦截路径
.addPathPatterns("/**")
// 设置排除拦截的路径
.excludePathPatterns(excludePatternList);
}
}

controller

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
package com.example.demo.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.example.demo.vo.Student;

@Controller
@RequestMapping("index")
public class IndexController {

@RequestMapping("hello")
public String hello() {
return "helloWorld";
}

@RequestMapping(value = "getStudentInfo", method = RequestMethod.GET)
@ResponseBody
public Student getStudentInfo() throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date birthday = format.parse("2020-01-01 10:10:10");

Student student = new Student();
student.setId(1);
student.setName("John");
student.setBirthday(birthday);

return student;
}

@RequestMapping(value = "getTimeNow")
public String getTimeNow(Model model) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dateTime = new Date();
String timeStamp = simpleDateFormat.format(dateTime);
model.addAttribute("date", timeStamp);
return "helloWorld";
}
}

html

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
templates/helloWorld.html
<br/>
time: <span th:text="${date}"></span>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1. url: http://localhost:8080/index/hello
页面:
templates/helloWorld.html
time:(空白)

控制台:
(空白)

2. url: http://localhost:8080/index/getStudentInfo
页面:
{ "birth":"2020-01-01 10:10:10", "id":1, "name":"John" }

控制台:
(空白)

3. url: http://localhost:8080/index/getTimeNow
页面:
templates/helloWorld.html
time: 2021-08-07 07:49:41

控制台:
preHandle controller = org.springframework.web.method.HandlerMethod
postHandle controller = org.springframework.web.method.HandlerMethod modelAndView = helloWorld
afterCompletion controller = org.springframework.web.method.HandlerMethod