本文旨在讲解springboot和web层的整合,包含了web层的常用配置
github地址:https://github.com/CharlsShan/springboot-demo/tree/master/springboot-web
步骤一 、依赖 ,导入依赖如下,配置文件就配置个服务器端口就行
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>
步骤二、写主方法
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
步骤三,配置WebMvcConfigurerAdapter,用这种方式运用拦截器可以对不同url进行做不同的判断,url中有bussiness进BussinessInterceptor拦截器,有terminal的url进TerminalInterceptor例如对终端是一套处理逻辑,对服务端的http请求又是一套处理逻辑,创建的两个bean就是两个拦截器,视图控制器,可以进行网址的跳转,此时如果地址输入 http:// ip:port/ 则自动跳转到 http:// ip:port/bussiness/hello, CORS是为了防止跨域的问题而产生的的解决方案
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.springboot.interceptor.BussinessInterceptor;
import com.springboot.interceptor.TerminalInterceptor;
@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
/**
* 拦截器配置
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(bussinessInterceptor()).addPathPatterns("/bussiness/**");
registry.addInterceptor(terminalInterceptor()).addPathPatterns("/terminal/**");
}
@Bean
public BussinessInterceptor bussinessInterceptor() {
return new BussinessInterceptor();
}
@Bean
public TerminalInterceptor terminalInterceptor() {
return new TerminalInterceptor();
}
/**
* 视图控制器配置
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/").setViewName("/bussiness/hello");
}
/**
* 跨域CORS配置
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
super.addCorsMappings(registry);
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("POST","GET","OPTIONS")
.allowedOrigins("*");
}
}
BussinessInterceptor拦截器的代码,可以在preHandle中添加进行拦截的代码
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BussinessInterceptor extends HandlerInterceptorAdapter {
public BussinessInterceptor(){
System.out.println("init BussinessInterceptor");
}
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("BussinessInterceptor preHandle enter");
return true;
}
}
TerminalInterceptor 拦截器的代码,可以在preHandle中添加进行拦截的代码
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TerminalInterceptor extends HandlerInterceptorAdapter {
public TerminalInterceptor(){
System.out.println("init TerminalInterceptor");
}
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("TerminalInterceptor preHandle enter");
return true;
}
}
步骤四,写controller类
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping(value = "bussiness")
@RestController
public class BussinessController {
@GetMapping("hello")
public Result getHello() {
return ResultUtil.success("hello");
}
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping(value = "terminal")
@RestController
public class TerminalController {
@GetMapping("world")
public Result getHello() {
return ResultUtil.success("hello world");
}
}
步骤五、写返回的错误码public class Result<T> {
/** 错误码. */
private Integer code;
/** 提示信息. */
private String msg;
/** 具体的内容. */
private T data;
public Result() {
}
public Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Result(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
public void setCode(Integer code) {
this.code = code;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
import com.springboot.domain.Result;
public class ResultUtil {
public static final Integer SUCCESS_CODE = 200;
public static final Result SERVER_EXCEPTION = new Result(201, "服务器偷懒了");
private ResultUtil() {
}
public static Result success() {
return success("");
}
public static Result success(Object object) {
Result result = new Result();
result.setCode(SUCCESS_CODE);
result.setMsg("成功");
result.setData(object);
return result;
}
public static Result success(String msg, Object object) {
Result result = new Result();
result.setCode(SUCCESS_CODE);
result.setMsg(msg);
result.setData(object);
return result;
}
public static Result error(Integer code, String msg) {
Result result = new Result();
result.setCode(code);
result.setMsg(msg);
return result;
}
public static Result error(Integer code, String msg,Object data) {
Result result = new Result();
result.setCode(code);
result.setMsg(msg);
result.setData(data);
return result;
}
public static Result error( String msg) {
Result result = new Result();
result.setCode(10000);
result.setMsg(msg);
return result;
}
}
第六步、写统一的异常处理
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import com.google.gson.GsonBuilder;
import com.springboot.util.ResultUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
/**
* 全局异常处理器
*/
@Component
public class HandleExceptionResolver implements HandlerExceptionResolver {
private static final Logger logger = LoggerFactory.getLogger(HandleExceptionResolver.class);
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
logger.error("interceptor handle exception, {}", ex.getMessage(), ex);
this.toOutputStream(request, response, ResultUtil.SERVER_EXCEPTION.getCode().toString(), ResultUtil.SERVER_EXCEPTION.getMsg());
return null;
}
private void toOutputStream(HttpServletRequest request, HttpServletResponse response, String code, String errorMsg) {
try (OutputStream os = response.getOutputStream()) {
response.setHeader("Cache-Control", "no-cache");
response.setContentType("text/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
os.write(new GsonBuilder().create().toJson(ResultUtil.SERVER_EXCEPTION).getBytes(Charset.forName("utf-8")));
os.flush();
} catch (IOException e) {
logger.error("handler un-handler exception {} error, {}", e, e.getMessage(), e);
}
}
}
第七步、写全局的返回日志,即所有的controller返回都会打印出返回结果
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import com.springboot.domain.Result;
@ControllerAdvice(basePackages = "com.springboot")
public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> {
private static final Logger logger = LoggerFactory.getLogger(MyResponseBodyAdvice.class);
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object obj, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
if(obj instanceof Result){
logger.info("接口对应方法:{},返回结果:{}",methodParameter.getMethod().getName(),obj);
}
return obj;
}
}