文章目录
处理全局异常Spring Boot MVC
提示
Spring Boot默认采用了org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
该类自动配置了org.springframework.boot.web.servlet.error.ErrorController
该类,它里面定义了两个error处理方式,一个是json,一个html
可以看一下下图
①Spring Boot自动配置的错误组件ErrorMvcAutoConfiguration
②ErrorMvcAutoConfiguration类中的BasicErrorController(定义了error,分别是json和html的)
③可以看到默认的错误信息
配置全局异常
-
编写Controller继承
AbstractErrorController
或者实现ErrorController
接口@Controller public class GlobalErrorController implements ErrorController{ @RequestMapping("/error") public ModelAndView exe(){ return new ModelAndView("error"); } @Override public String getErrorPath(){ return "/error"; } }
需要注意,重写的方法返回值请作为自定义ModelAndView组建的名字,并且视图组件添加@RequestMapping注解
-
配置error.html错误页面
我这里使用thymeleaf模板
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"/> <title>错误页面</title> </head> <body> <h3>服务器坐火箭去太空了~</h3> </body> </html>
配置单个异常前的准备
我这里为了测试编写了一个计算阶乘的Controller
package vip.javer.springbootmvc.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import vip.javer.springbootmvc.entity.Tips;
import java.math.BigInteger;
import java.util.ArrayList;
/**
* Class Describe:计算Controller,这里是为了测试单个异常
*
* @author biuaxia
* @date 2018/12/13 19:23
*/
@RestController
public class CacController {
@RequestMapping(value = "cac.do", method = {RequestMethod.GET, RequestMethod.POST})
/**
* TestUrl:/cac.do?no=123
*/
public Tips cac(int no) {
Tips tips = new Tips();
BigInteger integer;
Integer maximumNumberOfAfferents = 300;
if (no > maximumNumberOfAfferents) {
tips.setStatusCode(400);
tips.setMsg("error");
tips.setData("您传入的数字大于300,对服务器性能消耗过大,请调小数字");
return tips;
}
try {
integer = bigNumber(no);
} catch (Exception e) {
tips.setStatusCode(400);
tips.setMsg("error");
tips.setData("计算异常");
return tips;
}
tips.setStatusCode(200);
tips.setMsg("success");
tips.setData(integer);
return tips;
}
/**
* 阶乘算法
* 利用BigInteger类计算阶乘
*
* @param num
* @return
*/
private static synchronized BigInteger bigNumber(int num) {
//创建集合数组
ArrayList list = new ArrayList();
//往数组里添加一个数值
list.add(BigInteger.valueOf(1));
for (int i = list.size(); i <= num; i++) {
//获得第一个元素
BigInteger lastfact = (BigInteger) list.get(i - 1);
//获得下一个数组
BigInteger nextfact = lastfact.multiply(BigInteger.valueOf(i));
list.add(nextfact);
}
//返回数组中的下标为num的值
return (BigInteger) list.get(num);
}
}
代码写好了,如果说我们传入的参数没有或者其他情况则会触发我们的全局异常,那么如何自定义这里的异常?
配置单个异常
在之前的Controller再追加代码
@ExceptionHandler
public Tips error(Exception e) {
Tips tips = new Tips();
tips.setStatusCode(413);
tips.setMsg("waring");
tips.setData("出异常啦\t" + e.getCause());
return tips;
}
Spring Boot的MVC拦截器
-
编写组件实现HandlerInterceptor
package vip.javer.springbootmvc.interceptor; import org.springframework.stereotype.Component; import org.springframework.ui.ModelMap; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Class Describe: * * @author biuaxia * @date 2018/12/13 19:45 */ @Component public class MvcInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { String param = httpServletRequest.getQueryString(); System.out.println("之前\t请求了:" + httpServletRequest.getRequestURI() + "\t携带参数为:" + param + "\tURL:" + httpServletRequest.getRequestURL()); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("已处理\t"); } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("准备返回数据\t"); } }
需要注意的是,这里请加上**@Component**注解,方便后面注入
-
新建配置组件继承
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
package vip.javer.springbootmvc.interceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Class Describe: * * @author biuaxia * @date 2018/12/13 19:50 */ @Configuration public class MvcConfiguration extends WebMvcConfigurerAdapter { /** * 通过扫描注入刚才的MvcInterceptor */ private final MvcInterceptor interceptor; @Autowired public MvcConfiguration(MvcInterceptor interceptor) { this.interceptor = interceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(interceptor).addPathPatterns("/*"); } }
注意
在addPathPatterns();
方法内可以传入数据,我这里是全拦截了
Spring Boot 使用AOP
使用aop技术监控每个方法执行时间
切面 计算方法执行时间
切入点 所有Controller类的方法
通知 环绕通知@Around
配置AOP的使用
-
引入AOP工具包
spring-boot-starter-aop
-
新建计时类
package vip.javer.springbootmvc.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import org.springframework.util.StopWatch; /** * Class Describe: * 计时类,配合Aop使用 * * @author biuaxia * @date 2018/12/13 20:02 */ @Component @Aspect public class WatchBean { @Around("within(vip.javer.springbootmvc.controller.*)") public Object exe(ProceedingJoinPoint point) throws Throwable { StopWatch watch = new StopWatch(); watch.start(); Object o = point.proceed(); watch.stop(); System.out.println("类" + point.getTarget().getClass().getName() + "\t方法" + point.getSignature().getName() + "\t执行时间TimeSeconds:" + watch.getTotalTimeSeconds() + "\tTimeMillis:" + watch.getTotalTimeMillis()); return o; } }
Spring Boot静态资源
优先级
最高:META-INF/resources
高:resources
中:static
低:public
例如我想要访问java目录下的资源
可以这么做:
如果想要自定义资源,继承WebMvcConfigurerAdapter,然后重写addResourceHandlers方法
package vip.javer.springbootmvc.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* Class Describe:
* 自定义资源文件夹
*
* @author biuaxia
* @date 2018/12/13 20:15
*/
@Configuration
public class CustomResourceFolderConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/java/**").addResourceLocations("classpath:/java/");
}
}
JavaWeb的应用
JavaWeb三大组件
- Servlet
- Filter
- Listener
Servlet
-
新建Servlet类,继承HttpServlet
-
添加注解@WebServlet
name->对应Servlet-name urlPatterns->url-pattern initParams{}->init-param loadOnStartup->load-on-startup
-
主启动类添加@ServletComponentScan(添加后自动扫描
@WebServlet
,@WebFilter
,@WebListener
)package vip.javer.springbootmvc.servlet; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Class Describe: * * @author biuaxia * @date 2018/12/13 20:26 */ @WebServlet(name = "helloServlet", urlPatterns = "/hello.do") public class HelloServlet extends HttpServlet { @Override public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { res.setContentType("text/html;charset=UTF-8"); PrintWriter out = res.getWriter(); out.print("你好世界!"); out.print("<br/>"); out.print("HelloWorld"); out.flush(); out.close(); } }
主启动类
package vip.javer.springbootmvc; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; /** * @author wlmpr */ @SpringBootApplication @ServletComponentScan public class SpringbootmvcApplication { public static void main(String[] args) { SpringApplication.run(SpringbootmvcApplication.class, args); } }
Filter
编写Filter组件类,实现Filter接口,在doFilter方法定义拦截逻辑
package vip.javer.springbootmvc.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Class Describe:
*
* @author biuaxia
* @date 2018/12/13 20:46
*/
@WebFilter(filterName = "helloFilter", urlPatterns = "/hello.do")
public class HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("拦截器初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String url = request.getRequestURL().toString();
String param = request.getQueryString();
System.out.println("拦截到了请求" + url + "\t参数为:" + param);
System.out.println("放行前");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("放行后");
}
@Override
public void destroy() {
System.out.println("拦截器销毁");
}
}
Listener
这里展示的仅仅在Tomcat启动与销毁时执行
package vip.javer.springbootmvc.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* Class Describe: 应用监听器
* 这里会在Tomcat初始化和销毁时执行
*
* @author biuaxia
* @date 2018/12/13 20:53
*/
@WebListener(value = "appListener")
public class ApplicationListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("应用初始化\t" + servletContextEvent.getServletContext().getServerInfo());
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("应用销毁\t" + servletContextEvent.getServletContext().getServletContextName());
}
}
配置启用阿里Druid连接池监控
- 新建Serlvet继承StatviewServlet
- 该类添加注解
@WebServlet(name = "druidServlet",urlPatterns = "/druid/*")
- 设置账号密码
@WebServlet(name = "druidServlet", urlPatterns = "/druid/*", initParams = {
@WebInitParam(name = "loginUsername", value = "root"),
@WebInitParam(name = "loginPassword", value = "1234")
})
public class DruidServlet {
}
-
配置数据库SQL统计
- 新建一个Filter继承WebStatFilter
- 配置排除不统计的URL
package vip.javer.springbootmvc.filter; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; /** * Class Describe: * * @author biuaxia * @date 2018/12/13 21:03 */ @WebFilter(filterName = "druidFilter", urlPatterns = "/*", initParams = { @WebInitParam(name = "exclusions", value = "*.js, *.css, *.jpg, *.png, *.gif, *.jpeg, /druid/*") }) public class DruidFilter { }
配置阿里连接池属性
package vip.java.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* Class Describe:
*
* @author biuaxia
* @date 2018/12/12 9:31
*/
@Configuration
public class DruidDataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druid() {
DruidDataSource dataSource = new DruidDataSource();
try {
dataSource.setFilters("stat");
} catch (SQLException e) {
e.printStackTrace();
}
/* dataSource.setUsername("");
dataSource.setPassword("");
dataSource.setDriverClassName("");
dataSource.setUrl("");*/
/*
* 这样也可以创建对应的Druid连接池
* 其次,在type里面无参则是默认的tomcat-jdbc连接
*/
//DataSource dataSource = DataSourceBuilder.create().type(DruidDataSource.class).build();
return dataSource;
}
}