我有一个类似
的控制器@RequestMapping(value = {TABLE_URL}, method = RequestMethod.POST)
@ResponseBody
public TableModel checkAvailability(@ModelAttribute TableQueryForm TableQueryForm,
TableContext table, BindingResult bindingResult) throws Exception {
// body
}
TableContext是具有实现及其正常工作的接口。
最近我需要添加一个自定义日期格式化程序,因此在将其启用后,我添加了行
<mvc:annotation-driven conversion-service="conversionService"/>
如here
现在添加此内容后,我的请求失败,出现以下异常
Wrapped by: java.lang.IllegalStateException: No primary or default constructor found for interface com.table.domain.search.TableContext
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:212)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:84)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:132)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
此类的实现未定义构造函数,因此默认情况下应激活默认的构造函数。我不知道为什么会这样。请帮助我解决这个问题。
答案 0 :(得分:3)
如果不提供适当的HandlerMethodArgumentResolver
,则无法在spring handler中注入自定义的Java接口。请注意“ custom”一词,因为Spring可以注入其他接口的实现,例如HttpServletRequest,HttpServletResponse,Reader,Writer等。在这些情况下,Spring注入适当的具体实现。对于自定义的Java类(如果仅是interface),从您得到的错误的stacktrace中可以看出不可能的原因。如果您的接口没有自定义处理程序解析器,则解析逻辑将在默认的ModelAttributeMethodProcessor上回退,该模型将在所有情况下都为上述接口类查找一个构造函数,但是由于在Java中该接口无法具有构造函数,因此它将失败(请注意带有FAILS的行)在这里)
public class ModelAttributeMethodProcessor {
protected Object createAttribute(String attributeName, MethodParameter parameter,
WebDataBinderFactory binderFactory, NativeWebRequest webRequest) throws Exception {
MethodParameter nestedParameter = parameter.nestedIfOptional();
Class<?> clazz = nestedParameter.getNestedParameterType();
Constructor<?> ctor = BeanUtils.findPrimaryConstructor(clazz);
if (ctor == null) {
Constructor<?>[] ctors = clazz.getConstructors();
if (ctors.length == 1) {
ctor = ctors[0];
}
else {
try {
ctor = clazz.getDeclaredConstructor(); // FAILS HERE
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("No primary or default constructor found for " + clazz, ex);
}
}
}
......................................
......................................
我尝试了以下测试课程
public interface TestInterface {
public void test() ;
}
@Component
public class TestInterfaceImpl implements TestInterface {
@Override
public void test() {
System.out.println("Test called");
}
}
如果我的测试控制器是
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("test")
public String withParam(TestInterface testInterface) {
return "test";
}
我和你遇到同样的错误
Caused by: java.lang.IllegalStateException: No primary or default constructor found for interface com.shailendra.TestInterface
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:212)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:84)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:132)
但是如果我在下面使用
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("test")
public String withParam(TestInterfaceImpl test) {
return "test";
}
我得到了适当的答复。
如果接口注入有效,那么看起来您早先已经配置了适当的HandlerMethodArgumentResolver,但是由于某种原因,现在它没有被使用(也许是因为配置未包含在弹簧扫描中)
答案 1 :(得分:1)
需要一个空的构造函数来通过持久性框架的反射来创建新实例。如果不为该类的任何其他构造函数提供参数,则无需提供空的构造函数,因为默认情况下会得到一个。 @ u6f6o
您可能正在提供其他构造函数,因此您也应该尝试实现一个空的构造函数。
答案 2 :(得分:1)
您正在使用Java批注配置还是XML配置,如果您正在使用Java批注配置,那么您要做的就是删除XML配置文件以使其再次工作。
如果这不能解决您的问题,请提供您的配置和控制器类,以帮助解决问题。
答案 3 :(得分:0)
我建立了一个像您一样的项目,并且效果很好,但是我不知道您的bean中有哪些属性。 您可以根据实际代码进行调整
public interface TableContext {
Long getDate();
}
public class TableContextImpl implements TableContext{
private Long date;
private String tableName;
//getter setter ...
}
控制器
public String testOne(@RequestParam("tableContext") TableContext tableContext)
配置
<context:annotation-config/>
<context:component-scan base-package="com.test.controller"/>
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="tableContextFormatter"/>
</set>
</property>
</bean>
//this one is your custom formatter
<bean id="tableContextFormatter" class="com.test.controller.TableContextFormatter"></bean>
格式化程序
public class TableContextFormatter implements Converter<String, TableContext> {
@Override
public TableContext convert(String s) {
TableContext tc = null;
if ( null != s ){
tc = new TableContextImpl();
//your formatting rules here
((TableContextImpl) tc).setDate(Long.parseLong(s));
}
return tc;
}
}