백엔드는 서비스를 제공하고 일반적으로 JSON 문자열을 반환하지만 일부 시나리오에서는 이미지 편집 인터페이스와 같은 이진 스트림을 직접 반환해야하며 이미지 스트림을 프론트 엔드로 직접 반환하기를 희망합니다. 현재 무엇을 할 수 있습니까?
주요 용도는 httpservletresponse 객체이며, 케이스는 다음과 같이 구현됩니다.
@requestmapping (value = { "/img/render"}, method = {requestmethod.get, requestmethod.post, requestmethod.options})@crossorigin (origins = "*")@responsepublic string execute (httpservletRequest httpservletrequest, httpservletrronge httperpronge /// 이미지 바이트의 이진 스트림 [] img = xxx; httpservletresponse.setContentType ( "image/png"); outputStream os = httpservletResponse.getOutputStream (); os.write (IMG); os.flush (); os.close (); "성공"반환;}주목해야 할 것
일반적으로 백엔드에서 제공하는 서비스 인터페이스는 종종 JSON 데이터를 반환합니다. 앞에서 언급했듯이 사진을 직접 반환하는 장면은 사진을 반환하는 일반적인 방법은 무엇입니까?
그렇다면 컨트롤러는 어떻게 위의 세 가지 사용 자세를 동시에 지원해야합니까?
반환하는 방법에는 여러 가지가 있기 때문에 선택할 수있는 방법은 물론 프론트 엔드로 지정되므로 매개 변수를 요청하는 Bean 객체를 정의 할 수 있습니다.
@datapublic class baserequest {private static final long serialversionuid = 1146303518394712013L; / ** * 출력 이미지 방법 : * * URL : HTTP 주소 (기본 메소드) * Base64 : Base64 인코딩 * 스트림 : 직접 반환 이미지 * */ private String outtype; /*** 반환 이미지 유형* jpg | png | 웹 | gif */ 개인 문자열 mediaType; public returntypeenum returntype () {return returntypeenum.getenum (outtype); } public mediaTypeenum mediaType () {return mediaTypeenum.getenum (mediaType); }}판단을 단순화하기 위해 두 개의 주석이 정의되었습니다. 하나는 ReturnTypeenum과 다른 하나는 MediaTypeenum을 정의했습니다. 물론 필요성은 특별히 크지 않습니다. 다음은 둘 다의 정의입니다.
public enum returnTypeenum {url ( "url"), stream ( "stream"), base64 ( "base"); 개인 문자열 유형; returntypeenum (문자열 유형) {this.type = 유형; } private static map <string, returnTypeenum>지도; 정적 {map = new Hashmap <> (3); for (returnTypeenum e : returnTypeenum.values ()) {map.put (e.type, e); }} public static returntypeenum getenum (문자열 유형) {if (type == null) {return url; } returnTypeenum e = map.get (type.tolowercase ()); 반환 e == null? URL : e; }} @datapublic enum mediaTypeenum {imagejpg ( "jpg", "image/jpeg", "ffd8ff"), imageGif ( "gif", "image/gif", "47494638"), imagePng ( "png", "image/png", "89504E47", imageWebp ( "webp", ",", "," "52494646"), 개인 최종 문자열 내선; 개인 최종 문자열 마임; 개인 최종 문자열 마법; MediaTypeenum (String ext, String Mime, String Magic) {this.ext = ext; this.mime = 마임; this.magic = 마법; } 개인 정적 맵 <문자열, MediaTypeenum>지도; 정적 {map = new Hashmap <> (4); for (mediaTypeenum e : values ()) {map.put (e.getext (), e); }} public static mediaTypeenum getEnum (String type) {if (type == null) {return imagejpg; } mediaTyPeenum e = map.get (type.tolowercase ()); 반환 e == null? ImageJPG : e; }}위는 요청 매개 변수로 캡슐화 된 Bean입니다. 물론 반환 할 콩도 있습니다.
@datapublic class baseresponse { / *** 이미지의 상대 경로를 반환* / 개인 문자열 경로; / *** 이미지의 HTTPS 형식을 반환*/ 개인 문자열 URL; / *** Base64 형식의 이미지*/ 개인 문자열 기반;}설명 :
실제 프로젝트 환경에서 요청 매개 변수 및 반환은 위와 같이 단순하지 않으므로 위의 Bean을 상속하거나 해당 형식을 직접 정의하여 구현할 수 있습니다.
목표는 명확하기 때문에 포장은 이것에서 가장 분명한 단계입니다.
보호 된 void buildResponse (BaseRequest 요청, BaseResponse 응답, 바이트 [] 바이트)는 selfError {switch (request.returnType ()) {case URL : 업로드 (바이트, 응답); 부서지다; 사례 Base64 : Base64 (바이트, 응답); 부서지다; 케이스 스트림 : 스트림 (바이트, 요청); }} private void upload (byte [] bytes, baseResponse 응답) selfError {try {// 이미지 서버로 업로드하고 String path = uploadUtil.upload (bytes)를 교체합니다. if (stringUtils.isblank (path)) {// 업로드 실패 새로운 내부 테러 (null); } response.setpath (경로); Response.setUrl (cdnutil.img (path)); } catch (ioexception e) {// cdn Exception log.error ( "cdn 오류에 업로드! e : {}", e); 새로운 cdnuploaderror를 던지십시오 (e.getMessage ()); }} // return base64private void base64 (byte [] bytes, baseResponse 응답) {String base = base64.getEncoder (). encodeToString (bytes); response.setbase (base);} // 이진 이미지를 반환합니다 프라이버시 void stream (byte [] bytes, baserequest request)는 selfError {try {mediaTypeenum mediaType = request.MediAtype (); httpservletResponse servletResponse = ((servletRequestAttributes) requestContexTholder.getRequestAttributes (). getResponse (); servletResponse.setContentType (mediaType.getMime ()); outputStream os = servletResponse.getOutputStream (); os.write (바이트); os.flush (); os.close (); } catch (예외 e) {log.error ( "일반 반환 스트림 img error! req : {}, e : {}", request, e); if (stringUtils.isnotblank (e.getMessage ())) {새 ninternerror (e.getMessage ()); } else {Throw New InternalError (null); }}}설명 :
위의 사용자 정의 예외 방법을 무시하십시오. 사용해야 할 때 이러한 사용자 지정 예외를 완전히 제거 할 수 있습니다. 여기서는이 사용자 정의 예외 방법이 실제 프로젝트에서 사용되는 이유에 대해 간략하게 이야기합니다. 주로 다음과 같은 장점 때문입니다.
Global Exception Capture (ControllerAdvie)와 함께 매우 편리하고 사용하기 간단합니다.
정보 통계 및 경보를 용이하게하기 위해 모든 예외는 중앙에서 처리됩니다.
예를 들어, 통일 된 장소에서 예외 수를 수행 한 다음 특정 임계 값을 초과 한 후 담당자에게 전화하여 예외 케이스가 발생하는 각 장소에 자리를 적극적으로 묻을 필요가 없습니다.
오류 상태 코드의 계층 별 전송을 피하십시오
- 주로 웹 서비스를위한 것입니다. 일반적으로 반환 된 JSON 문자열에 해당 오류 상태 코드 및 오류 메시지가 포함됩니다.
- 예외 케이스가 어디에나 나타날 수 있습니다. 이 예외 정보를 유지하기 위해 데이터는 계층에 의해 컨트롤러 계층으로 전달됩니다. 또는 ThreadLocal에서 발견됩니다. 분명히 이러한 방법 중 어느 것도 사용하기 편리하지 않습니다
물론 단점이 있습니다.
예외 방법, 추가 성능 오버 헤드이므로 사용자 정의 예외에서 다음 방법을 다루었으며 완전한 스택이 없습니다.
@OverRidePublic Synchronized Throwable FillinStackTrace () {return this;}어떤 사람들은이 습관을 코딩하는 방법을 좋아하지 않을 수도 있습니다.
당신이 연습하지 않는다고 말하는 것은 흥미롭지 않은 것 같습니다. 위의 디자인은 내가 유지하고있는 오픈 소스 프로젝트 Quick-Media에 완전히 반영됩니다. 물론 위의 차이점이 있습니다. 결국, 그것은 비즈니스와 더 관련이 있습니다. 관심이 있으시면 참조 할 수 있습니다.
QuickMedia : https://github.com/liuyueyi/quick-media :
Baseection : com.hust.hui.quickmedia.web.wxapi.wxbaseaction#Buildreturn
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.