2015-04-20 36 views
13

Mevcut bir denetleyiciyi genişletmem ve ona bazı işlevler eklemem gerekiyor. Ancak, bir proje gereksinimi olarak, orijinal denetleyiciye dokunamıyorum, sorun, bu denetleyicinin üzerinde bir @RequestMapping ek açıklamasına sahip olmasıdır. Bu yüzden sorum, /someUrl numaralı telefona eski denetleyici yerine yeni denetleyicime nasıl istekte bulunabilirim. Burada Başka bir denetleyicide @RequestMapping nasıl geçersiz kılınır?

Sadece bahsettiğimi netleştirmek için bir örnektir:

Orjinal kontrolör:

@Controller 
public class HelloWorldController { 

    @RequestMapping("/helloWorld") 
    public String helloWorld(Model model) { 
     model.addAttribute("message", "Hello World!"); 
     return "helloWorld"; 
    } 
} 

yeni Denetleyici: Ben olmadan orijinal eşleşmesini geçersiz kılmak nasıl

@Controller 
public class MyHelloWorldController { 

    @RequestMapping("/helloWorld") 
    public String helloWorld(Model model) { 
     model.addAttribute("message", "Hello World from my new controller"); 
     // a lot of new logic 
     return "helloWorld"; 
    } 
} 

düzenleme HelloWorldController?

+0

