SpringBoot中开发web应用的技巧(拦截器和自定义异常处理)

环境:JDK1.8、MAVEN 3.6.1、eclipse

开发Web应用程序

引用spring官网的一句话:
Spring Boot非常适合Web应用程序开发。您可以使用嵌入式Tomcat,Jetty或Undertow轻松创建自包含的HTTP服务器。大多数Web应用程序将使用该spring-boot-starter-web模块快速启动和运行。

结论:就是只要引入了spring-boot-starter-web模块就基本上可以进行开发web项目了

1.SpringMVC框架

Spring Web MVC框架(通常简称为“Spring MVC”)是一个丰富的“模型视图控制器”Web框架。

  1. 一般使用@Controller或者@RestController(提供JSON数据)来标记控制层,相当于MVC中的C层。
  2. 控制器中的方法使用@RequestMapping(其他版本可以使用@GetMapping或者@PostMapping)注释映射到HTTP 。
  3. 控制层中返回值可以是String类型或者ModeAndView

总结:基本上更原来的SpringMVC框架的使用方式一致。

2.Spring MVC自动配置

Spring Boot为Spring MVC提供自动配置,适用于大多数应用程序。
自动配置在Spring的默认值之上添加了以下功能:

  • 包含ContentNegotiatingViewResolverBeanNameViewResolver的Bean类。
  • 支持提供静态资源,包括对WebJars的支持
  • 自动登记ConverterGenericConverterFormatter 等Bean类
  • 支持HttpMessageConverters
  • 自动注册MessageCodesResolver
  • 静态index.html支持
  • 自定义Favicon支持
  • 自动使用ConfigurableWebBindingInitializerbean

3.创建拦截器,并配置

这里创建拦截器UserInterceptor,用来检测用户是否已经登录

/**
 * @description 创建自定的用户拦截器
 * @author hy
 * @date 2019-08-10
 */
 //主要依靠实现HandlerInterceptor接口创建拦截器
public class UserInterceptor implements HandlerInterceptor {

	public UserInterceptor() {
		System.out.println("用户自定意拦截器被实例化。。。。。。。。。。。。。");
	}

	/**
	 * @description 在处理之前执行的内容,就是到达拦截器之前的处理
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("==========================================");
		//如果未登录就抛出异常
		Object attribute = request.getSession().getAttribute("loginUser");
		if (attribute == null) {
			throw new NoLoginException();
		}
		System.out.println("执行preHandle 前置处理。。。。。");
		System.out.println("执行的方法:" + handler);
		System.out.println("==========================================");
		return true;// 返回false表示不能继续执行
		// 返回true表示可以执行下一步
	}

	/**
	 * @description 请求处理过程,查看获得的视图,执行完成获得视图
	 */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("==========================================");
		System.out.println("执行postHandle 请求处理。。。。。");
		System.out.println("当前返回的视图为:" + (modelAndView == null ? "沒有视图" : modelAndView.getViewName()));
		System.out.println("执行的方法为:" + handler);
		System.out.println("==========================================");

	}

	/**
	 * @description 请求完成后,可以用來处理异常
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("==========================================");
		System.out.println("执行的方法为::" + handler);
		if (ex == null) {
			System.out.println("没有出现异常。。。。。");
		} else {
			System.out.println("出现了异常。。。。。");
		}
		System.out.println("==========================================");

	}

}

4.创建自己的配置类一(基于继承WebMvcConfigurationSupport类实现)

例如:创建一个MyConfig

/**
 * @description 创建自己的配置类
 * @author hy
 * @date 2019-08-10
 */
@Configuration//主要继承WebMvcConfigurationSupport即可
public class MyConfig extends WebMvcConfigurationSupport {

	/**
	 * @description 解决中文乱码问题,配置json转换器
	 */
	@Override
	protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		converters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));// 添加消息转换器,可以设置当前的编码,可以解決json数据乱码的问题
		super.configureMessageConverters(converters);
	}

	/**
	 * @description 添加拦截器库
	 */
	@Override
	protected void addInterceptors(InterceptorRegistry interceptorRegistry) {
		interceptorRegistry.addInterceptor(new UserInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");// 设置拦截的匹配路径
		super.addInterceptors(interceptorRegistry);
	}

	/**
	 * @description 自定义资源映射库
	 */
	@Override
	protected void addResourceHandlers(ResourceHandlerRegistry handlerRegistry) {
		// 可以添加资源路径:如image、js、jsp等位置
		 handlerRegistry.addResourceHandler("/templates/**").addResourceLocations("classpath:/resources/**");
		super.addResourceHandlers(handlerRegistry);
		// 也可以在application.properties中使用spring.mvc.static-path-pattern = / static / **
	}

	/**
	 * @description 自定义视图解析库,一般都會用來处理其他的视图名称,例如需要特殊处理的视图名
	 * @param viewResolverRegistry 视图解析器
	 */
	@Override
	protected void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {
		/*
		 * 自定义视图解析器 ViewResolver viewResolver = new ViewResolver() {
		 * 
		 * @Override public View resolveViewName(String viewName, Locale locale) throws
		 * Exception { //治理用来处理返回的String视图,用来处理特定的视图名 return null; } };
		 * viewResolverRegistry.viewResolver(viewResolver);
		 */
		// 设置视图解析器
		// InternalResourceViewResolver internalResourceViewResolver=new
		// InternalResourceViewResolver();
		// 设置前缀
		// internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
		// 设置后缀
		// internalResourceViewResolver.setSuffix(".jsp");
		// 设置视图解析器
		// viewResolverRegistry.viewResolver(internalResourceViewResolver);
		/**
		 * 相当于在application.properties中配置 spring.mvc.view.prefix= /WEB-INF/jsp/
		 * spring.mvc.view.suffix=.jsp
		 */
		super.configureViewResolvers(viewResolverRegistry);
	}

}

