2013-12-20 42 views
7

我想在Spring MVC項目中使用Spring的DomainClassConverter功能。 (我只有Spring MVC和Spring的基本知識,對於任何天真的問題都會提前道歉)。在Spring MVC中使用Spring的DomainClassConverter的問題

API docs

The DomainClassConverter allows you to use domain types in your Spring MVC controller 
method signatures directly, so that you don't have to manually lookup the instances via 
the repository: (PS: Example 1.20) 

我從以上可以理解的是,我沒有寫一個查找方法和Spring提供的User對象。因此,這些是我所做的步驟:

applicationcontext.xml中包含下面的XML行。

<bean class="org.springframework.data.web.config.SpringDataWebConfiguration" /> 
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 
<property name="converters"> 
    <list> 
     <bean class="com.rl.userservice.controller.UserConverter"/> 
    </list> 
</property> 

包括這種依賴性在我pom.xmlSpring Data REST DOC:

<dependencies> 
    <dependency> 
     <groupId>org.springframework.data</groupId> 
     <artifactId>spring-data-rest-webmvc</artifactId> 
     <version>2.0.0.BUILD-SNAPSHOT</version> 
    </dependency> 
</dependencies> 

我的控制器看起來像下面:

@Controller 
@RequestMapping(value = "/api/newuser") 
public class NewUserServiceController { 
     @Autowired 
    NewUserRepository newUserRepository; 

    @RequestMapping("/{id}") 
    public String showUserForm(@PathVariable("id") NewUser newUser, Model model) { 

     model.addAttribute("newUser", newUser); 
     return "userForm"; 
    } 
} 

Repository是這樣的:

@Repository 
public interface NewUserRepository extends JpaRepository<NewUser, Integer> { 
} 

這是我的轉換服務:

final class UserConverter implements Converter<Integer, NewUser> { 
    NewUserRepository newUserRepository; 

    public NewUser convert(Integer username) { 
     return newUserRepository.findOne(username); 
    } 
} 

當我運行程序Tomcat啓動成功,但訪問的URL 本地主機時:8080/userservice/api/newuser/1我收到以下例外情況:

type Exception report 
    message 
    description The server encountered an internal error() that prevented it from fulfilling this request. 
    exception 
    org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 
'com.mpp.userservice.domain.NewUser'; nested exception is 
java.lang.IllegalStateException: Cannot convert value of type 
[java.lang.String] to required type 
[com.mpp.userservice.domain.NewUser]: no matching editors or 
conversion strategy found 
     org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:71) 
     org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) 
     org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) 
     org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:101) 
     org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) 
     org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) 
     org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123) 
     org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) 
     org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
     org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) 
     org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) 
     org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) 
     org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
     org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 

    root cause 
    java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type 
[com.mpp.userservice.domain.NewUser]: no matching editors or 
conversion strategy found 
     org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:264) 
     org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:93) 
     org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:61) 
     org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:45) 
     org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:595) 
     org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:101) 
     org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) 
     org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) 
     org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:123) 
     org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) 
     org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) 
     org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
     org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) 
     org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) 
     org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) 
     org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
     org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) 
     javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 

    note The full stack trace of the root cause is available in the Apache Tomcat/6.0.29 logs. 
    mpp. 

雖然不是最好的代碼,這是我的控制器:

public @ResponseBody ResponseEntity<ModelMap> getUserTypeJSON(@PathVariable("userID" String userID, HttpServletResponse response) { 
    UserType UserType = UserTypeRepository.findOne(id); 
    model.addAttribute("Name",UserType.getName()); 
    ... 
} 

有一個例子here,我引用的,但是這是使用自定義轉換器,但似乎並沒有被使用域轉換服務。請指教。如果我想要減少寫作CRUD操作的樣板代碼,這是否應該走?當我能以其他方式獲取數據時,這個DomainClassConverter的真正好處是什麼?

每奧利弗·基爾克建議更新 - 仍然不能正常工作,同樣的錯誤

該文件描述:

<mvc:annotation-driven conversion-service="conversionService" /> 
<bean class="org.springframework.data.repository.support.DomainClassConverter"> 
    <constructor-arg ref="conversionService" /> 
</bean> 

所以我下面更新我的applicationcontext.xml,但同樣的問題:

<mvc:annotation-driven conversion-service="conversionService"/> 

    <bean class="org.springframework.data.repository.support.DomainClassConverter"> 
    <constructor-arg ref="conversionService" /> 
    </bean> 

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> 
    <property name="converters"> 
     <list> 
      <bean class="com.rl.userservice.controller.UserConverter"/> 
     </list> 
    </property> 
    </bean> 

仍是同樣的問題。

更新: DomainClassConverter與Java Config協同工作,但不支持XML方式(至少在這裏建議的以及在互聯網上的許多組合)。只爲其他可能感興趣的人提供一些有用的信息,這裏是所用的代碼。

pom.xml的(可能需要清理)

<dependency> 
    <groupId>org.springframework.data</groupId> 
    <artifactId>spring-data-rest-webmvc</artifactId> 
    <version>2.0.0.M1</version> 
</dependency> 

<dependency> 
    <groupId>org.springframework.data</groupId> 
    <artifactId>spring-data-jpa</artifactId> 
    <version>1.4.3.RELEASE</version> 
</dependency> 

控制器文件(可能需要清理)

@RequestMapping("/domain/{id}") 
    public @ResponseBody ResponseEntity<ModelMap> showDomainUserForm(@PathVariable("id") User userMatch, HttpServletResponse response) { 

    // some code omitted… 

    ModelMap model = new ModelMap();   
    model.addAttribute("DOMAIN-MAP","Domain Controller Service"); 
    model.addAttribute("Name",userMatch.getName()); 
    model.addAttribute("Phone",userMatch.getPhone());           

    // some code omitted… 


    } 

Java的配置文件中使用的實例組裝從和resource2。 (可能需要清理)

package com.rl.userservice.controller; 

import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.data.repository.support.DomainClassConverter; 
import org.springframework.format.support.FormattingConversionService; 
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; 
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; 

@Configuration 
@ComponentScan 
@EnableWebMvc 
public class WebConfig extends WebMvcConfigurationSupport{ 
    @Bean 
    public RequestMappingHandlerMapping requestMappingHandlerMapping() { 
     RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping(); 
     handlerMapping.setUseSuffixPatternMatch(false); 
     handlerMapping.setUseTrailingSlashMatch(false); 
     return handlerMapping; 
    } 


    @Bean 
    public DomainClassConverter<?> domainClassConverter() { 
     return new DomainClassConverter<FormattingConversionService>(mvcConversionService()); 
    } 

    @Override 
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 
     configurer.enable(); 
    } 

} 

