一、SpringBoot直接跳转
SpringMVC可以写下面的标签,来进行跳转
<mvc:view-controller path="/luzelong" view-name="success"/>
而springboot 想实现该功能,其实也蛮容易的:
1.编写springMVC 功能扩展类:
//该类是springmvc 的功能扩展类 要求书写类上@Configuration 和 并实现WebMvcConfigurer接口
//不标注@EnableWebMvc,则下面的是springmvc的扩展 标注就是完全自定义 摒弃一切的配置
@Configuration
//public class MyMvcConfig extends WebMvcConfigurerAdapter {//1.0的时候是继承该类
public class MyMvcConfig implements WebMvcConfigurer {
//相当于配置了在xml中配置了 <mvc:view-controller path="/luzelong" view-name="success"/>
public void addViewControllers( ViewControllerRegistry registry){
//浏览器发送 /luze 请求来到success
registry.addViewController("/luze").setViewName("success");
// registry.addViewController("/list.html").setViewName("list");
}
}
springBoot 1.0需要继承的是WebMvcConfigurerAdapter 类,而到了2.0版本,该类基本已经被遗弃,只需要实现WebMvcConfigurer 接口即可。
除了上述的方式,还可以写下面的:
@Configuration
//public class MyMvcConfig extends WebMvcConfigurerAdapter {//1.0的时候是继承该类
public class MyMvcConfig implements WebMvcConfigurer {
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
@Override//下面的东西完全可以写在头顶的addViewControllers方法中
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard");
}
};
return adapter;
}
}
那么该SpringMVC扩展类中还可以写什么呢??
二、配置拦截器
无论是springmvc 还是 springboot
第一步都是编写拦截器类:
package org.lzl.bootproject.component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//拦截器 实现登录校验
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override//拦截请求
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("loginUser");
if (user == null){
//未登录,返回登录页面
request.setAttribute("msg","没有权限,请先登录");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else {
//已登录
return true;
}
}
@Override//拦截响应
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override//渲染完毕
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
第二步:将拦截器配进去
首先看看之前springmvc是怎么配置的:
<mvc:interceptors>
<!--如果 不额外配置 :默认拦截一切请求-->
<!--配置具体的拦截路径-->
<mvc:interceptor>
<!--指定拦截的路径-->
<mvc:mapping path="/**"/>
<!--指定不拦截的路径-->
<mvc:exclude-mapping path="/handler/testUpload"/>
<bean class="interceptor.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
springboot的配置方法:
@Configuration
//public class MyMvcConfig extends WebMvcConfigurerAdapter {//1.0的时候是继承该类
public class MyMvcConfig implements WebMvcConfigurer {
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {//"/", "/index", "/index.html", "/user/login", "/asserts/**"
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login","/asserts/**");
}
}
三、获取参数问题
因为SpringBoot是对SSM的整合,所以对参数获取的方法完全可以参考我的这篇博客
本文只是写一下SpringBoot是怎么开启对矩阵变量的支持的:
1.给容器添加下面的Bean,该bean是配置springMVC的核心bean
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
//不移除;矩阵变量功能就可以生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
};
}
2.写完上面的bean,矩阵变量的写法就生效了,下面开始测试:
写个测试的controller:
@ResponseBody
@RequestMapping("/jj/{path}")
public Map<?, ?> jj(@PathVariable("path") String path,
@MatrixVariable("name") String name,
@MatrixVariable("ages") List<Integer> ages){
Map<String, Object> result = new HashMap<>();
result.put("name", name);
result.put("path", path);
result.put("ages", ages);
return result;
}
然后去访问该页面:
四、SpingBoot自定义类型转化器
可以借鉴一下 SpringMVC的类型转化的逻辑这篇博客的写法
举例子(将字符串转化成学生)
学生类:
public class Student {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
}
}
1.给容器添加下面的Bean,该bean是配置springMVC的核心bean
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new Converter<String,Student>(){
@Override
public Student convert(String source) {
//source接受前端传来的String:2-zs-23
String[] studentStrArr = source.split("-");
Student student = new Student();
student.setId(Integer.parseInt(studentStrArr[0]));
student.setName(studentStrArr[1]);
student.setAge(Integer.parseInt(studentStrArr[2]));
return student;
}
});
}
};
}
测试
前端输入的时候需要安装 1-zs-23,这种格式输入
<form action="handler/testConverter">
学生信息:<input name="studentInfo" type="text"/>
<input type="submit" value="转换">
</form>
@RequestMapping("testConverter")
public String testConverter(@RequestParam("studentInfo") Student student){//因为自己写的转换器已经配置到springmvc中了,所以这里可以自动转换!
System.out.println(student);
return "success";
}
五、Spring对内容协商的支持
1、判断当前响应头中是否已经有确定的媒体类型。MediaType
2、获取客户端(PostMan、浏览器)支持接收的内容类型。(获取客户端Accept请求头字段)
demo:
- pojo
@Data
public class Person {
private String userName;
private Integer age;
private Date birth;
private Pet pet;
}
- controller
@ResponseBody //利用返回值处理器里面的消息转换器进行处理
@GetMapping(value = "/test/person")
public Person getPerson(){
Person person = new Person();
person.setAge(28);
person.setBirth(new Date());
person.setUserName("zhangsan");
return person;
}
如果什么都不配置。直接在浏览器中访问 /test/person 则会返回下面的json数据:
现在我们在pom.xml中添加下面的依赖:(开启对xml格式的支持)
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
再次访问 /test/person ,发现响应的数据为xml格式:
为什么会这样?因为浏览器的消息头中的accept默认设置了访问的优先级,看下图:
xml的优先级是0.9,而json的优先级是0.8,所以引入了那个依赖后,springBoot开始支持xml格式,默认显示的就是xml格式了。
如果是postMan这种客户端工具,则只需要指定header的accept属性,即可随意更改响应的类型。
但我们如果想此时让浏览器依旧返回json格式的数据,则需下面的额外配置:
spring:
contentnegotiation:
favor-parameter: true #开启请求参数内容协商模式
浏览器访问的地址后面 加上 ?format=json 或者 ?format=xml 来指定响应的格式类型:
自定义MessageConverter
你会发现上面的format只能写 json 或者 xml,比如我想加个x-guigu
就得完成下面的步骤 :
1.编写实现HttpMessageConverter接口的类:
package com.atguigu.boot.converter;
import com.atguigu.boot.bean.Person;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
/**
* 自定义的Converter
*/
public class GuiguMessageConverter implements HttpMessageConverter<Person> {
@Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return clazz.isAssignableFrom(Person.class);
}
/**
* 服务器要统计所有MessageConverter都能写出哪些内容类型
*
* application/x-guigu
* @return
*/
@Override
public List<MediaType> getSupportedMediaTypes() {
return MediaType.parseMediaTypes("application/x-guigu");
}
@Override
public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
//自定义协议数据的写出
String data = person.getUserName()+";"+person.getAge()+";"+person.getBirth();
//写出去
OutputStream body = outputMessage.getBody();
body.write(data.getBytes());
}
}
然后在WebMvcConfigurer这个bean中配置刚刚写好的转化器:
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new GuiguMessageConverter());
}
};
}
完成上面的配置,postman即可响应 x-guigu 了
但用浏览器的话,还需以下的配置:
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
/**
* 自定义内容协商策略
* @param configurer
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
//Map<String, MediaType> mediaTypes
Map<String, MediaType> mediaTypes = new HashMap<>();
mediaTypes.put("json",MediaType.APPLICATION_JSON);
mediaTypes.put("xml",MediaType.APPLICATION_XML);
mediaTypes.put("gg",MediaType.parseMediaType("application/x-guigu"));
//指定支持解析哪些参数对应的哪些媒体类型
ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaTypes);
// parameterStrategy.setParameterName("ff");
HeaderContentNegotiationStrategy headeStrategy = new HeaderContentNegotiationStrategy();
configurer.strategies(Arrays.asList(parameterStrategy,headeStrategy));
}
};
}
接着浏览器访问 test/person?format=gg