Handling Request and Response
1. Using @RequestBody for JSON Deserialization
| Aspect |
Detail |
| Default converter |
MappingJackson2HttpMessageConverter |
| Records |
Supported natively (Java 17+) |
| Validation |
Combine with @Valid |
| Required |
@RequestBody(required=false) for optional |
2. Using @ResponseBody for JSON Serialization
Example: @ResponseBody on @Controller method
@Controller
public class ApiController {
@GetMapping("/api/me")
@ResponseBody
public UserDto me(Principal p) { return service.byEmail(p.getName()); }
}
Note: Implicit on every method when class is annotated with
@RestController.
3. Customizing Jackson ObjectMapper Configuration
| Property |
Effect |
spring.jackson.serialization.indent_output |
Pretty-print |
spring.jackson.serialization.write_dates_as_timestamps |
ISO vs epoch |
spring.jackson.deserialization.fail_on_unknown_properties |
Strict mode |
spring.jackson.property-naming-strategy |
SNAKE_CASE, KEBAB_CASE |
spring.jackson.default-property-inclusion |
NON_NULL, NON_EMPTY |
@Bean
Jackson2ObjectMapperBuilderCustomizer jackson() {
return b -> b.modules(new JavaTimeModule())
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
public record EventDto(
String name,
@JsonFormat(shape=Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ssXXX")
OffsetDateTime startsAt
) {}
| Attribute |
Use |
shape |
STRING, NUMBER, OBJECT |
pattern |
SimpleDateFormat / DateTimeFormatter pattern |
timezone |
e.g. UTC |
locale |
BCP-47 tag |
5. Ignoring Null Fields (@JsonInclude)
| Include Strategy |
Behavior |
ALWAYS |
Default |
NON_NULL |
Skip nulls |
NON_EMPTY |
Skip null + empty collections/strings |
NON_DEFAULT |
Skip default values |
6. Using Custom Serializers and Deserializers
Example: Custom serializer for value type
public class MoneySerializer extends JsonSerializer<Money> {
@Override public void serialize(Money m, JsonGenerator g, SerializerProvider sp) throws IOException {
g.writeString(m.amount() + " " + m.currency());
}
}
@JsonSerialize(using = MoneySerializer.class)
public record Money(BigDecimal amount, String currency) {}
7. Working with Multipart File Uploads (MultipartFile)
Example: Multipart file upload with path traversal guard
@PostMapping(value="/upload", consumes=MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<String> upload(@RequestPart("file") MultipartFile file,
@RequestPart("meta") MetaDto meta) throws IOException {
Path dest = Path.of("/data", UUID.randomUUID() + "-" + file.getOriginalFilename());
file.transferTo(dest);
return ResponseEntity.ok(dest.toString());
}
| Method |
Returns |
getOriginalFilename() |
Client-provided name |
getContentType() |
MIME type |
getSize() |
Bytes |
getInputStream() |
Streaming read |
transferTo(File/Path) |
Save to disk |
8. Configuring Max File Size
Example: Multipart upload size limits
spring:
servlet:
multipart:
max-file-size: 25MB
max-request-size: 100MB
file-size-threshold: 2KB
location: /tmp/uploads
| Property |
Default |
max-file-size |
1MB |
max-request-size |
10MB |
enabled |
true |
@PostMapping(value="/login", consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String login(@ModelAttribute @Valid LoginForm form, BindingResult br) {
if (br.hasErrors()) return "login";
// …
return "redirect:/home";
}
public record LoginForm(@NotBlank String username, @NotBlank String password) {}
10. Using HttpServletRequest and HttpServletResponse
| API |
Use |
request.getRemoteAddr() |
Client IP (behind proxy: use X-Forwarded-For) |
request.getHeader("…") |
Read header |
response.setStatus(int) |
Direct status set |
response.addCookie(...) |
Set cookie |
Warning: Prefer abstractions (@RequestHeader,
ResponseEntity) over raw servlet API.
11. Using HttpEntity for Request/Response Handling
Example: Echo request body with custom header
@PostMapping("/echo")
public HttpEntity<Map<String,Object>> echo(HttpEntity<String> req) {
HttpHeaders headers = new HttpHeaders();
headers.add("X-Length", String.valueOf(req.getBody().length()));
return new HttpEntity<>(Map.of("body", req.getBody()), headers);
}
| Type |
Description |
HttpEntity<T> |
Body + headers (no status) |
RequestEntity<T> |
Adds method + URL |
ResponseEntity<T> |
HttpEntity + status |