zoukankan      html  css  js  c++  java
  • 《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());
        }
    
    }

     

     

     


     

     

     

     


     

     

    package com.apress.todo.client.domain;
    
    import lombok.Data;
    
    import java.time.LocalDateTime;
    import java.util.UUID;
    
    @Data
    public class ToDo {
    
        private String id;
        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;
        }
    }

    package com.apress.todo.client.error;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.client.ClientHttpResponse;
    import org.springframework.util.StreamUtils;
    import org.springframework.web.client.DefaultResponseErrorHandler;
    
    import java.io.IOException;
    import java.nio.charset.Charset;
    
    public class ToDoErrorHandler extends DefaultResponseErrorHandler {
    
        private Logger log = LoggerFactory.getLogger(ToDoErrorHandler.class);
    
        @Override
        public void handleError(ClientHttpResponse response) throws IOException {
            log.error(response.getStatusCode().toString());
            log.error(StreamUtils.copyToString(response.getBody(),Charset.defaultCharset()));
        }
    
    }

     

    package com.apress.todo.client;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    @Component
    @ConfigurationProperties(prefix="todo")
    @Data
    public class ToDoRestClientProperties {
    
        private String url;
        private String basePath;
    
    }

    package com.apress.todo.client;
    
    import com.apress.todo.client.domain.ToDo;
    import com.apress.todo.client.error.ToDoErrorHandler;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.core.ParameterizedTypeReference;
    import org.springframework.http.*;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.HashMap;
    import java.util.Map;
    
    @Service
    public class ToDoRestClient {
    
        private RestTemplate restTemplate;
        private ToDoRestClientProperties properties;
    
        public ToDoRestClient(ToDoRestClientProperties properties){
            this.restTemplate = new RestTemplate();
            this.restTemplate.setErrorHandler(new ToDoErrorHandler());
            this.properties = properties;
        }
    
        public Iterable<ToDo> findAll() throws URISyntaxException {
            RequestEntity<Iterable<ToDo>> requestEntity = new RequestEntity<Iterable<ToDo>>(HttpMethod.GET,new URI(properties.getUrl() + properties.getBasePath()));
            ResponseEntity<Iterable<ToDo>> response =
                    restTemplate.exchange(requestEntity,new ParameterizedTypeReference<Iterable<ToDo>>(){});
    
            if(response.getStatusCode() == HttpStatus.OK){
                return response.getBody();
            }
    
            return null;
        }
    
        public ToDo findById(String id){
            Map<String, String> params = new HashMap<String, String>();
            params.put("id", id);
            return restTemplate.getForObject(properties.getUrl() + properties.getBasePath() + "/{id}",ToDo.class,params);
        }
    
        public ToDo upsert(ToDo toDo) throws URISyntaxException {
           RequestEntity<?> requestEntity = new RequestEntity<>(toDo,HttpMethod.POST,new URI(properties.getUrl() + properties.getBasePath()));
           ResponseEntity<?> response = restTemplate.exchange(requestEntity, new ParameterizedTypeReference<ToDo>() {});
    
           if(response.getStatusCode() == HttpStatus.CREATED){
               return restTemplate.getForObject(response.getHeaders().getLocation(),ToDo.class);
           }
           return null;
        }
    
        public ToDo setCompleted(String id) throws URISyntaxException{
            Map<String, String> params = new HashMap<String, String>();
            params.put("id", id);
            restTemplate.postForObject(properties.getUrl() + properties.getBasePath() + "/{id}?_method=patch",null, ResponseEntity.class, params);
    
            return findById(id);
        }
    
        public void delete(String id){
            Map<String, String> params = new HashMap<String, String>();
            params.put("id", id);
            restTemplate.delete(properties.getUrl() + properties.getBasePath() + "/{id}",params);
        }
    
    }

     

     

    package com.apress.todo;
    
    import com.apress.todo.client.ToDoRestClient;
    import com.apress.todo.client.domain.ToDo;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.WebApplicationType;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootApplication
    public class TodoClientApplication {
    
        public static void main(String[] args) {
            SpringApplication app = new SpringApplication(TodoClientApplication.class);
            app.setWebApplicationType(WebApplicationType.NONE);
            app.run(args);
        }
    
        private Logger log = LoggerFactory.getLogger(TodoClientApplication.class);
    
        @Bean
        public CommandLineRunner process(ToDoRestClient client){
            return args -> {
    
                Iterable<ToDo> toDos = client.findAll();
                assert toDos != null;
                toDos.forEach( toDo -> log.info(toDo.toString()));
    
                ToDo newToDo = client.upsert(new ToDo("Drink plenty of Water daily!"));
                assert newToDo != null;
                log.info(newToDo.toString());
    
                ToDo toDo = client.findById(newToDo.getId());
                assert toDos != null;
                log.info(toDo.toString());
    
                ToDo completed = client.setCompleted(newToDo.getId());
                assert completed.isCompleted();
                log.info(completed.toString());
    
                client.delete(newToDo.getId());
                assert client.findById(newToDo.getId()) == null;
            };
        }
    }

  • 相关阅读:
    jQuery基础之让出$,与其他库共存
    什么是闭包
    绑定repeater时三目运算加特殊结果处理
    将同一张表出来的两部分内容再合成一张表
    后台往前台写弹窗代码不显示
    固定行列转换加分段统计
    js调用后台方法(如果你能容忍执行的后台方法变成一个常量)
    javascript遍历数组
    基于SpringMVC框架使用ECharts3.0实现折线图,柱状图,饼状图,的绘制(上篇)
    echarts
  • 原文地址:https://www.cnblogs.com/JasonPeng1/p/12267444.html
Copyright © 2011-2022 走看看