2016-02-16 45 views
3

我想添加一個過濾器,創建一個對象,然後在Spring啓動應用程序中的控制器內使用。春天:如何將對象從過濾器傳遞到控制器

這個想法是使用過濾器作爲此對象的「集中式」生成器 - 這是特定於請求的且僅在控制器中有用的。 我試過使用HttpServletRequest request.getSession().setAttribute方法:我可以在控制器中訪問我的對象,但它會(明顯)添加到會話中。

篩選器是否正確嗎?如果是,我可以在哪裏保留由控制器使用的過濾器生成的臨時對象?

回答

4

可以使用ServletRequest.setAttribute(字符串名,對象O);

例如

@RestController 
@EnableAutoConfiguration 
public class App { 

    @RequestMapping("/") 
    public String index(HttpServletRequest httpServletRequest) { 
     return (String) httpServletRequest.getAttribute(MyFilter.passKey); 
    } 

    public static void main(String[] args) { 
     SpringApplication.run(App.class, args); 
    } 

    @Component 
    public static class MyFilter implements Filter { 

     public static String passKey = "passKey"; 

     private static String passValue = "hello world"; 

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

     } 

     @Override 
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
       throws IOException, ServletException { 
      request.setAttribute(passKey, passValue); 
      chain.doFilter(request, response); 
     } 

     @Override 
     public void destroy() { 

     } 
    } 
} 
2

我不知道實際情況是什麼,但如果你真的想在過濾器中創建一個對象,然後在代碼中的某個地方使用它,那麼你可以使用ThreadLocal類來這樣做。

爲了讓知道這項工作如何使用ThreadLocal這個問題Purpose of ThreadLocal?

一般來說,你將能夠創建可存儲僅適用於當前線程對象的一類看到的最投票的答案。

有時出於優化的原因,可以使用同一個線程來爲後續請求提供服務,因此在處理請求之後清理threadLocal值會很好。

class MyObjectStorage { 
    static private ThreadLocal threadLocal = new ThreadLocal<MyObject>(); 

    static ThreadLocal<MyObject> getThreadLocal() { 
    return threadLocal; 
    } 
} 

在過濾

MyObjectStorage.getThreadLocal().set(myObject); 

,並在控制器

MyObjectStorage.getThreadLocal().get(); 

相反過濾器,你也可以使用@ControllerAdvice並通過模型傳遞對象指定控制器。

@ControllerAdvice(assignableTypes={MyController.class}) 
class AddMyObjectAdvice { 

    // if you need request parameters 
    private @Inject HttpServletRequest request; 

    @ModelAttribute 
    public void addAttributes(Model model) { 
     model.addAttribute("myObject", myObject); 
    } 
} 


@Controller 
public class MyController{ 

    @RequestMapping(value = "/anyMethod", method = RequestMethod.POST) 
    public String anyMethod(Model model) { 
     MyObjecte myObject = model.getAttribute("myObject"); 

     return "result"; 
    } 
} 
0

的一種方式,我看到這種情況是與自己的實現意識到原來和你的臨時對象的包裹HttpServletRequest對象。這樣做的好處是它僅限於請求範圍,並不存儲在線程或會話中。因此,像這樣:

public class MyServletRequest extends HttpServletRequestWrapper { 
    private MyObject obj; 
    public MyServletRequest(HttpServletRequest request){ 
    super(request); 
    } 
    //set your object etc 
} 

然後在你的servlet:

public void doGet(HttpServletRequest req, HttpServletResponse resp){ 
    MyServletRequest myRequest = (MyServletRequest)req; 
    //now you can access your custom objects 
} 
0

你爲什麼不使用一個Bean與@Scope('request')

@Component 
@Scope(value="request", proxyMode= ScopedProxyMode.TARGET_CLASS) 
class UserInfo{ 
    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    private String password; 

} 

,然後你可以Autowireed這個bean在這兩個過濾器和控制器做設置和獲取的數據。

這個UserInfo bean的生命週期是在請求中僅exisits所以一旦HTTP請求做到,那麼就終止實例以及

+0

能否請您發佈完整的例子嗎? – Renann

相關問題