《Pro Spring Boot 2》第四章:Web Applications with Spring Boot

The Spring MVC is designed around the org.springframework.web.servlet. DispatcherServlet class. This servlet is very flexible and has a very robust functionality that you won’t find in any other MVC web framework out there. With the DispatcherServlet, you have several out-of-the-box resolutions strategies, including view resolvers, locale resolvers, theme resolvers, and exception handlers. In other words, the DispatcherServlet take a HTTP request and redirect it to the right handler (the class marked with the @Controller or @RestController and the methods that use the @RequestMapping annotations) and the right view (your JSPs).

package com.apress.todo.domain;

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.UUID;

@Data
public class ToDo {

    @NotNull
    private String id;
    @NotNull
    @NotBlank
    private String description;
    private LocalDateTime created;
    private LocalDateTime modified;
    private boolean completed;

    public ToDo(){
        LocalDateTime date = LocalDateTime.now();
        this.id = UUID.randomUUID().toString();
        this.created = date;
        this.modified = date;
    }

    public ToDo(String description){
        this();
        this.description = description;
    }
}

shows you the ToDo class, which has all the required fields. It also uses the @Data annotation, which is a Lombok annotation that generates a default constructor (if you don’t have one) and all the setters, getters, and overrides, such as the toString method, to make the class cleaner. Also note that the class has the @NotNull and @NotBlank annotations in some of the fields; these annotations are used in the validation that we do later on. The default constructor has field initialization, so it is easy to create a ToDo instance

package com.apress.todo.repository;

import com.apress.todo.domain.ToDo;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Repository
public class ToDoRepository implements CommonRepository<ToDo> {

    private Map<String,ToDo> toDos = new HashMap<>();

    @Override
    public ToDo save(ToDo domain) {
        ToDo result = toDos.get(domain.getId());
        if(result != null) {
            result.setModified(LocalDateTime.now());
            result.setDescription(domain.getDescription());
            result.setCompleted(domain.isCompleted());
            domain = result;
        }
        toDos.put(domain.getId(), domain);
        return toDos.get(domain.getId());

    }

    @Override
    public Iterable<ToDo> save(Collection<ToDo> domains) {
        domains.forEach(this::save);
        return findAll();
    }

    @Override
    public void delete(ToDo domain) {
        toDos.remove(domain.getId());
    }

    @Override
    public ToDo findById(String id) {
        return toDos.get(id);
    }

    @Override
    public Iterable<ToDo> findAll() {
        return toDos.entrySet().stream().sorted(entryComparator).map(Map.Entry::getValue).collect(Collectors.toList());
    }

    private Comparator<Map.Entry<String,ToDo>> entryComparator = (Map.Entry<String, ToDo> o1, Map.Entry<String, ToDo> o2) -> {
        return o1.getValue().getCreated().compareTo(o2.getValue().getCreated());
    };
}

package com.apress.todo.validation;

import com.fasterxml.jackson.annotation.JsonInclude;

import java.util.ArrayList;
import java.util.List;

public class ToDoValidationError {

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private List<String> errors = new ArrayList<>();

    private final String errorMessage;

    public ToDoValidationError(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public void addValidationError(String error) {
        errors.add(error);
    }

    public List<String> getErrors() {
        return errors;
    }

    public String getErrorMessage() {
        return errorMessage;
    }
}

package com.apress.todo.validation;

import org.springframework.validation.Errors;
import org.springframework.validation.ObjectError;

public class ToDoValidationErrorBuilder {

    public static ToDoValidationError fromBindingErrors(Errors errors) {
        ToDoValidationError error = new ToDoValidationError("Validation failed. " + errors.getErrorCount() + " error(s)");
        for (ObjectError objectError : errors.getAllErrors()) {
            error.addValidationError(objectError.getDefaultMessage());
        }
        return error;
    }
}

package com.apress.todo.controller;

import com.apress.todo.domain.ToDo;
import com.apress.todo.domain.ToDoBuilder;
import com.apress.todo.repository.CommonRepository;
import com.apress.todo.validation.ToDoValidationError;
import com.apress.todo.validation.ToDoValidationErrorBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.validation.Valid;
import java.net.URI;

@RestController
@RequestMapping("/api")
public class ToDoController {

