类org.springframework.http.MockHttpInputMessage源码实例Demo

下面列出了怎么用org.springframework.http.MockHttpInputMessage的API类实例代码及写法,或者点击链接到github查看源代码。

@Test
public void readTyped() throws IOException {
	String body = "{" +
			"\"bytes\":\"AQI=\"," +
			"\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42," +
			"\"string\":\"Foo\"," +
			"\"bool\":true," +
			"\"fraction\":42.0}";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
	MyBean result = (MyBean) converter.read(MyBean.class, inputMessage);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());
}
 
@Test
@SuppressWarnings("unchecked")
public void readUntyped() throws IOException {
	String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
	HashMap<String, Object> result = (HashMap<String, Object>) this.converter.read(HashMap.class, inputMessage);
	assertEquals("Foo", result.get("string"));
	Number n = (Number) result.get("number");
	assertEquals(42, n.longValue());
	n = (Number) result.get("fraction");
	assertEquals(42D, n.doubleValue(), 0D);
	List<String> array = new ArrayList<>();
	array.add("Foo");
	array.add("Bar");
	assertEquals(array, result.get("array"));
	assertEquals(Boolean.TRUE, result.get("bool"));
	byte[] bytes = new byte[2];
	List<Number> resultBytes = (ArrayList<Number>)result.get("bytes");
	for (int i = 0; i < 2; i++) {
		bytes[i] = resultBytes.get(i).byteValue();
	}
	assertArrayEquals(new byte[] {0x1, 0x2}, bytes);
}
 
@Test
@SuppressWarnings("unchecked")
public void readUntyped() throws IOException {
	String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
	HashMap<String, Object> result = (HashMap<String, Object>) this.converter.read(HashMap.class, inputMessage);
	assertEquals("Foo", result.get("string"));
	Number n = (Number) result.get("number");
	assertEquals(42, n.longValue());
	n = (Number) result.get("fraction");
	assertEquals(42D, n.doubleValue(), 0D);
	List<String> array = new ArrayList<>();
	array.add("Foo");
	array.add("Bar");
	assertEquals(array, result.get("array"));
	assertEquals(Boolean.TRUE, result.get("bool"));
	byte[] bytes = new byte[2];
	List<Number> resultBytes = (ArrayList<Number>)result.get("bytes");
	for (int i = 0; i < 2; i++) {
		bytes[i] = resultBytes.get(i).byteValue();
	}
	assertArrayEquals(new byte[] {0x1, 0x2}, bytes);
}
 