添加下面的bean定義在applicationContext.xml

<bean class="com.rl.userservice.controller.WebConfig"/> 
+0

什麼是'applicationcontext.xml'它是你的調度程序servlet上下文嗎? http://stackoverflow.com/questions/3652090/difference-between-applicationcontext-xml-and-spring-servlet-xml-in-spring MVC標籤和轉換器可能會在調度程序servlet使用的上下文中聲明 - 而不是根應用程序Web應用程序上下文 –

+0

請勿定義您自己的轉換服務(或自定義UserConverter)。刪除你的'conversionService' bean定義! –

+0

@Pavel你能詳細說明一下嗎?在這種情況下,我認爲轉換服務處於錯誤的上下文環境中,所以它被調度程序servlet中的轉換服務所遮蔽,但通常顯式聲明自定義bean沒有任何問題。 –

回答

0

請看看在relevant section of the reference documentation,瞭解正確的方法配置DomainClassConverter

+0

我試過每個解決方案,但不起作用。我也嘗試過你的其他解決方案 - https://jira.springsource.org/si/jira.issueviews:issue-html/DATACMNS-133/DATACMNS-133.html DomainClassConverter還存在問題嗎?最新的文檔也有所不同http://docs.spring.io/spring-data/data-commons/docs/current/reference/htmlsingle/#core.web – oneworld

+1

我通過互聯網搜索,找到沒有好的工作樣本碼。每個網站都有自己的做法,但只提供零散的信息。有沒有我可以完全參考的示例項目? – oneworld

+0

這個問題仍然徘徊? http://forum.spring.io/forum/spring-projects/data/113584-help-with-domainclassconverter-configuration – oneworld

1

URL是String,所以{id}也是String。因此,您的服務必須能夠按照您的要求將String轉換爲NewUser,而不是Integer

+0

那是UserConverter類的評論嗎?即使這樣,錯誤也是一樣的: public NewUser convert(String username){ return newUserRepository.findOne(Integer.parseInt(username)); }} – oneworld

+0

@oneworld不知道,如果它是必要的,但我使用的是'FormattingConversionServiceFactoryBean',而不是'ConversionServiceFactoryBean' – zeroflagL

0

ref

目前該庫必須實現CrudRepository是 資格被發現了轉換。

不應該是這個原因嗎?

+0

JpaRepository延伸PagingAndSortingRepository這又延伸CrudRepository,所以這不應該是這是基於一個問題 – lilalinux

0

這種結構設置了一個自定義的轉換服務,並將其傳遞到檢測並建立控制器註釋掃描機構:

<bean name="conversionService" class="rest.gateway.services.MyConversionService"/> 

<mvc:annotation-driven conversion-service="conversionService" /> 

而這是用於定製控制器的代碼,客戶是一個域類等用戶:

public class MyConversionService extends DefaultConversionService { 

    public MyConversionService() { 
     super(); 
     addConverter(String.class, Customer.class, new Converter<String, Customer>() { 
      @Override 
      public Customer convert(String source) { 
       return new Customer("123456","Doe","John"); 
      } 
     }); 
    } 
} 

有這樣的嘗試,因爲這是工作2.0.0.M1版本:

<dependency> 
     <groupId>org.springframework.data</groupId> 
     <artifactId>spring-data-rest-webmvc</artifactId> 
     <version>2.0.0.M1</version> 
    </dependency> 

<repositories> 
    <repository> 
     <id>spring-milestones</id> 
     <name>Spring Milestones</name> 
     <url>http://repo.spring.io/milestone</url> 
     <snapshots> 
      <enabled>false</enabled> 
     </snapshots> 
    </repository> 
</repositories> 
+0

在http://docs.spring.io/spring-data/jpa/docs/1.4.x/reference/html/repositories.html#d0e1111,我已經使用它並可以確認它正在工作 –

+0

我真的需要編寫一個域轉換器類的自定義轉換器?這是不是縮減目的? – oneworld