2015-09-18 3 views
1

Я использую Spring для создания REST api. На данный момент я использую эту структуру, чтобы обеспечить обслуживание Проводник:Управление ответом REST с помощью Spring MVC

FileModel.java

package hello; 


    public class FileModel { 
     private String name; 
     private Long lastUpdate; 
     private Long size; 

     /** 
     * Void Constructor 
     */ 
     public FileModel() { 
     } 


     /** 
     * Parametrized constructor 
     * @param name 
     * @param created 
     * @param lastUpdate 
     * @param size 
     */ 
     public FileModel(String name, Long lastUpdate, Long size) { 
      super(); 
      this.name = name; 
      this.lastUpdate = lastUpdate; 
      this.size = size; 
     } 


     /** 
     * @return the name 
     */ 
     public String getName() { 
      return name; 
     } 


     /** 
     * @param name the name to set 
     */ 
     public void setName(String name) { 
      this.name = name; 
     } 


     /** 
     * @return the lastUpdate:A long value representing the time the file was last modified, 
     * measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970) 
     */ 
     public Long getLastUpdate() { 
      return lastUpdate; 
     } 


     /** 
     * @param lastUpdate the lastUpdate to set 
     */ 
     public void setLastUpdate(Long lastUpdate) { 
      this.lastUpdate = lastUpdate; 
     } 


     /** 
     * @return the size in bytes 
     */ 
     public Long getSize() { 
      return size; 
     } 


     /** 
     * @param size the size to set 
     */ 
     public void setSize(Long size) { 
      this.size = size; 
     } 


    } 

FileServices.java

package hello; 

    import java.io.File; 
    import java.io.FileNotFoundException; 
    import java.nio.file.Files; 
    import java.nio.file.LinkOption; 
    import java.util.ArrayList; 

    import org.springframework.stereotype.Service; 

    @Service 
    public class FileServices { 

     public ArrayList<FileModel> getAllFiles(String path) throws FileNotFoundException { 
      ArrayList<FileModel> files=new ArrayList<FileModel>(); 
      File directory = new File(path); 
      if (directory.exists()){ 
       //get all the files from a directory 
       File[] fList = directory.listFiles(); 
       //check if list is null 
       for (File file : fList){ 
        if (file.isFile()){ 
         FileModel f=new FileModel(file.getName(),file.lastModified(),file.length()); 
         files.add(f); 
        } 
       } 
       return files; 
      } 
      else throw new ResourceNotFoundException(path); 
     } 
    } 

ResourceNotFoundException.java

package hello; 

    import org.springframework.http.HttpStatus; 
    import org.springframework.web.bind.annotation.ResponseStatus; 

    @ResponseStatus(HttpStatus.NOT_FOUND) 
    public class ResourceNotFoundException extends RuntimeException { 
     private static final long serialVersionUID = 1L; 

     public ResourceNotFoundException(String path){ 
      super("The specified path: "+ path +" doesn't exist"); 
     } 
    } 

FileManager

package hello; 

    import java.io.FileNotFoundException; 
    import java.util.Collection; 

    import org.springframework.beans.factory.annotation.Autowired; 
    import org.springframework.web.bind.annotation.RequestMapping; 
    import org.springframework.web.bind.annotation.RequestMethod; 
    import org.springframework.web.bind.annotation.RequestParam; 
    import org.springframework.web.bind.annotation.RestController; 

    @RestController 
    public class FileManager { 

     @Autowired 
     private FileServices file; 

     @RequestMapping(value = "/files", method = RequestMethod.GET) 
     public Collection<FileModel> getAllFiles(@RequestParam(value="path", defaultValue="/home") String path) throws FileNotFoundException { 
      return file.getAllFiles(path); 
     } 

    } 

Ответ либо сообщение об ошибке, как этот

> { "timestamp": 1442560477794, "status": 404, "error": "Not 
> Found", "exception": "hello.ResourceNotFoundException", "message": 
> "The specified path: /home doesn't exist", "path": 
> "/MatlabLib/files" } 

или это.

