Unit tests for record binding

See gh-27437
This commit is contained in:
Juergen Hoeller 2021-09-23 16:13:20 +02:00
parent 0241c5ebb3
commit f440fb8baf
3 changed files with 128 additions and 79 deletions

View File

@ -89,7 +89,7 @@ public abstract class AbstractRowMapperTests {
verifyPersonViaBeanWrapper(person);
}
private void verifyPersonViaBeanWrapper(Object person) {
protected void verifyPersonViaBeanWrapper(Object person) {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(person);
assertThat(bw.getPropertyValue("name")).isEqualTo("Bubba");
assertThat(bw.getPropertyValue("age")).isEqualTo(22L);

View File

@ -79,4 +79,28 @@ public class DataClassRowMapperTests extends AbstractRowMapperTests {
mock.verifyClosed();
}
@Test
public void testStaticQueryWithDataRecord() throws Exception {
Mock mock = new Mock();
List<RecordPerson> result = mock.getJdbcTemplate().query(
"select name, age, birth_date, balance from people",
new DataClassRowMapper<>(RecordPerson.class));
assertThat(result.size()).isEqualTo(1);
verifyPerson(result.get(0));
mock.verifyClosed();
}
protected void verifyPerson(RecordPerson person) {
assertThat(person.name()).isEqualTo("Bubba");
assertThat(person.age()).isEqualTo(22L);
assertThat(person.birth_date()).usingComparator(Date::compareTo).isEqualTo(new java.util.Date(1221222L));
assertThat(person.balance()).isEqualTo(new BigDecimal("1234.56"));
verifyPersonViaBeanWrapper(person);
}
static record RecordPerson(String name, long age, Date birth_date, BigDecimal balance) {
}
}

View File

@ -2202,6 +2202,19 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
assertThat(response.getContentAsString()).isEqualTo("2010-01-01");
}
@PathPatternsParameterizedTest
void dataRecordBinding(boolean usePathPatterns) throws Exception {
initDispatcherServlet(DataRecordController.class, usePathPatterns);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bind");
request.addParameter("param1", "value1");
request.addParameter("param2", "true");
request.addParameter("param3", "3");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertThat(response.getContentAsString()).isEqualTo("value1-true-3");
}
@Test
void routerFunction() throws ServletException, IOException {
GenericWebApplicationContext wac = new GenericWebApplicationContext();
@ -2397,7 +2410,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Controller
@RequestMapping("/myPage")
@SessionAttributes(names = { "object1", "object2" })
public static class MySessionAttributesController {
static class MySessionAttributesController {
@RequestMapping(method = RequestMethod.GET)
public String get(Model model) {
@ -2417,7 +2430,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@RequestMapping("/myPage")
@SessionAttributes({"object1", "object2"})
@Controller
public interface MySessionAttributesControllerIfc {
interface MySessionAttributesControllerIfc {
@RequestMapping(method = RequestMethod.GET)
String get(Model model);
@ -2426,7 +2439,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
String post(@ModelAttribute("object1") Object object1);
}
public static class MySessionAttributesControllerImpl implements MySessionAttributesControllerIfc {
static class MySessionAttributesControllerImpl implements MySessionAttributesControllerIfc {
@Override
public String get(Model model) {
@ -2444,7 +2457,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@RequestMapping("/myPage")
@SessionAttributes({"object1", "object2"})
public interface MyParameterizedControllerIfc<T> {
interface MyParameterizedControllerIfc<T> {
@ModelAttribute("testBeanList")
List<TestBean> getTestBeans();
@ -2453,14 +2466,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
String get(Model model);
}
public interface MyEditableParameterizedControllerIfc<T> extends MyParameterizedControllerIfc<T> {
interface MyEditableParameterizedControllerIfc<T> extends MyParameterizedControllerIfc<T> {
@RequestMapping(method = RequestMethod.POST)
String post(@ModelAttribute("object1") T object);
}
@Controller
public static class MyParameterizedControllerImpl implements MyEditableParameterizedControllerIfc<TestBean> {
static class MyParameterizedControllerImpl implements MyEditableParameterizedControllerIfc<TestBean> {
@Override
public List<TestBean> getTestBeans() {
@ -2485,7 +2498,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class MyParameterizedControllerImplWithOverriddenMappings
static class MyParameterizedControllerImplWithOverriddenMappings
implements MyEditableParameterizedControllerIfc<TestBean> {
@Override
@ -2514,7 +2527,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class MyFormController {
static class MyFormController {
@ModelAttribute("testBeanList")
public List<TestBean> getTestBeans() {
@ -2536,7 +2549,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class ValidTestBean extends TestBean {
static class ValidTestBean extends TestBean {
@NotNull
private String validCountry;
@ -2551,7 +2564,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class MyModelFormController {
static class MyModelFormController {
@ModelAttribute
public List<TestBean> getTestBeans() {
@ -2572,7 +2585,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class LateBindingFormController {
static class LateBindingFormController {
@ModelAttribute("testBeanList")
public List<TestBean> getTestBeans(@ModelAttribute(name="myCommand", binding=false) TestBean tb) {
@ -2915,7 +2928,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class ModelExposingViewResolver implements ViewResolver {
static class ModelExposingViewResolver implements ViewResolver {
@Override
public View resolveViewName(String viewName, Locale locale) {
@ -2926,7 +2939,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class ParentController {
static class ParentController {
@RequestMapping(method = RequestMethod.GET)
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
@ -2935,7 +2948,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Controller
@RequestMapping("/child/test")
public static class ChildController extends ParentController {
static class ChildController extends ParentController {
@RequestMapping(method = RequestMethod.GET)
public void doGet(HttpServletRequest req, HttpServletResponse resp, @RequestParam("childId") String id) {
@ -2969,7 +2982,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@MyControllerAnnotation
public static class CustomAnnotationController {
static class CustomAnnotationController {
@RequestMapping("/myPath.do")
public void myHandle() {
@ -2977,7 +2990,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class RequiredParamController {
static class RequiredParamController {
@RequestMapping("/myPath.do")
public void myHandle(@RequestParam(value = "id", required = true) int id,
@ -2986,7 +2999,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class OptionalParamController {
static class OptionalParamController {
@RequestMapping("/myPath.do")
public void myHandle(@RequestParam(required = false) String id,
@ -2998,7 +3011,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class DefaultValueParamController {
static class DefaultValueParamController {
@RequestMapping("/myPath.do")
public void myHandle(@RequestParam(value = "id", defaultValue = "foo") String id,
@ -3010,7 +3023,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class DefaultExpressionValueParamController {
static class DefaultExpressionValueParamController {
@RequestMapping("/myPath.do")
public void myHandle(@RequestParam(value = "id", defaultValue = "${myKey}") String id,
@ -3022,7 +3035,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class NestedSetController {
static class NestedSetController {
@RequestMapping("/myPath.do")
public void myHandle(GenericBean<?> gb, HttpServletResponse response) throws Exception {
@ -3031,7 +3044,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class TestBeanConverter implements Converter<String, ITestBean> {
static class TestBeanConverter implements Converter<String, ITestBean> {
@Override
public ITestBean convert(String source) {
@ -3040,14 +3053,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class PathVariableWithCustomConverterController {
static class PathVariableWithCustomConverterController {
@RequestMapping("/myPath/{id}")
public void myHandle(@PathVariable("id") ITestBean bean) throws Exception {
}
}
public static class AnnotatedExceptionRaisingConverter implements Converter<String, ITestBean> {
static class AnnotatedExceptionRaisingConverter implements Converter<String, ITestBean> {
@Override
public ITestBean convert(String source) {
@ -3061,7 +3074,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class MethodNotAllowedController {
static class MethodNotAllowedController {
@RequestMapping(value = "/myPath.do", method = RequestMethod.DELETE)
public void delete() {
@ -3093,7 +3106,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class PathOrderingController {
static class PathOrderingController {
@RequestMapping(value = {"/dir/myPath1.do", "/*/*.do"})
public void method1(Writer writer) throws IOException {
@ -3107,7 +3120,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class RequestResponseBodyController {
static class RequestResponseBodyController {
@RequestMapping(value = "/something", method = RequestMethod.PUT)
@ResponseBody
@ -3123,7 +3136,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class RequestResponseBodyProducesController {
static class RequestResponseBodyProducesController {
@RequestMapping(value = "/something", method = RequestMethod.PUT, produces = "text/plain")
@ResponseBody
@ -3133,7 +3146,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ResponseBodyVoidController {
static class ResponseBodyVoidController {
@RequestMapping("/something")
@ResponseBody
@ -3142,7 +3155,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class RequestBodyArgMismatchController {
static class RequestBodyArgMismatchController {
@RequestMapping(value = "/something", method = RequestMethod.PUT)
public void handle(@RequestBody A a) throws IOException {
@ -3150,14 +3163,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@XmlRootElement
public static class A {
static class A {
}
@XmlRootElement
public static class B {
static class B {
}
public static class NotReadableMessageConverter implements HttpMessageConverter<Object> {
static class NotReadableMessageConverter implements HttpMessageConverter<Object> {
@Override
public boolean canRead(Class<?> clazz, @Nullable MediaType mediaType) {
@ -3185,7 +3198,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class SimpleMessageConverter implements HttpMessageConverter<Object> {
static class SimpleMessageConverter implements HttpMessageConverter<Object> {
private final List<MediaType> supportedMediaTypes;
@ -3223,7 +3236,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ContentTypeHeadersController {
static class ContentTypeHeadersController {
@RequestMapping(value = "/something", headers = "content-type=application/pdf")
public void handlePdf(Writer writer) throws IOException {
@ -3237,7 +3250,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ConsumesController {
static class ConsumesController {
@RequestMapping(value = "/something", consumes = "application/pdf")
public void handlePdf(Writer writer) throws IOException {
@ -3251,7 +3264,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class NegatedContentTypeHeadersController {
static class NegatedContentTypeHeadersController {
@RequestMapping(value = "/something", headers = "content-type=application/pdf")
public void handlePdf(Writer writer) throws IOException {
@ -3266,7 +3279,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class AcceptHeadersController {
static class AcceptHeadersController {
@RequestMapping(value = "/something", headers = "accept=text/html")
public void handleHtml(Writer writer) throws IOException {
@ -3280,7 +3293,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ProducesController {
static class ProducesController {
@GetMapping(path = "/something", produces = "text/html")
public void handleHtml(Writer writer) throws IOException {
@ -3304,7 +3317,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ResponseStatusController {
static class ResponseStatusController {
@RequestMapping("/something")
@ResponseStatus(code = HttpStatus.CREATED, reason = "It's alive!")
@ -3314,7 +3327,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ModelAndViewResolverController {
static class ModelAndViewResolverController {
@RequestMapping("/")
public MySpecialArg handle() {
@ -3322,7 +3335,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class MyModelAndViewResolver implements ModelAndViewResolver {
static class MyModelAndViewResolver implements ModelAndViewResolver {
@Override
public ModelAndView resolveModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,
@ -3376,7 +3389,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Controller
@RequestMapping("/test*")
public static class BindingCookieValueController {
static class BindingCookieValueController {
@InitBinder
public void initBinder(WebDataBinder binder) {
@ -3393,16 +3406,16 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public interface TestController<T> {
interface TestController<T> {
ModelAndView method(T object);
}
public static class MyEntity {
static class MyEntity {
}
@Controller
public static class TestControllerImpl implements TestController<MyEntity> {
static class TestControllerImpl implements TestController<MyEntity> {
@Override
@RequestMapping("/method")
@ -3413,7 +3426,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@RestController
@RequestMapping(path = ApiConstants.ARTICLES_PATH)
public static class ArticleController implements ApiConstants, ResourceEndpoint<Article, ArticlePredicate> {
static class ArticleController implements ApiConstants, ResourceEndpoint<Article, ArticlePredicate> {
@Override
@GetMapping(params = "page")
@ -3435,14 +3448,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
String ARTICLES_PATH = API_V1 + "/articles";
}
public interface ResourceEndpoint<E extends Entity, P extends EntityPredicate<?>> {
interface ResourceEndpoint<E extends Entity, P extends EntityPredicate<?>> {
Collection<E> find(String pageable, P predicate) throws IOException;
List<E> find(boolean sort, P predicate) throws IOException;
}
public static abstract class Entity {
static abstract class Entity {
public UUID id;
@ -3451,7 +3464,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
public Instant createdDate;
}
public static class Article extends Entity {
static class Article extends Entity {
public String slug;
@ -3460,7 +3473,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
public String content;
}
public static abstract class EntityPredicate<E extends Entity> {
static abstract class EntityPredicate<E extends Entity> {
public String createdBy;
@ -3475,7 +3488,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class ArticlePredicate extends EntityPredicate<Article> {
static class ArticlePredicate extends EntityPredicate<Article> {
public String query;
@ -3486,7 +3499,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class RequestParamMapController {
static class RequestParamMapController {
@RequestMapping("/map")
public void map(@RequestParam Map<String, String> params, Writer writer) throws IOException {
@ -3521,7 +3534,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class RequestHeaderMapController {
static class RequestHeaderMapController {
@RequestMapping("/map")
public void map(@RequestHeader Map<String, String> headers, Writer writer) throws IOException {
@ -3564,14 +3577,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public interface IMyController {
interface IMyController {
@RequestMapping("/handle")
void handle(Writer writer, @RequestParam(value="p", required=false) String param) throws IOException;
}
@Controller
public static class IMyControllerImpl implements IMyController {
static class IMyControllerImpl implements IMyController {
@Override
public void handle(Writer writer, @RequestParam(value="p", required=false) String param) throws IOException {
@ -3579,14 +3592,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static abstract class MyAbstractController {
static abstract class MyAbstractController {
@RequestMapping("/handle")
public abstract void handle(Writer writer) throws IOException;
}
@Controller
public static class MyAbstractControllerImpl extends MyAbstractController {
static class MyAbstractControllerImpl extends MyAbstractController {
@Override
public void handle(Writer writer) throws IOException {
@ -3595,7 +3608,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class TrailingSlashController {
static class TrailingSlashController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public void root(Writer writer) throws IOException {
@ -3609,7 +3622,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ResponseEntityController {
static class ResponseEntityController {
@PostMapping("/foo")
public ResponseEntity<String> foo(HttpEntity<byte[]> requestEntity) throws Exception {
@ -3666,7 +3679,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class CustomMapEditorController {
static class CustomMapEditorController {
@InitBinder
public void initBinder(WebDataBinder binder) {
@ -3681,7 +3694,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class CustomMapEditor extends PropertyEditorSupport {
static class CustomMapEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
@ -3695,7 +3708,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class MultipartController {
static class MultipartController {
@InitBinder
public void initBinder(WebDataBinder binder) {
@ -3716,7 +3729,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class CsvController {
static class CsvController {
@RequestMapping("/singleInteger")
public void processCsv(@RequestParam("content") Integer content, HttpServletResponse response) throws IOException {
@ -3840,7 +3853,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class TextRestController {
static class TextRestController {
@RequestMapping(path = "/a1", method = RequestMethod.GET)
public String a1(@RequestBody String body) {
@ -3864,7 +3877,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@Controller
public static class ModelAndViewController {
static class ModelAndViewController {
@RequestMapping("/path")
public ModelAndView methodWithHttpStatus(MyEntity object) {
@ -3886,7 +3899,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class DataClass {
static class DataClass {
@NotNull
private final String param1;
@ -3921,7 +3934,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class DataClassController {
static class DataClassController {
@RequestMapping("/bind")
public String handle(DataClass data) {
@ -3930,7 +3943,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class PathVariableDataClassController {
static class PathVariableDataClassController {
@RequestMapping("/bind/{param2}")
public String handle(DataClass data) {
@ -3939,7 +3952,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class ValidatedDataClassController {
static class ValidatedDataClassController {
@InitBinder
public void initBinder(WebDataBinder binder) {
@ -3960,7 +3973,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class BindStatusView extends AbstractView {
static class BindStatusView extends AbstractView {
private final String content;
@ -3980,7 +3993,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class MultipartFileDataClass {
static class MultipartFileDataClass {
@NotNull
public final MultipartFile param1;
@ -4003,7 +4016,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class MultipartFileDataClassController {
static class MultipartFileDataClassController {
@RequestMapping("/bind")
public String handle(MultipartFileDataClass data) throws IOException {
@ -4012,7 +4025,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class ServletPartDataClass {
static class ServletPartDataClass {
@NotNull
public final Part param1;
@ -4035,7 +4048,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class ServletPartDataClassController {
static class ServletPartDataClassController {
@RequestMapping("/bind")
public String handle(ServletPartDataClass data) throws IOException {
@ -4045,7 +4058,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class NullableDataClassController {
static class NullableDataClassController {
@RequestMapping("/bind")
public String handle(@Nullable DataClass data, BindingResult result) {
@ -4060,7 +4073,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class OptionalDataClassController {
static class OptionalDataClassController {
@RequestMapping("/bind")
public String handle(Optional<DataClass> optionalData, BindingResult result) {
@ -4074,7 +4087,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
public static class DateClass {
static class DateClass {
@DateTimeFormat(pattern = "yyyy-MM-dd")
public LocalDate date;
@ -4085,7 +4098,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RestController
public static class DateClassController {
static class DateClassController {
@InitBinder
public void initBinder(WebDataBinder binder) {
@ -4107,4 +4120,16 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
static record DataRecord(String param1, boolean param2, int param3) {
}
@RestController
static class DataRecordController {
@RequestMapping("/bind")
public String handle(DataRecord data) {
return data.param1 + "-" + data.param2 + "-" + data.param3;
}
}
}