    private CommonRepository<ToDo> repository;

    @Autowired
    public ToDoController(CommonRepository<ToDo> repository) {
        this.repository = repository;
    }

    @GetMapping("/todo") //@RequestMapping(value="/todo", method = {RequestMethod.GET})
    public ResponseEntity<Iterable<ToDo>> getToDos(){
        return ResponseEntity.ok(repository.findAll());
    }

    @GetMapping("/todo/{id}")
    public ResponseEntity<ToDo> getToDoById(@PathVariable String id){
        return ResponseEntity.ok(repository.findById(id));
    }

    @PatchMapping("/todo/{id}")
    public ResponseEntity<ToDo> setCompleted(@PathVariable String id){
        ToDo result = repository.findById(id);
        result.setCompleted(true);
        repository.save(result);
        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .buildAndExpand(result.getId()).toUri();

        return ResponseEntity.ok().header("Location",location.toString()).build();
    }

    @RequestMapping(value="/todo", method = {RequestMethod.POST,RequestMethod.PUT})
    public ResponseEntity<?> createToDo(@Valid @RequestBody ToDo toDo, Errors errors){
        if (errors.hasErrors()) {
            return ResponseEntity.badRequest().body(ToDoValidationErrorBuilder.fromBindingErrors(errors));
        }

        ToDo result = repository.save(toDo);
        URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                .buildAndExpand(result.getId()).toUri();
        return ResponseEntity.created(location).build();
    }

    @DeleteMapping("/todo/{id}")
    public ResponseEntity<ToDo> deleteToDo(@PathVariable String id){
        repository.delete(ToDoBuilder.create().withId(id).build());
        return ResponseEntity.noContent().build();
    }

    @DeleteMapping("/todo")
    public ResponseEntity<ToDo> deleteToDo(@RequestBody ToDo toDo){
        repository.delete(toDo);
        return ResponseEntity.noContent().build();
    }