[ 
    { 
    "name": "apache-tomcat-8.0.26-windows-x64.zip", 
    "lastUpdate": 1441282759343, 
    "size": 10470002 
    }, 
    { 
    "name": "desktop.ini", 
    "lastUpdate": 1441357976196, 
    "size": 282 
    } 
] 

Учитывая, что я должен управлять этой веб-службы с помощью других Java или код MatLab, мне нужен собственный ответ, например, со статусом, ошибки, исключения, сообщение, тело так что я могу проверить код состояния и undestand если есть ошибка или меньше. Есть ли весной метод строительства?

Благодаря

UPDATE: Я создал два класса ответа, один для ErrorResponse и один для реагирования с различным количеством Fied. Тогда я использовал

@ControllerAdvice 
public class ErrorController { 

    /** 
    * 
    * @param e: exception thrown 
    * @return ErroreResponse 
    */ 
    @ExceptionHandler(Exception.class) 
    public @ResponseBody ErrorResponse errorHandler(Exception e){ 
     //Make the exception by buildErrorResponse 
     return ErrorResponseBuilder.buildErrorResponse(e); 
    } 

в ErrorResponseBuilder сделал этот метод:

/** 
* Build exception response beginning from exception 
* @param e exception thrown 
* @return ErrorResponse: response of an exception 
*/ 
public static ErrorResponse buildErrorResponse(Exception e){ 
    StringWriter errors = new StringWriter(); 
    e.printStackTrace(new PrintWriter(errors)); 
    return new ErrorResponse(HttpStatusManager.getHttpCode(e),e.getClass().getName(),e.getMessage(),errors.toString()); 
} 

и в HttpStatusManager я реализовал это:

public HttpStatusManager() { 
    } 

    /** 
    * Add to this class all new exception associating a code error 
    * @param exception 
    * @return 
    */ 
    public static int getHttpCode(Exception exception){ 
     if (exception instanceof ResourceNotFoundException); 
      return HttpStatus.NOT_FOUND.value(); 
     } 

так из Controlle использовать эту простую линию

@RequestMapping(value = "/files", method = RequestMethod.GET) 
    public Response<Collection<FileModel>> getAllFiles(@RequestParam(value="path", defaultValue="/home") String path) throws ResourceNotFoundException { 
     Collection<FileModel> result; 
     result = file.getAllFiles(path); 
     return new Response<Collection<FileModel>>(HttpStatus.OK.value(),result); 
    } 

Как вы думаете?

+0

Это не весна, но я думаю, она может удовлетворить ваши потребности: javax.ws.rs.core.Response. – pzeszko

+0

Это уже есть, это называется HTTP. В первом случае ваш http-код будет 404 в последнем 200. В основном что-то в диапазоне 400 или 500 указывает на ошибку ... –

ответ

1

Вы можете использовать javax.ws.rs.core.Response который имеет хороший API. Но лично я предпочел бы создать настраиваемый класс для обработки таких ответов.

Конечно, вам необходимо прикрепить к вашему проекту f.e. Jackson JSON API, чтобы вы могли создавать методы, возвращающие объекты. Также вы должны настроить messageConverters в своем конфигурационном файле весны.


UPDATE

public class Response { 

private Object responseBody; 
private String message; 
private int responseCode; 
public Response() { 
    responseCode = 200; //default HTTP 200 OK 
} 
public Object getResponseBody() { 
    return responseBody; 
} 

public void setResponseBody(Object responseBody) { 
    this.responseBody = responseBody; 
} 

public String getMessage() { 
    return message; 
} 

public void setMessage(String message) { 
    this.message = message; 
} 

public int getResponseCode() { 
    return responseCode; 
} 

public void setResponseCode(int responseCode) { 
    this.responseCode = responseCode; 
} 


} 

Пример использования

@RequestMapping(value = "/files", method = RequestMethod.GET) 
    public Response getAllFiles(@RequestParam(value="path", defaultValue="/home") String path) { 
     Response response = new Response(); 
     try { 
      Collection<FileModel> files = file.getAllFiles(path); 
      response.setResponseBody(files); 
     } catch (FileNotFoundException e) { 
      Utils.setErrMessage(response, e); 
     } 

     return response; 
    } 

Ваш setErrMessage функция может выглядеть следующим образом

public void setErrMessage(Response response, Exception e) { 
    if(e instanceof NullPointerException) { 
     response.setErrCode(400); //HTTP 400 Bad Request 
    } 
    else if(e instanceof FileNotFoundException || ...) { 
     response.setErrCode(500); //HTTP 500 Interval Server Error 
    } 
    ... 
    response.setMessage(e.getMessage); 
} 

Это просто общая идея, вы можете изменить ее, как хотите.

+0

Я думал использовать новый класс, например ResponeBulder, который имеет следующие поля: статус, ошибка, исключение, сообщение, тело. Затем с одним конструктором используйте null в теле, если у меня есть ошибка, и в противном случае null в другом поле, если у меня есть код состояния. Хорошая идея? Как получить код состояния, ошибку и исключение из моих исключений? – luca

+0

Это очень хорошая идея (рекомендуется использовать шаблон Builder). Если я правильно понимаю вашу проблему, если вы вызываете какой-то метод, и при обработке исключения произойдет, почему бы не использовать только блок try-catch? Вы можете легко извлечь сообщение об ошибке, класс исключения и т. Д. Из объекта Exception в блоке catch, а затем установить его в свой объект ResponeBuilder. – pzeszko

+0

Что касается кодов ошибок, вы можете назначить их самостоятельно. Вы можете создать такой метод, как int getExceptionCode (Exception e) и на основе вида исключения вернуть правильный код. Есть, может, десяток разных кодов, которые вам нужно отличить. – pzeszko

0

Есть два способа для достижения этой цели:

