Java实操可能出现的错误3 ---springmvc

    科技2026-06-09  4

    文章目录

    1返回的状态吗不对?1.1自定义返回状态码的方式1.1.1 用ResponseEntity1.1.2@ResponseStatus定义在异常类1.1.3@ResponseStatus定义在方法上1.1.4@RestControllerAdvice 2时间序列化与反序列化2.1 @DateTimeFormat2.2@JsonFormat2.3@JsonDeserialize 局部2.4定义一个全局配置类 3日志到底放在拦截器,还是过滤器?3.1 过滤器3.2 拦截器3.3 上述代码中过滤器和拦截器的比较 4获取不到数据?

    1返回的状态吗不对?

    1.1自定义返回状态码的方式

    1.1.1 用ResponseEntity

    1.1.2@ResponseStatus定义在异常类

    1.1.3@ResponseStatus定义在方法上

    一般重定向时候用,比如重定向到response404

    1.1.4@RestControllerAdvice

    public class CustomException extends Exception { public CustomException(String message) { super(message); } } /** * <h1>全局统一异常处理</h1> * */ @RestControllerAdvice public class GlobalExceptionAdvice { @ExceptionHandler(value = CustomException.class) public ResponseEntity<GeneralResponse<String>> handleCustomException( HttpServletRequest request, CustomException ex ) { GeneralResponse<String> result = new GeneralResponse<>(0, ""); result.setData(ex.getMessage()); return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST); } } /** * <h2>第四种方式自定义返回状态码</h2> * */ @GetMapping("/fourth") public GeneralResponse<String> fourth() throws CustomException { throw new CustomException("some error"); }

    2时间序列化与反序列化

    例子:

    2.1 @DateTimeFormat

    测试: get方法可以接收到时间参数 post 方法报错 原因: 一般都是使用@DateTimeFormat把传给后台的时间字符串转成Date,使用@JsonFormat把后台传出的Date转成时间字符串,但是@DateTimeFormat只会在类似@RequestParam的请求参数(url拼接的参数才生效,如果是放到RequestBody中的form-data也是无效的)上生效,如果@DateTimeFormat放到@RequestBody下是无效的。

    在@RequestBody中则可以使用@JsonFormat把传给后台的时间字符串转成Date,也就是说@JsonFormat其实既可以把传给后台的时间字符串转成Date也可以把后台传出的Date转成时间字符串。

    2.2@JsonFormat

    @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”) private Date time;

    缺点:只支持这一种格式;yyyy-MM-dd HH:mm:ss,兼容性不好 改进:写一个通用转化器,自定义一个反序列化器

    2.3@JsonDeserialize 局部

    package com.imooc.spring.escape.date_se_de; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import java.io.IOException; import java.text.ParseException; import java.util.Date; @Slf4j public class DateJacksonConverter extends JsonDeserializer<Date> { private static final String[] pattern = new String[] { "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd" }; @Override public Date deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { Date targetDate = null; String originDate = jsonParser.getText(); if (StringUtils.isNotEmpty(originDate)) { try { long longDate = Long.parseLong(originDate.trim()); targetDate = new Date(longDate); } catch (NumberFormatException pe) { try { targetDate = DateUtils.parseDate( originDate, DateJacksonConverter.pattern ); } catch (ParseException ex) { log.error("parse error: {}", ex.getMessage()); throw new IOException("parse error"); } } } return targetDate; } }

    使用: 缺点:是一个局部处理,侵入性强,代码维护性差

    2.4定义一个全局配置类

    package com.imooc.spring.escape.date_se_de; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import java.io.IOException; import java.text.ParseException; import java.util.Date; @Slf4j public class DateJacksonConverter extends JsonDeserializer<Date> { private static final String[] pattern = new String[] { "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd" }; @Override public Date deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { Date targetDate = null; String originDate = jsonParser.getText(); if (StringUtils.isNotEmpty(originDate)) { try { long longDate = Long.parseLong(originDate.trim()); targetDate = new Date(longDate); } catch (NumberFormatException pe) { try { targetDate = DateUtils.parseDate( originDate, DateJacksonConverter.pattern ); } catch (ParseException ex) { log.error("parse error: {}", ex.getMessage()); throw new IOException("parse error"); } } } return targetDate; } @Override //指定哪个类型需要序列化 public Class<?> handledType() { return Date.class; } } @Configuration public class DateConverterConfig { @Bean public DateJacksonConverter dateJacksonConverter() { return new DateJacksonConverter(); } @Bean public Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean( @Autowired DateJacksonConverter dateJacksonConverter ) { Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean(); jackson2ObjectMapperFactoryBean.setDeserializers(dateJacksonConverter); return jackson2ObjectMapperFactoryBean; } }

    使用:

    3日志到底放在拦截器,还是过滤器?

    3.1 过滤器

    package com.imooc.spring.escape.filter_and_interceptor; import lombok.extern.slf4j.Slf4j; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @Slf4j @WebFilter(urlPatterns = "/*", filterName = "LogFilter") public class LogFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long start = System.currentTimeMillis(); chain.doFilter(request, response); log.info("LogFilter Print Log: {} -> {}", ((HttpServletRequest) request).getRequestURI(), System.currentTimeMillis() - start); } @Override public void destroy() { } }

    3.2 拦截器

    package com.imooc.spring.escape.filter_and_interceptor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Slf4j @Component public class LogInterceptor implements HandlerInterceptor { long start = System.currentTimeMillis(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { start = System.currentTimeMillis(); HandlerMethod handlerMethod = (HandlerMethod) handler; log.info("LogInterceptor: {}", ((HandlerMethod) handler).getBean() .getClass().getName()); log.info("LogInterceptor: {}", handlerMethod.getMethod().getName()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("LogInterceptor Print Log: {} -> {}", request.getRequestURI(), System.currentTimeMillis() - start); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }

    拦截器中定义啦一个全局变量 long start = System.currentTimeMillis(); 是线程不安全的 改进:

    package com.imooc.spring.escape.filter_and_interceptor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Slf4j @Component public class UpdateLogInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { request.setAttribute("startTime", System.currentTimeMillis()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("UpdateLogInterceptor Print Log: {} -> {}", request.getRequestURI(), System.currentTimeMillis() - (long) request.getAttribute("startTime")); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } package com.imooc.spring.escape.filter_and_interceptor; import com.imooc.spring.escape.http_request_response.User; import com.imooc.spring.escape.http_request_response.UserIdInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Component @Configuration public class WebInterceptorAdapter implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**").order(0); registry.addInterceptor(new UpdateLogInterceptor()) .addPathPatterns("/**").order(1); registry.addInterceptor(new UserIdInterceptor()).addPathPatterns("/**") .order(3); } }

    3.3 上述代码中过滤器和拦截器的比较

    4获取不到数据?

    Processed: 0.011, SQL: 9