关于SpringBoot 接受Date类型以及返回时间格式的记录

本文介绍了SpringBoot中处理日期时间的方法,包括使用@DateTimeFormat注解接收时间,通过@JsonFormat注解返回时间,以及自定义时间格式化类和WebMvcConfigurer配置。还提到解决日期时间相差8小时的问题,可以通过设置timezone和数据库连接配置来修正。

最近开始接触SpringBoot,不得不说他很强大。
下面说说SpringBoot接受时间的问题,网上的方法很多,我就说说我自己的。

  • 接受时间:
    @NotNull(message = "过期日不能为空")
    @DateTimeFormat(pattern="yyyy-MM-dd hh:mm:ss")
    private Date expired;

用@DateTimeFormat 注解去接受,就是不会去报错。

  • 返回时间格式方式一:

    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    用接送@JsonFormat 注解去返回,我用的时jackson的json转换包,SpringBoot 他自身就集成了这些,所以不用去引入。

  • 返回时间格式方式二(这种方式不用注解):

    首先去自定义一个类去继承 StdDateFormat 这个类,然后去重写他的method.

import com.fasterxml.jackson.databind.util.StdDateFormat;
import org.apache.commons.lang3.StringUtils;

import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName CustomDateFormat
 * @Description TODO
 * @Date 2018/8/16 9:32
 * @Author itastro
 * @Version 1.0
 **/
public class CustomDateFormat extends StdDateFormat {




    private static final long serialVersionUID = -3201781773655300201L;

    public static final CustomDateFormat instance = new CustomDateFormat();

    @Override
    /**
     * @ClassName: CustomDateFormat
     * 这个方法可不写,jckson主要使用的是parse(String)这个方法用来转换日期格式的,
     * 只要覆盖parse(String)这个方法即可
     * @date 2018年01月23日 下午4:28:57
     */
    public Date parse(String dateStr, ParsePosition pos) {
        SimpleDateFormat sdf  = null;
        if(StringUtils.isBlank(dateStr)){
            return null;
        }
        if (dateStr.length() == 10) {
            sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.parse(dateStr, pos);
        }
        if (dateStr.length() == 16) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            return sdf.parse(dateStr, pos);
        }
        if (dateStr.length() == 19) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.parse(dateStr, pos);
        }
        if (dateStr.length() == 23) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            return sdf.parse(dateStr, pos);
        }
        return super.parse(dateStr, pos);
    }

    @Override
    public Date parse(String dateStr) {
        ParsePosition pos = new ParsePosition(0);
        SimpleDateFormat sdf  = null;
        if(StringUtils.isBlank(dateStr)){
            return null;
        }
        if (dateStr.length() == 10) {
            sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.parse(dateStr, pos);
        }
        if (dateStr.length() == 16) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            return sdf.parse(dateStr, pos);
        }
        if (dateStr.length() == 19) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.parse(dateStr, pos);
        }
        if (dateStr.length() == 23) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            return sdf.parse(dateStr, pos);
        }
        return super.parse(dateStr, pos);
    }

    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date, toAppendTo, fieldPosition);
    }

    public CustomDateFormat clone() {
        return new CustomDateFormat();
    }
}

接下来在让SpringBoot启动类实现WebMvcConfigurer这个类,重写他的方法。

@MapperScan("com.bl.station.mapper")
@ComponentScan("com.bl.station.*")
@EnableAutoConfiguration
@ImportResource(locations = {"classpath:mykaptcha.xml"})
@ServletComponentScan
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)// 解决jmx重复注册bean的问题
@Import(FdfsClientConfig.class)
@EnableSwagger2
public class BlstationWebApplication  extends SpringBootServletInitializer implements WebMvcConfigurer {


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


    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(BlstationWebApplication.class);
    }
   @Bean
    public MappingJackson2HttpMessageConverter getMappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        //设置日期格式
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setDateFormat(CustomDateFormat.instance);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
        //设置中文编码格式
        List<MediaType> list = new ArrayList<MediaType>();
        list.add(MediaType.APPLICATION_JSON_UTF8);
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(list);
        return mappingJackson2HttpMessageConverter;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(getMappingJackson2HttpMessageConverter());
    }
}

这样的话他的日期返回格式就正确了。

  • 返回日期是时时间相差8小时的问题
    有时你会发现你的时间和实际时间相差8小时。
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")

加上 timezone = “GMT+8”,如果还是不行请进行修改数据库连接配置。

 url: jdbc:mysql://localhost:3306/station?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai

serverTimezone=Asia/Shanghai 设置成他。