@Test
@SuppressWarnings("unchecked")
public void readAndWriteGenerics() throws Exception {
	Field beansList = ListHolder.class.getField("listField");

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	Type genericType = beansList.getGenericType();
	List<MyBean> results = (List<MyBean>) converter.read(genericType, MyBeanListHolder.class, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, genericType, new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
@Test
@SuppressWarnings("unchecked")
public void writeParameterizedBaseType() throws Exception {
	ParameterizedTypeReference<List<MyBean>> beansList = new ParameterizedTypeReference<List<MyBean>>() {};
	ParameterizedTypeReference<List<MyBase>> baseList = new ParameterizedTypeReference<List<MyBase>>() {};

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	List<MyBean> results = (List<MyBean>) converter.read(beansList.getType(), null, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, baseList.getType(), new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
@Test
@SuppressWarnings("unchecked")
public void readUntyped() throws IOException {
	String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
	HashMap<String, Object> result = (HashMap<String, Object>) this.converter.read(HashMap.class, inputMessage);
	assertEquals("Foo", result.get("string"));
	Number n = (Number) result.get("number");
	assertEquals(42, n.longValue());
	n = (Number) result.get("fraction");
	assertEquals(42D, n.doubleValue(), 0D);
	List<String> array = new ArrayList<>();
	array.add("Foo");
	array.add("Bar");
	assertEquals(array, result.get("array"));
	assertEquals(Boolean.TRUE, result.get("bool"));
	byte[] bytes = new byte[2];
	List<Number> resultBytes = (ArrayList<Number>)result.get("bytes");
	for (int i = 0; i < 2; i++) {
		bytes[i] = resultBytes.get(i).byteValue();
	}
	assertArrayEquals(new byte[] {0x1, 0x2}, bytes);
}
 
@Test
@SuppressWarnings("unchecked")
public void readAndWriteGenerics() throws Exception {
	Field beansList = ListHolder.class.getField("listField");

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	Type genericType = beansList.getGenericType();
	List<MyBean> results = (List<MyBean>) converter.read(genericType, MyBeanListHolder.class, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, genericType, new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
@Test
@SuppressWarnings("unchecked")
public void readAndWriteParameterizedType() throws Exception {
	ParameterizedTypeReference<List<MyBean>> beansList = new ParameterizedTypeReference<List<MyBean>>() {};

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	List<MyBean> results = (List<MyBean>) converter.read(beansList.getType(), null, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, beansList.getType(), new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
@Test
@SuppressWarnings("unchecked")
public void writeParameterizedBaseType() throws Exception {
	ParameterizedTypeReference<List<MyBean>> beansList = new ParameterizedTypeReference<List<MyBean>>() {};
	ParameterizedTypeReference<List<MyBase>> baseList = new ParameterizedTypeReference<List<MyBase>>() {};

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	List<MyBean> results = (List<MyBean>) converter.read(beansList.getType(), null, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, baseList.getType(), new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
@Test
public void read() throws IOException {
	InputStream is = getClass().getResourceAsStream("atom.xml");
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(is);
	inputMessage.getHeaders().setContentType(new MediaType("application", "atom+xml", StandardCharsets.UTF_8));
	Feed result = converter.read(Feed.class, inputMessage);
	assertEquals("title", result.getTitle());
	assertEquals("subtitle", result.getSubtitle().getValue());
	List<?> entries = result.getEntries();
	assertEquals(2, entries.size());

	Entry entry1 = (Entry) entries.get(0);
	assertEquals("id1", entry1.getId());
	assertEquals("title1", entry1.getTitle());

	Entry entry2 = (Entry) entries.get(1);
	assertEquals("id2", entry2.getId());
	assertEquals("title2", entry2.getTitle());
}
 
@Test
public void testXmlBomb() throws Exception {
	// https://en.wikipedia.org/wiki/Billion_laughs
	// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
	String content = "<?xml version=\"1.0\"?>\n" +
			"<!DOCTYPE lolz [\n" +
			" <!ENTITY lol \"lol\">\n" +
			" <!ELEMENT lolz (#PCDATA)>\n" +
			" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
			" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
			" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
			" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
			" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
			" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
			" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
			" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
			" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
			"]>\n" +
			"<rootElement><external>&lol9;</external></rootElement>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
	assertThatExceptionOfType(HttpMessageNotReadableException.class).isThrownBy(() ->
			this.converter.read(RootElement.class, inputMessage))
		.withMessageContaining("DOCTYPE");
}
 
@Test
public void readWithTypeMismatchException() throws Exception {
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(new byte[0]);

	Marshaller marshaller = mock(Marshaller.class);
	Unmarshaller unmarshaller = mock(Unmarshaller.class);
	given(unmarshaller.unmarshal(isA(StreamSource.class))).willReturn(Integer.valueOf(3));

	MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller, unmarshaller);
	try {
		converter.read(String.class, inputMessage);
		fail("Should have thrown HttpMessageNotReadableException");
	}
	catch (HttpMessageNotReadableException ex) {
		assertTrue(ex.getCause() instanceof TypeMismatchException);
	}
}
 
@Test
public void readWithMarshallingFailureException() throws Exception {
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(new byte[0]);
	UnmarshallingFailureException ex = new UnmarshallingFailureException("forced");

	Unmarshaller unmarshaller = mock(Unmarshaller.class);
	given(unmarshaller.unmarshal(isA(StreamSource.class))).willThrow(ex);

	MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter();
	converter.setUnmarshaller(unmarshaller);

	try {
		converter.read(Object.class, inputMessage);
		fail("HttpMessageNotReadableException should be thrown");
	}
	catch (HttpMessageNotReadableException e) {
		assertTrue("Invalid exception hierarchy", e.getCause() == ex);
	}
}
 
@Test
public void readSAXSourceExternal() throws Exception {
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(bodyExternal.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
	converter.setSupportDtd(true);
	SAXSource result = (SAXSource) converter.read(SAXSource.class, inputMessage);
	InputSource inputSource = result.getInputSource();
	XMLReader reader = result.getXMLReader();
	reader.setContentHandler(new DefaultHandler() {
		@Override
		public void characters(char[] ch, int start, int length) {
			String s = new String(ch, start, length);
			assertNotEquals("Invalid result", "Foo Bar", s);
		}
	});
	reader.parse(inputSource);
}
 
@Test
@SuppressWarnings("unchecked")
public void readUntyped() throws IOException {
	String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
	HashMap<String, Object> result = (HashMap<String, Object>) this.converter.read(HashMap.class, inputMessage);
	assertEquals("Foo", result.get("string"));
	Number n = (Number) result.get("number");
	assertEquals(42, n.longValue());
	n = (Number) result.get("fraction");
	assertEquals(42D, n.doubleValue(), 0D);
	List<String> array = new ArrayList<>();
	array.add("Foo");
	array.add("Bar");
	assertEquals(array, result.get("array"));
	assertEquals(Boolean.TRUE, result.get("bool"));
	byte[] bytes = new byte[2];
	List<Number> resultBytes = (ArrayList<Number>)result.get("bytes");
	for (int i = 0; i < 2; i++) {
		bytes[i] = resultBytes.get(i).byteValue();
	}
	assertArrayEquals(new byte[] {0x1, 0x2}, bytes);
}
 
@Test
public void readWithMarshallingFailureException() throws Exception {
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(new byte[0]);
	UnmarshallingFailureException ex = new UnmarshallingFailureException("forced");

	Unmarshaller unmarshaller = mock(Unmarshaller.class);
	given(unmarshaller.unmarshal(isA(StreamSource.class))).willThrow(ex);

	MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter();
	converter.setUnmarshaller(unmarshaller);

	try {
		converter.read(Object.class, inputMessage);
		fail("HttpMessageNotReadableException should be thrown");
	}
	catch (HttpMessageNotReadableException e) {
		assertTrue("Invalid exception hierarchy", e.getCause() == ex);
	}
}
 
@Test
public void read() throws IOException {
	String body = "<MyBean>" +
			"<string>Foo</string>" +
			"<number>42</number>" +
			"<fraction>42.0</fraction>" +
			"<array><array>Foo</array>" +
			"<array>Bar</array></array>" +
			"<bool>true</bool>" +
			"<bytes>AQI=</bytes></MyBean>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
	MyBean result = (MyBean) converter.read(MyBean.class, inputMessage);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[]{"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes());
}
 
@Test
@SuppressWarnings("unchecked")
public void writeParameterizedBaseType() throws Exception {
	ParameterizedTypeReference<List<MyBean>> beansList = new ParameterizedTypeReference<List<MyBean>>() {};
	ParameterizedTypeReference<List<MyBase>> baseList = new ParameterizedTypeReference<List<MyBase>>() {};

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	List<MyBean> results = (List<MyBean>) converter.read(beansList.getType(), null, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, baseList.getType(), new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
@Test
public void read() throws IOException {
	String body = "<MyBean>" +
			"<string>Foo</string>" +
			"<number>42</number>" +
			"<fraction>42.0</fraction>" +
			"<array><array>Foo</array>" +
			"<array>Bar</array></array>" +
			"<bool>true</bool>" +
			"<bytes>AQI=</bytes></MyBean>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
	MyBean result = (MyBean) converter.read(MyBean.class, inputMessage);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[]{"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[]{0x1, 0x2}, result.getBytes());
}
 
@Test
@SuppressWarnings("unchecked")
public void readXmlRootElementExternalEntityEnabled() throws Exception {
	Resource external = new ClassPathResource("external.txt", getClass());
	String content =  "<!DOCTYPE root [" +
			"  <!ELEMENT external ANY >\n" +
			"  <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]>" +
			"  <list><rootElement><type s=\"1\"/><external>&ext;</external></rootElement></list>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));

	Jaxb2CollectionHttpMessageConverter<?> c = new Jaxb2CollectionHttpMessageConverter<Collection<Object>>() {
		@Override
		protected XMLInputFactory createXmlInputFactory() {
			XMLInputFactory inputFactory = XMLInputFactory.newInstance();
			inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true);
			return inputFactory;
		}
	};

	Collection<RootElement> result = c.read(rootElementListType, null, inputMessage);
	assertEquals(1, result.size());
	assertEquals("Foo Bar", result.iterator().next().external);
}
 
@Test
public void testXmlBomb() throws Exception {
	// https://en.wikipedia.org/wiki/Billion_laughs
	// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
	String content = "<?xml version=\"1.0\"?>\n" +
			"<!DOCTYPE lolz [\n" +
			" <!ENTITY lol \"lol\">\n" +
			" <!ELEMENT lolz (#PCDATA)>\n" +
			" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
			" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
			" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
			" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
			" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
			" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
			" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
			" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
			" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
			"]>\n" +
			"<list><rootElement><external>&lol9;</external></rootElement></list>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
	assertThatExceptionOfType(HttpMessageNotReadableException.class).isThrownBy(() ->
			this.converter.read(this.rootElementListType, null, inputMessage))
		.withMessageContaining("\"lol9\"");
}
 
@Test
@SuppressWarnings("unchecked")
public void readAndWriteGenerics() throws Exception {
	Field beansList = ListHolder.class.getField("listField");

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	Type genericType = beansList.getGenericType();
	List<MyBean> results = (List<MyBean>) converter.read(genericType, MyBeanListHolder.class, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, genericType, new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
@Test
public void readDomSourceWithXmlBomb() throws Exception {
	// https://en.wikipedia.org/wiki/Billion_laughs
	// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
	String content = "<?xml version=\"1.0\"?>\n" +
			"<!DOCTYPE lolz [\n" +
			" <!ENTITY lol \"lol\">\n" +
			" <!ELEMENT lolz (#PCDATA)>\n" +
			" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
			" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
			" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
			" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
			" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
			" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
			" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
			" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
			" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
			"]>\n" +
			"<root>&lol9;</root>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));

	this.thrown.expect(HttpMessageNotReadableException.class);
	this.thrown.expectMessage("DOCTYPE");

	this.converter.read(DOMSource.class, inputMessage);
}
 
@Test
public void testXmlBomb() throws Exception {
	// https://en.wikipedia.org/wiki/Billion_laughs
	// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
	String content = "<?xml version=\"1.0\"?>\n" +
			"<!DOCTYPE lolz [\n" +
			" <!ENTITY lol \"lol\">\n" +
			" <!ELEMENT lolz (#PCDATA)>\n" +
			" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
			" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
			" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
			" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
			" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
			" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
			" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
			" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
			" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
			"]>\n" +
			"<list><rootElement><external>&lol9;</external></rootElement></list>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
	this.thrown.expect(HttpMessageNotReadableException.class);
	this.thrown.expectMessage("\"lol9\"");
	this.converter.read(this.rootElementListType, null, inputMessage);
}
 
@Test
public void readWithTypeMismatchException() throws Exception {
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(new byte[0]);

	Marshaller marshaller = mock(Marshaller.class);
	Unmarshaller unmarshaller = mock(Unmarshaller.class);
	given(unmarshaller.unmarshal(isA(StreamSource.class))).willReturn(Integer.valueOf(3));

	MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(marshaller, unmarshaller);
	try {
		converter.read(String.class, inputMessage);
		fail("Should have thrown HttpMessageNotReadableException");
	}
	catch (HttpMessageNotReadableException ex) {
		assertTrue(ex.getCause() instanceof TypeMismatchException);
	}
}
 
@Test
public void readForm() throws Exception {
	String body = "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.ISO_8859_1));
	inputMessage.getHeaders().setContentType(
			new MediaType("application", "x-www-form-urlencoded", StandardCharsets.ISO_8859_1));
	MultiValueMap<String, String> result = this.converter.read(null, inputMessage);

	assertEquals("Invalid result", 3, result.size());
	assertEquals("Invalid result", "value 1", result.getFirst("name 1"));
	List<String> values = result.get("name 2");
	assertEquals("Invalid result", 2, values.size());
	assertEquals("Invalid result", "value 2+1", values.get(0));
	assertEquals("Invalid result", "value 2+2", values.get(1));
	assertNull("Invalid result", result.getFirst("name 3"));
}
 
@Test
@SuppressWarnings("unchecked")
public void readXmlRootElementExternalEntityEnabled() throws Exception {
	Resource external = new ClassPathResource("external.txt", getClass());
	String content =  "<!DOCTYPE root [" +
			"  <!ELEMENT external ANY >\n" +
			"  <!ENTITY ext SYSTEM \"" + external.getURI() + "\" >]>" +
			"  <list><rootElement><type s=\"1\"/><external>&ext;</external></rootElement></list>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));

	Jaxb2CollectionHttpMessageConverter<?> c = new Jaxb2CollectionHttpMessageConverter<Collection<Object>>() {
		@Override
		protected XMLInputFactory createXmlInputFactory() {
			XMLInputFactory inputFactory = XMLInputFactory.newInstance();
			inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true);
			return inputFactory;
		}
	};

	Collection<RootElement> result = c.read(rootElementListType, null, inputMessage);
	assertEquals(1, result.size());
	assertEquals("Foo Bar", result.iterator().next().external);
}
 
@Test
public void testXmlBomb() throws Exception {
	// https://en.wikipedia.org/wiki/Billion_laughs
	// https://msdn.microsoft.com/en-us/magazine/ee335713.aspx
	String content = "<?xml version=\"1.0\"?>\n" +
			"<!DOCTYPE lolz [\n" +
			" <!ENTITY lol \"lol\">\n" +
			" <!ELEMENT lolz (#PCDATA)>\n" +
			" <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n" +
			" <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n" +
			" <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n" +
			" <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n" +
			" <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n" +
			" <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n" +
			" <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n" +
			" <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">\n" +
			" <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">\n" +
			"]>\n" +
			"<rootElement><external>&lol9;</external></rootElement>";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8"));
	this.thrown.expect(HttpMessageNotReadableException.class);
	this.thrown.expectMessage("DOCTYPE");
	this.converter.read(RootElement.class, inputMessage);
}
 
@Test
public void readSAXSourceExternal() throws Exception {
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(bodyExternal.getBytes("UTF-8"));
	inputMessage.getHeaders().setContentType(new MediaType("application", "xml"));
	converter.setSupportDtd(true);
	SAXSource result = (SAXSource) converter.read(SAXSource.class, inputMessage);
	InputSource inputSource = result.getInputSource();
	XMLReader reader = result.getXMLReader();
	reader.setContentHandler(new DefaultHandler() {
		@Override
		public void characters(char[] ch, int start, int length) {
			String s = new String(ch, start, length);
			assertNotEquals("Invalid result", "Foo Bar", s);
		}
	});
	reader.parse(inputSource);
}
 
@Test
@SuppressWarnings("unchecked")
public void writeParameterizedBaseType() throws Exception {
	ParameterizedTypeReference<List<MyBean>> beansList = new ParameterizedTypeReference<List<MyBean>>() {};
	ParameterizedTypeReference<List<MyBase>> baseList = new ParameterizedTypeReference<List<MyBase>>() {};

	String body = "[{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," +
			"\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}]";
	MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8));
	inputMessage.getHeaders().setContentType(new MediaType("application", "json"));

	List<MyBean> results = (List<MyBean>) converter.read(beansList.getType(), null, inputMessage);
	assertEquals(1, results.size());
	MyBean result = results.get(0);
	assertEquals("Foo", result.getString());
	assertEquals(42, result.getNumber());
	assertEquals(42F, result.getFraction(), 0F);
	assertArrayEquals(new String[] {"Foo", "Bar"}, result.getArray());
	assertTrue(result.isBool());
	assertArrayEquals(new byte[] {0x1, 0x2}, result.getBytes());

	MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
	converter.write(results, baseList.getType(), new MediaType("application", "json"), outputMessage);
	JSONAssert.assertEquals(body, outputMessage.getBodyAsString(StandardCharsets.UTF_8), true);
}
 
 类所在包
 同包方法