当前pom文件引入了spring-boot-starter-thymeleaf

使用继承WebMvcConfigurationSupport方式实现添加拦截器中发现存在很多个问题返回json中会出现乱码问题资源配置问题视图解析器问题,那么就是说使用继承方式会将原来springboot中的原来的配置取消(这个方式并不友好有的配置需要自己定义例如:http的消息转换器)

5.创建自己的配置类二(基于实现方式WebMvcConfigurer类实现)

/**
 * @description 创建自己的配置类
 * @author hy
 * @date 2019-08-10
 */
@Configuration//主要实现WebMvcConfigurer即可
public class MyConfig implements WebMvcConfigurer {

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// TODO Auto-generated method stub
		registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**")
				.excludePathPatterns("/login");
		//WebMvcConfigurer.super.addInterceptors(registry);
	}
}

分析:首先这个方式的实现是实现接口方式,没有继承的耦合大,其次,我们不需要重写当前的Spring已近配置好的一些配置(建议使用这个)

6.入口类Application的编写

/**
 * @description 使用SpringBoot 开发web应用
 * @author hy
 * @date 2019-08-10
 */
@Controller
@SpringBootApplication
public class Application {

	@RequestMapping("/show")
	@ResponseBody
	public String show() {
		return "中文字符";
	}

	@RequestMapping("/login")
	public String login(HttpSession session) {
		session.setAttribute("loginUser", "admin");
		return "index";
	}
	
    @RequestMapping("/throwException")
	public String throwException() throws Exception {
		throw new Exception("未知错误!");
	}

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

7.创建异常类和异常处理类

异常类NoLoginException 内容如下

/**
 * @description 自定义:用户未登录异常
 * @author hy
 * @date 2019-08-10
 */
@SuppressWarnings("serial")
public class NoLoginException extends RuntimeException {

	public NoLoginException() {
		super("用户未登录错误");
	}
}

异常处理类 MyExceptionHandler 内容如下:

/**
 * @description 自定义异常处理类
 * @author hy
 * @date 2019-08-10
 */
@ControllerAdvice
public class MyExceptionHandler {

	//处理所有的未登录异常,并返回{result:noLogin} 的json数据
	@ExceptionHandler(value = { NoLoginException.class })
	@ResponseBody
	public String jsonExceptionHandler(HttpServletRequest request, Throwable ex) {
		return "{\"result\":\"noLogin\"}";
	}

	//当上面的异常处理不了的时候,就执行该异常处理,基本上处理所有的异常,返回的为视图页面
	@ExceptionHandler(value = { Exception.class })
	@RequestMapping("/error")
	public String htmlExceptionHandler(HttpServletRequest request, Throwable ex) {
		request.setAttribute("ex", ex.getMessage());
		return "error";
	}

}

8.创建简单的html页面

index.html内容如下:


<html>
<head>
<meta charset="UTF-8"/>
<title>Insert title heretitle>
head>
<body>
	<h1>欢迎<span th:text="${session.loginUser}">span>!h1>
body>
html>

error.html页面内容如下


<html>
<head>
<meta charset="UTF-8"/>
<title>Insert title heretitle>
head>
<body>
	<h1>出现了<span th:text="${ex}">span>!h1>
body>
html>

9.测试拦截器

发现当前拦截器拦截了未登录的操作,登录操作不被限制

10.测试异常处理

发现异常基本上都被捕获,登陆后,可以解决其他异常的问题

11.总结

1.当前如果需要diy自己的webConfig,需要创建自己的webConfig类,实现WebMvcConfigurer接口(推荐)(继承WebMvcConfigurationSupport类(不建议使用))并重写addInterceptors这个方法

  • addInterceptors(InterceptorRegistry interceptorRegistry)添加拦截器
  • 本人不建议使用WebMvcConfigurationSupport类方式,因为需要重写4个方法,并且需要自己配置当前的Spring原来的配置(过于繁琐),况且继承本来就是耦合度高的动作

2.创建拦截器的时候需要实现InterceptorHandler接口,并实现其中的方法

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)//在处理前的操作
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView)//请求处理过程,查看获得的视图,执行完成获得视图
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)//请求完成后,可以用來处理异常

3.在统一处理异常的时候(一般用于处理带有@Controller的注解的Controller中的异常,如果是过滤器则不会处理异常),可以使用自定义的异常处理类,该类需要以下操作

  • 该类上需要添加@ControllerAdvice,就可以处理所有的异常
  • 方法上面需要使用@ExceptionHandler(value = { 异常类 }),指明当前方法处理的异常类型
  • 如果想要返回JSON格式的错误提示数据,需要在方法上添加@ResponseBody
  • 如果需要返回错误页面需要使用@RequestMapping("/error"),并返回视图

以上内容纯属个人操作和参照springboot的api获得的见解,如有错误请联系本人!

你可能感兴趣的:(SpringBoot)