406 HttpMediaTypeNotAcceptableException:找不到“文本/日历”类型输出的可接受表示形式

时间:2018-11-07 13:52:10

标签: java spring spring-boot

我正在尝试通过Spring Boot提供ICS文件。我无法使用正确的Content-Type进行响应(我在Junit中)。我认为构建正确的响应,但Spring会覆盖它。

在我的@RestController中,我有

@GetMapping(value="/meeting/ics/{id}",produces = "text/calendar;charset=UTF-8")
public ResponseEntity<byte[]> getMeetingRoomCalendar(@PathVariable("id") Long id) throws ParseException, URISyntaxException, IOException {
    //...

    byte[]out= calendar.toString().getBytes();

    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.setContentType(new MediaType("text", "calendar", Charset.forName("UTF-8")));
    responseHeaders.setContentLength(out.length);

    return new ResponseEntity<>(out,responseHeaders,HttpStatus.OK);
}

我以这种方式进行测试:

MvcResult mvcResult = restMembershipConfigMockMvc.perform(get("/api/meeting/ics/1")
        .accept(MediaType.ALL))
        .andExpect(status().isOk())
        .andReturn()
        ;

我尝试了一些在堆栈溢出中类似问题上找到的响应,但是我总是收到406状态,并抛出HttpMediaTypeNotAcceptableException: Could not find acceptable representation响应异常

在这里,我从路径后缀中删除了“ .ics”以排除它,从而导致异常。

1 个答案:

答案 0 :(得分:0)

好吧, 我找到了路。我的问题有太多错误点。 之所以不起作用,是因为Spring mvc没有提供支持“文本/日历”类型的HttpMessageConverter

所以我创建了一个(我使用ical4j库,所以我希望我的控制器响应这种对象):

public class ICSHttpMessageConverter<T> extends AbstractHttpMessageConverter<T>
{

    public ICSHttpMessageConverter() {
        super(new MediaType("text","calendar"));
    }

    @Override
    protected boolean supports(Class<?> aClass) {
        return true;
    }


    @Override
    protected T readInternal(Class<? extends T> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
        CalendarBuilder calendarBuilder = new CalendarBuilder();
        Calendar calendar = null;
        try {
             calendar = calendarBuilder.build(httpInputMessage.getBody());

        } catch (ParserException e) {
            e.printStackTrace();
        }
        return (T)calendar;
    }

    @Override
    protected void writeInternal(T t, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
        httpOutputMessage.getBody().write(t.toString().getBytes());
    }
}

我可能应该改进支持方法,但是到那时一切都正常了,我很乐意参加其他任务。

现在我们只在Spring配置中注册了转换器:

@Configuration
public class MediaTypeConfiguration extends WebMvcConfigurationSupport {

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters){
        converters.add(new ICSHttpMessageConverter());
        super.addDefaultHttpMessageConverters(converters);
    }
}

之后,我的控制器如下所示:

@GetMapping(value="/meeting/ics/{id}.ics")
public ResponseEntity<Calendar> getMeetingRoomCalendar(@PathVariable("id") Long id) throws ParseException, URISyntaxException, IOException {
    //...
    calendar = ICSMeetingRoomAgendaHandler.loadBookings(calendar,bookingDTOS,meetingRoomDTO);

    return ResponseEntity.ok().body(calendar);
}

那时,我唯一的问题是,在我的junit集成测试中,我的转换器似乎没有被注册。这是因为在模拟init时没有给我的MockMvc转换器。我只需要使用方法setMessageConverters

添加它