    @ExceptionHandler
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public ToDoValidationError handleException(Exception exception) {
        return new ToDoValidationError(exception.getMessage());
    }

}

原文地址:https://www.cnblogs.com/JasonPeng1/p/12267444.html

时间: 2024-10-08 17:17:52

《Pro Spring Boot 2》第四章:Web Applications with Spring Boot的相关文章

《metasploit渗透测试魔鬼训练营》学习笔记第四章—web应用渗透

继续来学习metasploit...记好笔记是很重要的,下面开始正文: 二.WEB应用渗透技术 1.WEB应用渗透基础知识 先介绍WEB应用攻击的主要类型(大致介绍,具体请自行查询) Sql注入攻击:大致分为 普通注入和盲注 跨站脚本(XSS): 分为存储型XSS,反射性XSS以及DOM型XSS 跨站伪造请求(CSRF):以XSS方式注入一段脚本,受害者点击该脚本时,脚本伪造受害者发出请求. 会话认证管理缺陷:验证身份的功能存在缺陷. 安全误配置:开发和管理人员的失误导致存在漏洞. 不安全密码存

【第2章 Spring快速入门】2.2 WEB应用之HelloWorld

上一节:[第2章 Spring快速入门]2.1 Java应用之HelloWorld 本章节主要介绍在WEB开发过程中,Spring是怎么使用的?上一节中我们已经讲到在普通的Java Project中如何使用Spring容器了,那么在WEB开发中集成Spring时,Spring又应该与Web容器是如何集成使用的呢?本章会着重介绍WEB与Spring的集成使用,同时提供一个简单的Web Demo,供大家快速入手学习.本章主要讲解内容:1. Web开发中如何集成Spring:2. Spring MVC

Spring 注解驱动(二)WEB 注解开发

Spring 注解驱动(二)WEB 注解开发 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.基本使用 在 Servlet 3.0 时支持注解启动,不再需要 web.xml 配制文件. 1.1 Servlet 3.0 注解 Servlet 3.0 常用注解: @WebServlet @WebFilter @WebInitParam @WebListener @WebServlet("/hello") pu

第三章 Maven构建 Java Spring Boot Web项目

3.1   认识Srping Boot Spring Boot是一个框架,是一种全新的编程规范,它的产生简化了对框架的使用,简化了Spring众多的框架中大量的繁琐的配置文件,所以说Spring Boot是一个服务于框架的框架,服务范围是简化文件的配置. Spring Boot的核心功能: 独立运行的spring项目:可以以jar包的形式独立运行,通过Java -jar xx.jar来运行. 内嵌的servlet容器:可以选择内嵌的Tomcat.Jetty或者Undertow. 提供starte

《Spring技术内幕》笔记-第四章 Spring MVC与web环境

?上下文在web容器中的启动 1,IoC容器的启动过程 IoC的启动过程就是建立上下文的过程,该上下文是与ServletContext相伴.在Spring中存在一个核心控制分发器,DispatcherServlet,这是Spring的核心.在web容器启动Spring应用程序时,首先建立根上下文,然后ContextLoader建立WebApplicationContext. Web容器中启动Spring过程如下: 在web.xml中,已经配置了ContextLoadListener,该类实现了S

《深入实践Spring Boot》第1章 Spring Boot入门

目录 第1章 Spring Boot入门 1.1 配置开发环境 1.1.1 安装JDK 1.1.2 安装InterlliJ IDEA 1.1.3 安装Apache Maven 1.1.4 安装Git客户端 1.2 创建项目工程 1.2.1 使用Maven新建项目 1.2.2 使用Spring Initializr新建项目 1.3 使用Spring Boot 1.3.1 Maven依赖管理 1.3.2 一个简单的实例 1.4 运行与发布 1.4.1 在IDEA环境中运行 1.4.2 将应用打包发布

《spring boot》8.2章学习时无法正常启动,报“ORA-00942: 表或视图不存在 ”

在学习<spring boot>一书的过程中,由于原书作者难免有一些遗漏的的地方,或者系统.软件版本不一致.框架更新等各种因素,完全安装书中源码页不能实现项目的正常启动 在8.2章节,演示JPA对oracle的支持时,配置文件中设置了如下代码,正常情况下应该支持数据库自动创建序列和表,但实际启动时却报错"ORA-00942: 表或视图不存在 " spring.datasource.driverClassName=oracle.jdbc.OracleDriver spring

web—第四章css&amp;第五章

web—第四章css&第五章 终于迎接等待已久的CSS,在没学这个之前,我们只会用一点img,查一点小图片,或者是用style改一下颜色,而且比较麻烦.现在多了个css在文件夹在创建一个css文件很多东西都可以在css里面而且修改的话非常方便,但是我还是有一些问题,就是老师叫我们做注册表的时候:年月日我真不相信是用下拉列表一个一个打上去的,我一开始想用时间轴但是太难啦,老师也没说. 随着时间过得很快国庆节也要来临了,这几天老师似乎有点急但是又怕教不好我们所以课程会有点紧张,但是我觉得还是很好跟上

spring boot 1.5.4 之web开发(三)

上一篇:springboot 1.5.4 入门和原理(二) spring Boot 之web开发 更多更详细的配置参考文件:application.properties和<SpringBoot之application配置详解>(新版本新增属性缺失)  或参考官网http://projects.spring.io/spring-boot/ 注意:Spring Boot工程默认沿用前文中的project,如有变动,各章节会明确说明 注释springboot工程中的application.prope