Spring Boot MVC中的代码配置--WebMvcConfigurer

SpringFramework原本使用的是如下图显示的xml配置,这种xml配置曾经让很多程序员头疼,由于一个字符不对而产生一大堆不知道原因的错误,尤其是xmlns种约束文件的引入更是繁杂。

现在spring boot使用 WebMvcConfigurer来配置,其源码如下:

public interface WebMvcConfigurer {
	//帮助配置HandlerMappings路径匹配选项,
	default void configurePathMatch(PathMatchConfigurer configurer) {
	}
    //配置内容协商选项
	default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
	}
    //配置异步请求处理选项.
	default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
	}
   //配置处理程序以通过转发到来委托未处理的请求
	default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
	}
    //配置自定义转换器
	default void addFormatters(FormatterRegistry registry) {
	}
    //配置拦截器
	default void addInterceptors(InterceptorRegistry registry) {
	}
     //配置静态资源处理器
	default void addResourceHandlers(ResourceHandlerRegistry registry) {
	}
     //配置跨源请求处理
	default void addCorsMappings(CorsRegistry registry) {
	}
	/**  预先配置了响应的简单自动化控制器 	 */
	default void addViewControllers(ViewControllerRegistry registry) {
	}
	/** 配置视图解析器  */
	default void configureViewResolvers(ViewResolverRegistry registry) {
	}
	/** 	添加解析器以支持自定义控制器方法参数类型 	 */
	default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
	}
	/** 添加处理程序以支持自定义控制器方法返回值类型。 */
	default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers){
    }
	// 将HttpMessageConverters配置为用于读取或写入请求或响应的正文。 
	default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
	}	
   // 一个钩子,用于在配置后扩展或修改转换器列表。 例如,这对于允许注册默认转换器然后通过此方法 
   //插入自定义转换器可能很有用。	
	default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
	}
	/** 配置异常解析器 */
	default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
	}
	default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
	}
	 //提供自定义的{@link Validator},而不是默认创建的{@link
	@Nullable
	default Validator getValidator() {
		return null;
	}	
	@Nullable
	default MessageCodesResolver getMessageCodesResolver() {
		return null;
	}

}

上述 WebMvcConfigurer表面上是接口,实质上是有default修饰的抽象类,所以实现的类不必要全部实现其方法。

(1)配置页面跳转 addViewControllers

由于spring mvc拦截了所有请求,以前需要专门配置controller来跳转到某个页面,现在只需要配置行代码就行

        @Override
		public void addViewControllers(ViewControllerRegistry registry) {
			WebMvcConfigurer.super.addViewControllers(registry);
			registry.addViewController("/welcome").setViewName("welcome");
            registry.addViewController("/welcome2").setViewName("welcome2");
		}

(2) 配置静态资源文件--addResourceHandlers

	    @Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
				WebMvcConfigurer.super.addResourceHandlers(registry);		registry.addResourceHandler("/teststatic/**").addResourceLocations("classpath:/teststatic/");
		registry.addResourceHandler("/teststatic2/**").addResourceLocations("classpath:/teststatic2/");
		}

(3)A)配置自定义转换器--addFormatters

首先定义一个类实现一个Formatter接口,这个接口将字符串转化为T类型,这里是转化为Date类型

public class StringToDateFormatter implements Formatter<Date> {

	private String datePattern = "yyyy年MM月dd日";
	private SimpleDateFormat simpleDateFormat;   
	@Override
	public String print(Date arg0, Locale arg1) {
		// TODO Auto-generated method stub
		return new SimpleDateFormat().format(arg0);
	}
	@Override
	public Date parse(String arg0, Locale arg1) throws ParseException {
		System.out.println("from StringToDateFormatter ");
		simpleDateFormat = new SimpleDateFormat(datePattern);
		return simpleDateFormat.parse(arg0);
	
	}
}

再举一个将字符串转换为User对象的例子

public class StringToUserFormatter implements Formatter<User>{
	@Override
	public String print(User arg0, Locale arg1) {	
		return arg0.toString();
	}
	@Override
	public User parse(String arg0, Locale arg1) throws ParseException {
		//name=zhangsan;age=20
		User us=new User();
		String[] str=arg0.split(";");
		System.out.println("formatter "+str.toString());
		String[] name=str[0].split(":");
		String[] age=str[1].split(":");
		us.setName(name[1]);
		us.setAge(Integer.parseInt(age[1]));
		return us;
	}
}

 

@Override
	public void addFormatters(FormatterRegistry registry) {
		registry.addFormatter(new StringToDateFormatter());	 
	}

B)配置自定义转换器--Converter,这个转换类实现了T--->T的转换

先通过继承Converter来实现一个自定义转换类

public class StringToDateConverter implements Converter<String, Date> {
    private static ThreadLocal<SimpleDateFormat[]> formats = new ThreadLocal<SimpleDateFormat[]>() {
        protected SimpleDateFormat[] initialValue() {
            return new SimpleDateFormat[]{
                    new SimpleDateFormat("yyyy-MM"),
                    new SimpleDateFormat("yyyy-MM-dd"),
                    new SimpleDateFormat("yyyy-MM-dd HH"),
                    new SimpleDateFormat("yyyy-MM-dd HH:mm"),
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
            };
        }
    };

