Nik*_*tić 9 spring spring-mvc spring-boot
我有一个类型化的抽象RestController,它包含一些用于处理该类型所有对象的通用逻辑.处理服务是通过构造函数提供的.
在子类的bean实例化期间,使用非null参数调用两个构造函数,并成功传递超类非null断言.
调用API端点(URI路径是子类和超类路径的组合)使用正确识别的参数调用正确的方法.但是,endpoint方法抛出空指针异常,因为提供的服务(传递非null断言的服务)为null.在检查其方法被调用的bean的子类和超类的所有属性时,将所有属性报告为null.
这是一个简化的例子:
模型:
public class Cookie {
public long id;
}
public class ChocolateCookie extends Cookie {
public long chipCount;
}
Run Code Online (Sandbox Code Playgroud)
服务:
public interface CookieService<T extends Cookie> {
T findCookie(long cookieId);
void eatCookie(T cookie);
}
@Service
public class ChocolateCookieService implements CookieService<ChocolateCookie> {
@Override
public ChocolateCookie findCookie(long cookieId) {
// TODO Load a stored cookie and return it.
return new ChocolateCookie();
}
@Override
public void eatCookie(ChocolateCookie cookie) {
// TODO Eat cookie;
}
}
Run Code Online (Sandbox Code Playgroud)
休息控制器:
public abstract class CookieApi<T extends Cookie> {
private final CookieService<T> cookieService;
public CookieApi(CookieService<T> cookieService) {
this.cookieService = cookieService;
Assert.notNull(this.cookieService, "Cookie service must be set.");
}
@PostMapping("/{cookieId}")
public ResponseEntity eatCookie(@PathVariable long cookieId) {
final T cookie = cookieService.findCookie(cookieId); // Cookie service is null
cookieService.eatCookie(cookie);
return ResponseEntity.ok();
}
}
@RestController
@RequestMapping("/chocolateCookies")
public class ChocolateCookieApi extends CookieApi<ChocolateCookie> {
@Autowired
public ChocolateCookieApi(ChocolateCookieService cookieService) {
super(cookieService);
}
@PostMapping
public ResponseEntity<ChocolateCookie> create(@RequestBody ChocolateCookie dto) {
// TODO Process DTO and store the cookie
return ResponseEntity.ok(dto);
}
}
Run Code Online (Sandbox Code Playgroud)
需要注意的是,如果不是向超类提供服务对象,而是定义了一个抽象方法,用于按需获取服务并在子类中实现它,超类将按预期运行.
在任何情况下,同样的原理都适用于@RestController和@RequestMapping不包括在等式中.
我的问题是双重的:
编辑1:
我尝试重新创建问题,但提供的代码工作正常,正如人们建议的那样.在篡改简化项目后,我终于设法重现了这个问题.重现问题的实际条件是子类中的端点方法必须是子类不可访问的(例如:类在不同的包中,并且该方法具有包可见性).这会导致spring创建一个EnhancerBySpringCGLIB代理类,其中填充的字段为零.
修改超类方法以获得受保护/公共可见性解决了该问题.
尼古拉,
我不知道为什么你的代码不能在你的系统中工作,我在一个项目中创建了相同的类并且它工作正常,我什至添加了另一个 Cookie 类型、服务和 api 类。
SpringBoot日志(可以看到初始化的4个端点):
2019-02-26 14:39:07.612 INFO 86060 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/chocolateCookies],methods=[POST]}" onto public org.springframework.http.ResponseEntity<cookie.ChocolateCookie> cookie.ChocolateCookieApi.create(cookie.ChocolateCookie)
2019-02-26 14:39:07.613 INFO 86060 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/chocolateCookies/{cookieId}],methods=[POST]}" onto public org.springframework.http.ResponseEntity<?> cookie.CookieApi.eatCookie(long)
2019-02-26 14:39:07.615 INFO 86060 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/oatmeal-raisin-cookie],methods=[POST]}" onto public org.springframework.http.ResponseEntity<cookie.OatmealRaisinCookie> cookie.OatmealRaisingCookieApi.create(cookie.OatmealRaisinCookie)
2019-02-26 14:39:07.615 INFO 86060 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/oatmeal-raisin-cookie/{cookieId}],methods=[POST]}" onto public org.springframework.http.ResponseEntity<?> cookie.CookieApi.eatCookie(long)
Run Code Online (Sandbox Code Playgroud)
正如 @Domingo 提到的,您的应用程序中可能存在一些配置问题,因为从 OOP 和 Spring IoC 的角度来看,您的代码看起来很好并且运行没有问题。
注意:我使用 SpringBoot 2.0.5、Java 8、Eclipse 运行这些控制器
我把我的项目发布在GitHub上供大家参考。 https://github.com/karl-codes/cookie-monster
干杯!
| 归档时间: |
|
| 查看次数: |
1351 次 |
| 最近记录: |