在Spring MVC中将对象从@ControllerAdvice传递给@Controller

时间:2015-03-20 07:31:24

标签: java spring spring-mvc

我想检查ControllerAdvice中是否存在用户,如果用户存在则将用户视为@ModelAttribute。另一方面,我还想直接访问@Controller中的用户对象。所以我在@RequestMapping方法的参数上添加@ModelAttribute注释。

我正在使用@ControllerAdvice:

@ControllerAdvice
public class UserAdvice {

    @Autowired
    private UserService userService;

    @ModelAttribute("user")
    public User user(@PathVariable("username") String username) {
        User user = userService.findByUsername(username);
        if (user != null) {
            return user;
        }
        user = userService.findById(username);
        if (user == null) {
            throw new ResourceNotFoundException("user not found");
        }

        return user;
    }
}

UserController赞:

@RestController
@RequestMapping("/users/{username}")
public class UserController {

    public static final Logger logger = LoggerFactory.getLogger(UserCourseListController.class);

    @Autowired
    private CourseService courseService;

    @RequestMapping(value = "", method = RequestMethod.GET)
    public void getUser(@ModelAttribute("user") User user, Model model) {
        logger.info("{}", user);//user is null
        logger.info("{}", model.asMap().get("user"));// not null
    }

}

但是现在,使用@ModelAttribute注释的参数user为null,而模型映射中有“user”obj。

我在这种情况下是否有任何错误?或者对@ModelAttribute@ControllerAdvice

的概念有任何误解

非常感谢!

更新

来自Docs of Springframework

  

一旦出现在模型中,参数的字段应该从具有匹配名称的所有请求参数中填充。

因此,我们无法将@ModelAttribute直接添加到由@RequestMapping注释的方法参数,因为Spring将根据请求(而非Model)进行数据绑定。

最后我找到了一个解决方案 - HandlerMethodArgumentResolver。它可以解析每个@RequestMapping方法的方法参数,并在解析参数方面做一些工作。 Java Config的一个例子如下:

public class Config extends WebMvcConfigurerAdapter {

    @Bean(name = "auditorBean")
    public AuditorAware<User> auditorAwareBean() {
        return () -> null;
    }

    @Bean
    public HttpMessageConverters customConverters() {
        return new HttpMessageConverters(new MappingJackson2HttpMessageConverter());
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new HandlerMethodArgumentResolver() {
            @Override
            public boolean supportsParameter(MethodParameter parameter) {
                return parameter.getParameterType().equals(User.class);
            }

            @Override
            public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
                return mavContainer.getDefaultModel().get(parameter.getParameterName());
            }
        });
    }

}

我们通过parameter.getParameterName()从模型中解析方法参数。这意味着方法参数(user)的名称必须等于@ControllerAdvice中定义的@ModelAttrubute的值。您还可以使用任何其他命名约定来实现绑定。

0 个答案:

没有答案