2013-06-10 2 views
3

코드 재사용 가능성을 향상시키기 위해 일반 컨트롤러를 작성하려고 시도해 왔습니다. 아래는 내가 지금까지 무엇을 가지고 :Spring MVC의 일반 컨트롤러

public abstract class CRUDController<T> { 

    @Autowired 
    private BaseService<T> service; 

    @RequestMapping(value = "/validation.json", method = RequestMethod.POST) 
    @ResponseBody 
    public ValidationResponse ajaxValidation(@Valid T t, 
      BindingResult result) { 
     ValidationResponse res = new ValidationResponse(); 
     if (!result.hasErrors()) { 
      res.setStatus("SUCCESS"); 
     } else { 
      res.setStatus("FAIL"); 
      List<FieldError> allErrors = result.getFieldErrors(); 
      List<ErrorMessage> errorMesages = new ArrayList<ErrorMessage>(); 
      for (FieldError objectError : allErrors) { 
       errorMesages.add(new ErrorMessage(objectError.getField(), 
         objectError.getDefaultMessage())); 
      } 
      res.setErrorMessageList(errorMesages); 
     } 
     return res; 
    } 

    @RequestMapping(method = RequestMethod.GET) 
    public String initForm(Model model) { 
     service.initializeForm(model); 
     return "country"; // how can I make this generic too ? 
    } 
} 

T 나라, 항목, 등록 및 사용자 같은 것들을 할 수 있습니다. 현재 자동 배선 프로세스에 직면 한 문제는 다음 오류로 인해 실패했습니다.

No unique bean of type [com.ucmas.cms.service.BaseService] is defined: expected single matching bean but found 4: [countryServiceImpl, itemServiceImpl, registrationServiceImpl, userServiceImpl]. 

내가 원하는 것을 얻을 수 있습니까? 이 문제를 어떻게 해결할 수 있습니까?

+2

스프링 4부터 제네릭 타입을 기반으로 자동 와이어 링이 가능합니다. 내 대답은 업데이트를 참조하십시오. – matsev

답변

8

나는 당신이 CRUDController 클래스에 생성자 매개 변수로 BaseService를 추가하는 것이 좋습니다 :

public abstract class CRUDController<T> { 

    private final BaseService<T> service; 
    private final String initFormParam; 

    public CRUDController(BaseService<T> service, String initFormParam) { 
     this.service = service; 
     this.initFormParam; 
    } 

    @RequestMapping(value = "/validation.json", method = RequestMethod.POST) 
    @ResponseBody 
    public ValidationResponse ajaxValidation(@Valid T t, BindingResult result) { 
     // same as in the example 
     return res; 
    } 

    @RequestMapping(method = RequestMethod.GET) 
    public String initForm(Model model) { 
     service.initializeForm(model); 
     return initFormParam; // Now initialized by the constructor 
    } 
} 

그런 다음 당신이 그것을 확장 서브 클래스의 각각에서 autowiring을 사용할 수 있습니다

또는
public class CountryController extends CRUDController<Country> { 

    @Autowired 
    public CountryController(CountryService countryService) { 
     super(countryService, "country"); 
    } 
} 

, 귀하의 생성자에서 @Qualifier 주석을 사용하여 다른 BaseService 구현을 구별 할 수 있습니다.

@Autowired 
public CountryController(@Qualifier("countryServiceImpl") BaseService<Country> baseService) { 
    super(baseService, "country"); 
} 

업데이트 :Spring 4.0 RC1의로

, 그것은 일반적인 유형에 따라 자동으로 묶어 할 수 있습니다. 당신의 생성자를 autowiring에 경우에 따라서, 당신은 매개 변수로 일반적인 BaseService<Country>을 사용할 수 있으며, 봄은 아직 어떤 NoSuchBeanDefinitionException 던지는없이 올바른 하나입니다 알아낼 수있을 것입니다 : 여기

@Controller 
public class CountryController extends CRUDController<Country> { 

    @Autowired 
    public CountryController(BaseService<Country> countryService) { 
     super(countryService, "country"); 
    } 
} 
4

나의 솔루션입니다

public abstract class CrudController<Model extends MyEntity<Model>, Service extends SharedService>{ 

private Service service; 

public void setDependencies(Service service){ 
    this.service = service; 
} 

@RequestMapping(value = "/get", method = RequestMethod.GET) 
public Response get(){ 
    Response response = new Response(); 
    try{ 
     response.setStatusCode(200); 
     response.setMessage("Successfully retrieved " + service.count() + "."); 
     response.setData(service.getAll()); 
    }catch(Exception e){ 
     response.setServerError(e.getMessage()); 
    } 
    return response; 
} 

그리고 컨트롤러는 이제 경로 mylocalhost/foo는 사용이

@RequestMapping(value = "/foo") 
@RestController 
public class FooController extends CrudController<Foo, FooServiceImpl> { 

private final FooServiceImpl fooService; 
} 
@Autowired 
public GroupsController(FooServiceImpl fooService){ 
    super.setDependencies(fooService); 
    this.fooService = fooService; 
} 

과 같은 작업을 수행 할 수 있습니다/를 얻을 수당신에게 모든 정보를 돌려 줄 것입니다.