    @Override
    public Date convert(String source) {
        if (source == null || source.trim().equals("")) {
            return null;
        }
        System.out.println("from StringToDateConverter ");
        Date result = null;
        String originalValue = source.trim();
        if (source.matches("^\\d{4}-\\d{1,2}$")) {
            return parseDate(source, formats.get()[0]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
            return parseDate(source, formats.get()[1]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}$")) {
            return parseDate(source, formats.get()[2]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, formats.get()[3]);
        } else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
            return parseDate(source, formats.get()[4]);
        } else if (originalValue.matches("^\\d{1,13}$")) {
            try {
                long timeStamp = Long.parseLong(originalValue);
                if (originalValue.length() > 10) {
                    result = new Date(timeStamp);
                } else {
                    result = new Date(1000L * timeStamp);
                }
            } catch (Exception e) {
                result = null;
                e.printStackTrace();
            }
        } else {
            result = null;
        }

        return result;
    }

  
    public Date parseDate(String dateStr, DateFormat dateFormat) {
        Date date = null;
        try {
            date = dateFormat.parse(dateStr);
        } catch (Exception e) {

        }
        return date;
    }
}

 然后注册上面三个自定义转换器(包含了前面的配置),编写一个WebMvcConfig 类继承WebMvcConfigurer 接口,然后编写如下的代码,其中@Configuration表示这是一个配置类;@Import({WebMvcAutoConfiguration.class})导入了系统提供的一些自动配置,比如对类路径下/static、/public、/resources这些文件夹的定义。WebMvcConfig代码如下

@Configuration
@Import({WebMvcAutoConfiguration.class})
class WebMvcConfig implements WebMvcConfigurer {
   //方法1:以@Bean注入自定义转换器
	/*    @Bean
    public StringToDateConverter stringToDateConverter() {
        return new StringToDateConverter();
    }*/
    /*    	
	@Bean
    public StringToUserFormatter userToFormatter() {
        return new StringToUserFormatter();
    }*/	
	@Override
	public void addFormatters(FormatterRegistry registry) {
		//方法2:用FormatterRegistry注册自定义转换器
		registry.addFormatter(new StringToDateFormatter());
	 	registry.addFormatter(new StringToUserFormatter());	 
		registry.addConverter(new StringToDateConverter()); 
	}      
	    @Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
			// TODO Auto-generated method stub
		WebMvcConfigurer.super.addResourceHandlers(registry);
		registry.addResourceHandler("/teststatic/**").addResourceLocations("classpath:/teststatic/");
		registry.addResourceHandler("/teststatic2/**").addResourceLocations("classpath:/teststatic2/");
		}
	
	@Override
		public void addViewControllers(ViewControllerRegistry registry) {
			// TODO Auto-generated method stub
			WebMvcConfigurer.super.addViewControllers(registry);
			registry.addViewController("/welcome").setViewName("welcome");
			registry.addViewController("/welcome2").setViewName("welcome2");
		}	
}

也可以用@Bean注解来注册 ,如:

    @Bean
    public StringToDateConverter stringToDateConverter() {
        return new StringToDateConverter();
   } 

编写controller

@RestController
public class TestConvertController {
	@RequestMapping("/testConvert")	
	String handler(Date date) {
		System.err.println("the followings are the output");
		System.out.println("date is:" + date);
		Gson gson = new Gson();
		return gson.toJson(date);
	}
	// test
	@RequestMapping("/testUser")
	String handler(@RequestParam("param") User user) {
		String userJson = "{'id':22,'name':'王五','age':26}";
		Gson gson = new Gson();
		String jsonstr = gson.toJson(user);
		User user2 = gson.fromJson(userJson, User.class);
		System.err.println("the object output from gson:" + user2.toString());
		System.out.println("json string by use gson:" + jsonstr);
		System.out.println("user is:" + user.toString());
		return jsonstr;
	}
}

上述代码中国采用了google的Gson实现json字符串和java对象之间的相互转换(Gson非常好用极力推荐),需要在pom.xml中添加如下依赖:

		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.8.6</version>
		</dependency>

测试welcome.html页面 

<body>
welcome to this page
<br/>
<a href="/testConvert?date=2020-10-22 08:30:05">测试StringToDateConverter</a><br/>
<a href="/testConvert?date=2020年10月1日">测试StringToDateFormatter</a><br/>
<a href="/testUser?param=name:zhangsan;age:30">测试StringToUserFormatter</a><br/>
</body>

测试结果:

1、浏览器中输入:http://localhost:8080/welcome,有如下结果,说明配置视图控制器起作用。

2、 浏览器中输入:http://localhost:8080/teststatic/test.xml,有下图所示的结果,说明配置静态资源起作用

3、测试StringToDateFormatter和StringToDateConverter

点击第一个链接输出:

点击第二个链接输出为null,说明 Converter优先级高于Formatter

在 TestConvertController 注释掉“registry.addConverter(new StringToDateConverter()); ” 后,再点击第二个链接输出:

测试StringToUserFormatter

点击第三个链接输出:

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值