还有这个配置我没试,有兴趣的可以试下:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/station?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
    username: root
    password: Zn252600@
    jackson:
          date-format: yyyy-MM-dd HH:mm:ss
          time-zone: GMT+8

到此结束,亲测可用,有其他好办法的伙伴可以告诉我下,小生这厢有礼了。

<think>我们正在讨论一个SpringBoot应用,特别是要实现暂停和返回按钮的后端逻辑。根据用户的问题,我们需要在SpringBoot框架中实现这两个功能。首先,我们需要明确这两个按钮的具体场景。暂停按钮通常用于暂停某个正在进行的任务或操作,而返回按钮则用于返回到上一个状态或页面。由于用户没有给出具体的应用场景,我们可以假设这是一个常见的任务处理场景,比如一个长时间运行的任务(如文件上传、数据处理等)的控制。在SpringBoot中,我们可以通过控制器(Controller)来接收前端的请求,然后调用服务层(Service)来实现具体的业务逻辑。1.暂停功能:暂停功能通常需要中断当前正在执行的任务。在Java中,我们可以使用多线程来实现任务的执行,然后通过某种机制(如中断标志)来暂停任务。2.返回功能:返回功能通常与前端路由有关,但用户要求后端逻辑。这里我们可能理解为取消当前操作并返回上一步,或者返回上一个状态。因此,我们需要在服务层记录任务的状态,并在接收到返回请求时进行状态回退。但是,由于用户没有提供具体的上下文,我们只能给出一般性的实现方案。下面我们分别设计这两个功能:一、暂停功能假设我们有一个长时间运行的任务,我们将其放在一个独立的线程中运行。我们可以通过一个标志位来控制任务的暂停。步骤:1.在服务层创建一个任务类,该任务类包含一个可暂停的机制(例如,使用一个volatile布尔变量作为暂停标志)。2.当用户点击暂停按钮时,前端发送一个请求到后端的某个暂停端点,该端点将设置这个暂停标志。3.任务在执行过程中会定期检查这个暂停标志,如果标志被设置,则暂停执行(例如,通过wait()方法或睡眠一段时间,直到标志被清除)。二、返回功能返回功能可能需要撤销已经执行的操作,或者返回到之前的某个状态。这通常需要状态管理。我们可以使用状态模式或者简单地记录状态历史。步骤:1.在服务层维护一个状态栈,每次状态变化时将当前状态压栈。2.当用户点击返回按钮时,前端发送请求到后端的返回端点,该端点从状态栈中弹出上一个状态,并将当前状态设置为上一个状态。然而,由于具体应用场景不明确,以上只是两种可能的实现思路。下面我们给出一个简化的代码示例:首先,我们定义一个任务类,它可以被暂停:```javapublicclassPausableTaskimplementsRunnable{privatevolatilebooleanisPaused=false;publicvoidpause(){isPaused=true;}publicvoidresume(){isPaused=false;synchronized(this){this.notify();//唤醒在暂停时等待的线程}}@Overridepublicvoidrun(){while(true){//检查暂停标志if(isPaused){synchronized(this){try{this.wait();//暂停线程}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}//执行任务的工作单元//...//假设任务可以分步骤执行,每一步后检查暂停}}}```然后,我们在服务层中管理这个任务:```java@ServicepublicclassTaskService{privatePausableTasktask;privateThreadtaskThread;publicvoidstartTask(){task=newPausableTask();taskThread=newThread(task);taskThread.start();}publicvoidpauseTask(){if(task!=null){task.pause();}}publicvoidresumeTask(){if(task!=null){task.resume();}}}```在控制器中,我们可以这样处理暂停请求:```java@RestController@RequestMapping("/api/task")publicclassTaskController{@AutowiredprivateTaskServicetaskService;@PostMapping("/start")publicResponseEntity<String>startTask(){taskService.startTask();returnResponseEntity.ok("Taskstarted");}@PostMapping("/pause")publicResponseEntity<String>pauseTask(){taskService.pauseTask();returnResponseEntity.ok("Taskpaused");}@PostMapping("/resume")publicResponseEntity<String>resumeTask(){taskService.resumeTask();returnResponseEntity.ok("Taskresumed");}}```注意:上面的代码只是一个示例,实际应用中需要更完善的线程管理和错误处理。对于返回功能,由于具体场景不明确,我们假设是一个状态回退。我们可以使用一个栈来保存状态:```java@ServicepublicclassStateService{privateDeque<State>stateStack=newArrayDeque<>();publicvoidsaveState(Statestate){stateStack.push(state);}publicStatepopState(){returnstateStack.pop();}}@RestController@RequestMapping("/api/state")publicclassStateController{@AutowiredprivateStateServicestateService;@PostMapping("/back")publicResponseEntity<String>back(){StatepreviousState=stateService.popState();//应用上一个状态//...returnResponseEntity.ok("Returnedtopreviousstate");}}```注意:状态的设计需要根据具体业务来定。以上是一个简单的实现思路。由于用户的具体应用场景不明确,这里只能提供一般性的方案。另外,暂停和返回按钮的前端逻辑需要与后端配合,前端在用户点击按钮时发送相应的HTTP请求。最后,我们生成相关问题:1.如何确保暂停的任务能够安全地恢复?2.在SpringBoot中如何管理任务的状态?3.如何实现一个可以暂停和恢复的异步任务?4.返回功能中如何处理多个用户同时操作的状态栈?5.在SpringBoot中如何实现撤销操作?希望这些回答能帮助用户。</think>### 在 Spring Boot 中实现暂停和返回按钮的后端逻辑 在 Spring Boot 应用中实现暂停和返回按钮的核心是**状态管理和事务控制**。以下是分步实现方案: #### 一、暂停功能实现 1. **状态机设计** 在实体类中添加状态字段,使用枚举管理状态: ```java @Entity public class Task { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 状态枚举:CREATED, RUNNING, PAUSED, COMPLETED @Enumerated(EnumType.STRING) private TaskStatus status; // 其他业务字段 } public enum TaskStatus { CREATED, RUNNING, PAUSED, COMPLETED } ``` 2. **服务层逻辑** 通过原子操作更新状态: ```java @Service public class TaskService { @Autowired private TaskRepository repository; @Transactional public void pauseTask(Long taskId) { Task task = repository.findById(taskId) .orElseThrow(() -> new EntityNotFoundException("Task not found")); // 状态校验:只有运行中的任务可暂停 if (task.getStatus() != TaskStatus.RUNNING) { throw new IllegalStateException("Only running tasks can be paused"); } task.setStatus(TaskStatus.PAUSED); repository.save(task); // 可选:触发暂停后的业务逻辑(如资源释放) } } ``` 3. **控制器层** 接收前端请求并调用服务: ```java @RestController @RequestMapping("/api/tasks") public class TaskController { @Autowired private TaskService taskService; @PostMapping("/{id}/pause") public ResponseEntity<Void> pauseTask(@PathVariable Long id) { taskService.pauseTask(id); return ResponseEntity.ok().build(); } } ``` #### 二、返回功能实现 1. **状态恢复机制** 在实体中添加`previousStatus`字段: ```java @Entity public class Task { // ... @Enumerated(EnumType.STRING) private TaskStatus previousStatus; // 用于存储返回前的状态 } ``` 2. **服务层逻辑** 实现状态回滚: ```java @Service public class TaskService { // ... @Transactional public void returnToPreviousState(Long taskId) { Task task = repository.findById(taskId) .orElseThrow(() -> new EntityNotFoundException("Task not found")); // 验证是否可返回 if (task.getPreviousStatus() == null) { throw new IllegalStateException("No previous state available"); } // 恢复状态并重置历史 TaskStatus current = task.getStatus(); task.setStatus(task.getPreviousStatus()); task.setPreviousStatus(current); // 可选的交换逻辑 repository.save(task); } } ``` 3. **控制器层** ```java @PostMapping("/{id}/return") public ResponseEntity<Void> returnToPrevious(@PathVariable Long id) { taskService.returnToPreviousState(id); return ResponseEntity.ok().build(); } ``` #### 三、关键注意事项 1. **并发控制** 使用乐观锁防止状态冲突: ```java @Entity public class Task { @Version private Long version; // 乐观锁字段 } ``` 2. **事务边界** 通过`@Transactional`确保状态变更的原子性,避免中间状态不一致。 3. **审计日志** 记录状态变更历史: ```java @EntityListeners(AuditingEntityListener.class) public class Task { @CreatedDate private LocalDateTime createdDate; @LastModifiedDate private LocalDateTime lastModifiedDate; } ``` 4. **前端交互** 前端按钮触发示例: ```javascript // 暂停按钮事件 axios.post(`/api/tasks/${taskId}/pause`) // 返回按钮事件 axios.post(`/api/tasks/${taskId}/return`) ``` ### 架构示意图 ```mermaid graph LR A[前端界面] -->|暂停/返回请求| B(Controller层) B -->|调用服务| C[Service层] C -->|状态操作| D[Repository层] D -->|数据持久化| E[(数据库)] E -->|状态反馈| A ``` ### 应用场景示例 - **招聘流程管理**:暂停职位审核流程,返回到编辑状态[^3] - **订单处理**:暂停订单履行,返回至支付确认状态 - **工作流引擎**:BPMN流程的中间状态控制
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值