emin değil (http://docs.spring.io /spring-framework/docs/3.2.3.RELEASE/javadoc-api/org/springframework/core/annotation/Order.html) açıklama, işleyici eşleme mantığını etkileyecektir (bunu bir deneyin). Değilse, farklı bir URL ile eşleştirebilir ve bir tür yeniden yazma işlemini gerçekleştirebilirsiniz (ör. [URLRewriteFilter] (http://tuckey.org/urlrewrite/) aracılığıyla). –

+0

Kendimi düzeltmek zorundayım - “Sipariş” işe yaramayacaktır çünkü yinelenen eşleştirmeye Baharda izin verilmiyor (çünkü onun cevabında Jordi işaret ediyor). –

cevap

9

URL eşleme geçersiz edilemez. Aynı istek URL'si ve istek yöntemiyle iki veya daha fazla Denetimci yapılandırılırsa bir hata alırsınız.

@Controller 
public class MyHelloWorldController { 

    @RequestMapping("/helloWorld", params = { "type=42" }) 
    public String helloWorld(Model model) { 
     model.addAttribute("message", "Hello World from my new controller"); 
     return "helloWorld"; 
    } 

} 

Örnek: Ne yapabilirsiniz

istek eşleme uzatmaktır Şimdi type = 42MyHelloWorldController irade yanıtı isteği


By yourhost/helloWorld çağırırsanız? yol. Denetleyici, dinamik içerik sağlayıcısı olmamalıdır. Bir @Service örneğine ihtiyacınız var. Böylece, Denetleyiciyi bir kez uygulayabilir ve çoklu Hizmet uygulamasını kullanabilirsiniz. Bu Burada ya da tehlikeli olabilir de olmayabilir de başka bir geçici çözüm vardır Spring MVC and DI

@Controller 
public class HelloWorldController { 

    @Autowired 
    private MessageService _messageService; // -> new MessageServiceImpl1() or new MessageServiceImpl2() ... 

    @RequestMapping("/helloWorld") 
    public String helloWorld(Model model) { 
     model.addAttribute("message", messageService.getMessage()); 
     return "helloWorld"; 
    } 

} 
3

Her bir eşleme benzersiz olmalıdır.. Mevcut bir @RequestMapping'un geçersiz kılınmasının bir yolu yoktur.



ANCAK Hep bir geçici çözümler yapabilirsiniz:

Kullanım mevcut birinden farklı olacaktır yeni @RequestMapping yaratacak böyle isteğinde bir param.

@RequestMapping("/helloWorld/{someDataId}", method = RequestMethod.GET) 
public String helloWorld(@PathVariable("someDataId") final long id, Model model) { 
/* your code here */ 
} 

ya da mevcut bir uzanan bir @Controller oluşturma: ek açıklama olarak

public class YourController extends BaseController { 

    @Override 
    @RequestMapping("/helloWorld") 
    public void renderDashboard(Model model){ 
     // Call to default functionallity (if you want...) 
     super.renderDashboard(patientId, map); 
    } 
} 
+0

Geçersiz kılmayı denediğimde maalesef ilkbahar bir AmbiguousMappingException atar. –

+0

Yeni * sanal * özniteliğiyle 1. seçeneği denediniz mi? –

+2

@JordiCastilla Anlayışım, yöntemlerin aynı adı ve imzası olmadıkça Geçersiz Kıl eşleştirmesini kullanamazsınız. İkinci seçenek nasıl çalışır? –

2

ana fikirdir.

aşağıda sınıfı "MyRequestMappingHandler" oluşturun, ardından da MvcConfig içinde

@Bean 
public RequestMappingHandlerMapping requestMappingHandlerMapping() { 

    return new MyRequestMappingHandler(); 
} 

RequestMappingHandlerMapping o kadar Tel: * BU ÜRETİM KODU DEĞİLDİR - SİZE UP *

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.aop.support.AopUtils; 
import org.springframework.context.annotation.Primary; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.servlet.mvc.method.RequestMappingInfo; 
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; 

import java.lang.reflect.Method; 
import java.util.List; 
import java.util.Map; 
import java.util.stream.Collectors; 

public class MyRequestMappingHandler extends RequestMappingHandlerMapping { 

@Override 
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) { 

     RequestMappingInfo mappingForMethod = super.getMappingForMethod(method, handlerType); 

     // Check if this class extends a super. and that super is annotated with @Controller. 
     Class superClass = handlerType.getSuperclass(); 

     if (superClass.isAnnotationPresent(Controller.class)) { 
      // We have a super class controller. 

      if (handlerType.isAnnotationPresent(Primary.class)) { 
      // We have a @Primary on the child. 
      return mappingForMethod; 
      } 
     } else { 
      // We do not have a super class, therefore we need to look for other implementations of this class. 
      Map<String, Object> controllerBeans = getApplicationContext().getBeansWithAnnotation(Controller.class); 

      List<Map.Entry<String, Object>> classesExtendingHandler = controllerBeans.entrySet().stream().filter(e -> 
       AopUtils.getTargetClass(e.getValue()).getSuperclass().getName().equalsIgnoreCase(handlerType 
         .getName()) && 
         !AopUtils.getTargetClass(e.getValue()).getName().equalsIgnoreCase(handlerType.getName())) 
       .collect(Collectors.toList()); 


      if (classesExtendingHandler == null || classesExtendingHandler.isEmpty()) { 
       // No classes extend this handler, therefore it is the only one. 
       return mappingForMethod; 
      } else { 
       // Classes extend this handler, 

       // If this handler is marked with @Primary and no others are then return info; 
       List<Map.Entry<String, Object>> classesWithPrimary = classesExtendingHandler 
        .stream() 
        .filter(e -> e.getValue().getClass().isAnnotationPresent(Primary.class) && 
          !AopUtils.getTargetClass(e.getValue().getClass()).getName().equalsIgnoreCase 
            (handlerType.getName())) 
        .collect(Collectors.toList()); 
       if (classesWithPrimary == null || classesWithPrimary.isEmpty()) { 
        // No classes are marked with primary. 
        return null; 
       } else { 
        // One or more classes are marked with @Primary, 

        if (classesWithPrimary.size() == 1 && AopUtils.getTargetClass(classesWithPrimary.get(0).getValue 
         ()).getClass().getName().equalsIgnoreCase(handlerType.getName())) { 
         // We have only one and it is this one, return it. 
         return mappingForMethod; 
        } else if (classesWithPrimary.size() == 1 && !AopUtils.getTargetClass(classesWithPrimary.get(0) 
         .getValue()).getClass().getName().equalsIgnoreCase(handlerType.getName())) { 
         // Nothing. 
        } else { 
         // nothing. 
        } 
       } 
      } 
     } 



     // If it does, and it is marked with @Primary, then return info. 

     // else If it does not extend a super with @Controller and there are no children, then return info; 

     return null; 
    } 
} 

ne bu Yapmanıza izin verir, bir @Controller sınıfı genişletmek ve @ Öncü ile işaretlemek ve bu sınıftaki bir yöntemi geçersiz kılmak, yeni sınıfınız artık "birden fazla fasulye/istekler" ile patlatmak yerine yayınlandığında yüklenecek t dönüşümler vb süper "Kontrolör" bir

Örnek:" uygulama

@Controller 
public class Foobar { 

    @RequestMapping(method = "GET") 
    private String index() { 
     return "view"; 
    } 

} 

Örnek: [ 'Order`] olup

@Primary 
@Controller 
public class MyFoobar extends Foobar { 

    @Override 
    private String index() { 
     return "myView"; 
    } 

} 
İlgili konular