2016-04-25 5 views
1

ich einige Feder @RestControllers Methoden haben Feder, die Ich mag würde mit einem Wert injizieren, die mit jeder Anforderung als eine Anforderung Attribut kommt (die den Benutzer) so etwas wie:Injekt Anfrage Attribut von Anforderungssteuerung Methoden

@RestController 
@RequestMapping("/api/jobs") 
public class JobsController { 
    // Option 1 get user from request attribute as prop somehow 
    private String userId = "user1"; 

    // Option 2 inject into method using aspect or something else 
    @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
    public ResponseEntity<List<Jobs>> getJobs() throws ResourceNotFoundException { 
     // currentUser is injected 
     this.getJobs(currentUser); 
} 

ich weiß, was ich tun kann, dass:

@RestController 
@RequestMapping("/api/jobs") 
public class JobsController { 

    @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
    public ResponseEntity<List<Jobs>> getJobs(HttpServletRequest request) throws ResourceNotFoundException { 
     String currentUser = null; 
     if (request.getAttribute("subject") != null) { 
      currentUser = request.getAttribute("subject").toString(); 
     } 
     this.getJobs(currentUser); 
} 

Aber das würde mich benötigen diesen Code bei jeder Methode in meinem Programm zu schreiben, die mir scheint, eine wirklich schlechte Praxis.
Gibt es eine Möglichkeit zu erreichen, was ich will?

Wenn die Antwort Aspekt erfordert, wird ein Codebeispiel sehr geschätzt werden, da ich nur darüber gelesen habe, aber nie wirklich etwas mit Aspekt getan hat.

aktualisieren
Der Code i dies vereinfacht werden vorgeschlagen kann mit:

@RestController 
@RequestMapping("/api/jobs") 
public class JobsController { 

    @RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
    public ResponseEntity<List<Jobs>> getJobs(@Value("#{request.getAttribute('subject')}" String currentUser) throws ResourceNotFoundException { 
     this.getJobs(currentUser); 
} 

Aber erfordern mich immer noch, dass der Parameter bei jeder Methode hinzuzufügen. Kann dieser Parameter irgendwie in jede Methode injiziert werden?

+0

Haben Sie lesen [im Referenzhandbuch] (http://docs.spring.io/ spring/docs/aktuell/spring-framework-reference/html/mvc.html # mvc-ann-requestheader)? Sie benötigen keinen Aspekt, da dieser standardmäßig unterstützt wird. Machen Sie die Dinge nicht komplexer als nötig. –

+0

Ich kann nicht zu verstehen, wie es ist out-of-the-box? Ich muss dieses Stück Code auf jede Methode setzen, die ich habe, ich möchte es vermeiden. – Osher

+0

Wenn es JWT ist, dann empfehle ich dringend, anstatt ein Attribut mit der Anfrage richtig zu integrieren und das Prinzipal zu verwenden. Auf diese Weise können Sie 'getPrincipal' auf die Anfrage anwenden oder einfach den' Principal' zur Methodensignatur hinzufügen.Wenn Sie Spring Security zum Dekodieren der JWT verwenden, erhalten Sie diese Unterstützung kostenlos (Sie benötigen die Konfiguration). –

Antwort

0

Sie einen Filter verwenden könnte eine ThreadLocal<String> Variable zu füllen, die das Attribut speichert:

public class MyFilter implements Filter { 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException {} 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
    throws IOException, ServletException { 
    HttpServletRequest req = (HttpServletRequest) request; 
    ContextHolder.setSubject(request.getAttribute('subject')); 
    chain.doFilter(request, response); 
    } 

    @Override 
    public void destroy() { 
    ContextHolder.removeSubject(); 
    } 
} 


public class ContextHolder { 

    private static final ThreadLocal<String> SUBJECT = new ThreadLocal<String>() { 
    @Override 
    protected String initialValue() { 
     return "empty"; 
    } 
    }; 

    public static void setSubject(String subject) { 
    SUBJECT.set(subject); 
    } 

    public static String getSubject() { 
    return SUBJECT.get(); 
    } 

    public static void removeSubject() { 
    SUBJECT.remove(); 
    } 
} 

Der Filter wird so konfiguriert, alle Anfragen abzufangen und zu bevölkern die SUBJECT Variable. Mit einem ThreadLocal stellen Sie sicher, dass jeder Thread seinen eigenen subject Wert hat. Sie können nun diesen Wert überall in Ihrer Anwendung erhalten, indem ContextHolder.getSubject() Aufruf:

@RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
    public ResponseEntity<List<Jobs>> getJobs(HttpServletRequest request) throws ResourceNotFoundException { 
    this.getJobs(ContextHolder.getSubject()); 
    } 

Sie werden auch die Filter in der Datei web.xml registrieren müssen:

<filter> 
    <filter-name>MyFilter</filter-name> 
    <filter-class>com.MyFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>MyFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

Falls Sie mehrere Attribute hatte, Sie könnten stattdessen eine ThreadLocal<Map<String, String>> Variable verwenden.

0

Wenn Sie wirklich über Attribute wissen wollen, sollten Sie sich die @RequestParam Annotation des Frühlings ansehen. Sie würden es wie folgt verwenden:

@RequestMapping(value = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) 
public ResponseEntity<List<Jobs>> getJobs(@RequestParam("subject") String currentUser) throws ResourceNotFoundException { 
    this.getJobs(currentUser); 
} 
+0

Das Attribut @Header funktioniert nicht für mich, da sich die Daten in einem Anforderungsattribut befinden. Und der Grund, warum ich den Benutzer so bekomme, ist, dass ich jwt benutze, und vor meinem Controller gibt es einen Filter, der den Benutzer vom Token nimmt und ihn auf die Anfrage stellt. – Osher

+0

Ok, ich habe die Antwort aktualisiert. Es ist wirklich einfach. –

+0

Was ich brauchte, war @Value ("# {request.getAttribute ('subject')}", aber immer noch Duplikation für jede Methode. Iv'e aktualisiert die Frage, danke für Ihre Hilfe – Osher

0

Fügen Sie einfach nur @ResuestAttribute in Ihrem Rest contorller

@RestController 
@RequestMapping(path="/yourpath") 

@RequestMapping(method = RequestMethod.GET) 
    public ResponseEntity getAll(
      @RequestAttribute(value = "yourAttribute") Object 

yourAttribute ......

Verwandte Themen