  • Поймайте исключение и возвращает POJO, который описывает детали исключения следующим образом:

    @RequestMapping(value = "/files", method = RequestMethod.GET) 
        public Object getAllFiles(@RequestParam(value="path", defaultValue="/home") String path) throws FileNotFoundException { 
         try{ 
    
         }catch(ResourceNotFoundException rnfEx){ 
          return new ExceptionDTO("ERR-001","Resource not found"); 
         } 
        } 
    

    где ExceptionDTO представляет собой POJO, который превратит к JSON

  • Используйте @ExceptionHandler, чтобы работать с той же функциональностью. Пример: http://www.journaldev.com/2651/spring-mvc-exception-handling-exceptionhandler-controlleradvice-handlerexceptionresolver-json-response-example

1

У меня есть общий réponse DTO и я использую Spring @ControllerAdvice и @ExceptionHandler для достижения глобального механизма обработки ошибок в моих остальных услугах.

Global Code Handler Ошибка:

@ControllerAdvice  
public class WSControllerAdvice { 
     private static Logger logger = Logger.getLogger(SearchControllerAdvice.class); 
     @ExceptionHandler(Exception.class) 
     public @ResponseBody WSResponse<String> errorHandler(Exception e){ 
      WSResponse<String> response = new WSResponse<String>(); 
      logger.error("Exception occured "+e.getMessage()); 
      response.setResponseStatus(WSResponseCode.UNHANDLED_EXCEPTION); 
      response.setCount(0); 
      response.getErrors().add("Unhandled Search Error : " + e.getMessage()); 
      return response; 
     } 
    } 

Generic Response DTO

public class WSResponse<T> { 

    private String responseStatus; 
    private long count; 
    private long totalNumFound; 
    private T results ; 
    private List<String> errors = new ArrayList<>(); 
    private String nextPageMark; 
    private List<Facet> facets = new ArrayList<>(); 
} 

Getter сеттер удален

У вас есть последовательный формат ответа с этой структурой в месте , irrespect что происходит исключение или нет.

+0

как его использовать? Итак, на веб-сервер, без исключения, я должен установить значение null? – luca

+0

Если вы успешно выполнили запрос, ваш массив 'errors' будет пустым. – M4ver1k

Смежные вопросы