xylz,imxylz

          關注后端架構、中間件、分布式和并發編程

             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            111 隨筆 :: 10 文章 :: 2680 評論 :: 0 Trackbacks

          3 Web 和 Servlet

          3.1 快速開始

          我們從一個例子開始Guice Web的開發。

           image 首先準備我們的環境,由于是web開發,因此我們需要guice-servlet的jar包。log4j不是必須的,只是為了方便日志記錄而已(Guice內部是使用jdk內部的logging包來完成日志記錄的)。

          必可避免的要在web.xml中都一些手腳,這里先配置一個filter吧。

          <filter>
              
          <filter-name>guiceFilter</filter-name>
              
          <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
          </filter>
          <filter-mapping>
              
          <filter-name>guiceFilter</filter-name>
              
          <url-pattern>/*</url-pattern>
          </filter-mapping>

           

          GuiceFilter中并沒有幫我們完成Guice的初始化工作,因此我們必須手動完成Guice的模塊注入。


          1 public class MyGuiceServletContextListener extends GuiceServletContextListener {
          2 
          3     @Override
          4     protected Injector getInjector() {
          5         return Guice.createInjector(new ServletModule());
          6     }
          7 }
          8 

          繼續在web.xml中添加東西。

          <listener>
              
          <listener-class>cn.imxylz.study.guice.web.MyGuiceServletContextListener</listener-class>
          </listener>

           

          顯然我們需要將某個PATH映射到一個Servlet上,于是需要在ServletModule上做點事情。


           1 public class MyGuiceServletContextListener extends GuiceServletContextListener {
           2 
           3     @Override
           4     protected Injector getInjector() {
           5         return Guice.createInjector(new ServletModule() {
           6             protected void configureServlets() {
           7                 serve("/helloworld").with(HelloWorldServlet.class);
           8             }
           9         });
          10     }
          11 }
          12 

          這里將/helloworld這個地址映射到HelloWorldServlet上。好吧,先寫個 “HelloWorld”的Servlet吧。

          1 @Singleton
          2 public class HelloWorldServlet extends HttpServlet{
          3     private static final long serialVersionUID = 1L;
          4     @Override
          5     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
          6             IOException {
          7      resp.getWriter().append("Hello, guice! "+new Date());
          8     }
          9 }

           

          注意,根據Guice的Servlet要求,每一個Servlet必須是單例的,因此這里強制加上@Singleton。

          好了,我們來看看輸出。

          image

           3.2 注入服務

           當然了,既然是一個IOC的容器,那么在Guice中也是可以注入服務的。

           首先定義一個服務。


          1 @ImplementedBy(HelloWorldImpl.class)
          2 public interface HelloWorld {
          3 
          4     void execute() throws IOException;
          5 }
          6 

          接著是服務的實現,注意在我們的服務中需要request和response對象,并且我們的服務假定是與request綁定的,采用@RequestScoped標簽來標識。


           1 @RequestScoped
           2 public class HelloWorldImpl implements HelloWorld {
           3 
           4     private HttpServletRequest request;
           5     private HttpServletResponse response;
           6     @Inject
           7     public HelloWorldImpl(HttpServletRequest request, HttpServletResponse response) {
           8         super();
           9         this.request = request;
          10         this.response = response;
          11     }
          12 
          13     public void execute() throws IOException{
          14         String name=request.getParameter("user");
          15         if(name==null||name.length()<1)name="Guest";
          16         response.getWriter().append(String.format("Hello, %s. %s -> sessionId=%s,hashCode=%d "n", name,new Date(),request.getSession().getId(),hashCode()));
          17     }
          18 
          19 }
          20 

           然后在我們的Servlet中可以采用如下實現。

           1 @Singleton
           2 public class HelloWorldServlet extends HttpServlet{
           3     private static final long serialVersionUID = 1L;
           4     @Inject
           5     private Injector inj;
           6     @Override
           7     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
           8             IOException {
           9      inj.getInstance(HelloWorld.class).execute();
          10      inj.getInstance(HelloWorld.class).execute();
          11     }
          12 }

          這里我們自動注入Injector對象,然后通過Inject對象獲取我們的服務,注意我們沒有將HttpServletRequest和HttpServletResponse手動注入到我們的服務中。

          好了,我們再來看看輸出。可以看到我們的對象是與request綁定,同一個request使用的同一個HelloWorld服務,不同的request那么是同一個session獲取的服務也是不一樣的。

          image

           老實說,Guice關于WEB的東西其實大概就這么多。其它的關于多規則匹配順序,正則表達式匹配等等其實不談也罷,都很弱,用處不大。

           3.3 整合Struts 2

          Guice可以與Struts 2整合,當然了理論上可以與其它MVC框架整合,只是Guice官方提供了一個Struts 2的插件。

          image 首先看看依賴的jar包,我們盡可能的少用jar包。

           aopalliance-1.0.jar是guice-servlet依賴的,因此guice需要aopalliance/guice/guice-servlet/guice-struts2-plugin等包,struts2啟動依賴commons-logging/freemarker/ognl/struts2-core/xwork等jar包。lo4j只是為了記錄日志方便而已。

          首先定義一個服務,服務很簡單輸出服務器的狀態。


          1 public interface Service {
          2 
          3     String getStatus();
          4 }
          5 

          1 public class ServiceImpl implements Service {
          2 
          3     public String getStatus() {
          4         return "I'am running.";
          5     }
          6 }
          7 

          然后寫一個Module綁定服務及其實現,當然如果偷懶可以使用@ImplementedBy,這里為了說明如果在配置文件中配置Module,所以單寫一個Module。

          1 public class ServiceModule implements Module {
          2     @Override
          3     public void configure(Binder binder) {
          4         binder.bind(Service.class).to(ServiceImpl.class);
          5     }
          6 }

           

          然后寫一個SessionScope級別的對象綁定訪問次數。


           1 @SessionScoped
           2 public class AccessCounter {
           3 
           4     private AtomicInteger count = new AtomicInteger(0);
           5 
           6     public int visit() {
           7         return count.incrementAndGet();
           8     }
           9 
          10     @Override
          11     public String toString() {
          12         return String.format("AccessCounter#%s:%d"this.hashCode(), count.get());
          13     }
          14 }
          15 

          好了,我們的Servlet出場了。


           1 package cn.imxylz.study.guice.web.struts2;
           2 
           3 import com.google.inject.Inject;
           4 
           5 public class AccessStatusAction {
           6 
           7   final AccessCounter counter;
           8   final Service service;
           9   String message;
          10 
          11   @Inject
          12   public AccessStatusAction(AccessCounter counter, Service service) {
          13     this.counter = counter;
          14     this.service = service;
          15   }
          16 
          17   public String execute() {
          18     return "success";
          19   }
          20 
          21   public int getCount() {
          22     return counter.visit();
          23   }
          24 
          25   public String getStatus() {
          26     return service.getStatus();
          27   }
          28 
          29   public String getMessage() {
          30     return message;
          31   }
          32 
          33   public void setMessage(String message) {
          34     this.message = message;
          35   }
          36 }
          37 

          可以看到我們很簡單的服務又被Guice給入侵了,所以說Guice對我們業務邏輯的侵入是很大,估計這也是很多程序員不愿意推廣Guice的一個原因吧。

          要寫的Java代碼就這么多,剩下的就是一堆的配置了。

          首先web.xml中配置struts2的filter,注意這里我們沒必要再配置一個guice的listener了,因為在guice的struts2的插件中已經配置一個ServletModule了。


           1 <?xml version="1.0" encoding="UTF-8"?>
           2 <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           3     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           4     version="2.5">
           5 
           6     <display-name>guice</display-name>
           7     <description>xylz study project - guice</description>
           8 
           9     <filter>
          10         <filter-name>guiceFilter</filter-name>
          11         <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
          12     </filter>
          13     <filter-mapping>
          14         <filter-name>guiceFilter</filter-name>
          15         <url-pattern>/*</url-pattern>
          16     </filter-mapping>
          17     <filter> 
          18         <filter-name>struts2</filter-name>
          19         <filter-class>org.apache.struts2.dispatcher.FilterDispatcher
          20         </filter-class>
          21     </filter>
          22     <filter-mapping>
          23         <filter-name>struts2</filter-name>
          24         <url-pattern>/*</url-pattern>
          25     </filter-mapping>
          26     <!-- listener>
          27         <listener-class>cn.imxylz.study.guice.web.MyGuiceServletContextListener</listener-class>
          28     </listener -->
          29 </web-app>
          30 

          下面該配置struts.xml了。


           1 <!DOCTYPE struts PUBLIC
           2     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
           3     "http://struts.apache.org/dtds/struts-2.0.dtd">
           4 
           5 <struts>
           6 
           7   <constant name="guice.module" value="cn.imxylz.study.guice.web.struts2.ServiceModule"/>
           8 
           9   <package name="default" extends="struts-default">
          10     <action name="access-status"
          11         class="cn.imxylz.study.guice.web.struts2.AccessStatusAction">
          12       <result>access-status.jsp</result>
          13     </action>     
          14   </package>
          15 
          16 </struts>
          17 

          在這里先配置我們的Module,我們的Module就是完成Guice的注入過程。在guice的Struts2插件中類com.google.inject.struts2.GuiceObjectFactory有以下邏輯:

          @Inject(value = "guice.module", required = false)
          void setModule(String moduleClassName) {
            
          try {
              
          // Instantiate user's module.
              @SuppressWarnings({"unchecked"})
              Class
          <? extends Module> moduleClass =
                  (Class
          <? extends Module>) Class.forName(moduleClassName);
              
          this.module = moduleClass.newInstance();
            } 
          catch (Exception e) {
              
          throw new RuntimeException(e);
            }
          }

           

          這段邏輯就是完成我們Module的注入過程。

          當然了我們需要配置一個Struts2的action類cn.imxylz.study.guice.web.struts2.AccessStatusAction,訪問地址access-status.action正確的時候渲染access-status.jsp頁面。


           1 <%@ taglib prefix="s" uri="/struts-tags" %>
           2 
           3 <html>
           4   <body>
           5     <h1>Access Status</h1>
           6     <h3><b>Access in this session:</b>
           7       <s:property value="count"/></h3>
           8 
           9     <h3><b>Status:</b>
          10       <s:property value="status"/></h3>
          11 
          12     <h3><b>Message:</b>
          13       <s:property value="message"/></h3>
          14       <h4><%="sessionId="+session.getId()%></h4>
          15   </body>
          16 </html>
          17 

          所有的工作就完成了,我們看看瀏覽器中的渲染結果。

          image

           即使如此,Guice整合Struts 2還是比較弱的。

          上一篇:Google Guice 入門教程05 - AOP(面向切面編程)

          下一篇:Google Guice 入門教程07 - 整合第三方組件(01)



          ©2009-2014 IMXYLZ |求賢若渴
          posted on 2009-12-27 22:58 imxylz 閱讀(16789) 評論(1)  編輯  收藏 所屬分類: J2EEGoogle Guice

          評論

          # re: Google Guice 入門教程06 – Web 和 Servlet 2010-01-14 20:45 ruanchao
          留個記號,查看。  回復  更多評論
            


          ©2009-2014 IMXYLZ
          主站蜘蛛池模板: 靖西县| 屏边| 建阳市| 中方县| 大丰市| 耿马| 黑河市| 米脂县| 山东省| 玉门市| 布尔津县| 贵溪市| 高尔夫| 伊金霍洛旗| 德化县| 桐柏县| 石河子市| 荃湾区| 泰兴市| 武夷山市| 沾化县| 兴义市| 安义县| 海晏县| 菏泽市| 衢州市| 三都| 珠海市| 正镶白旗| 潞西市| 铁岭县| 克拉玛依市| 东城区| 鄂伦春自治旗| 德令哈市| 恭城| 昌黎县| 新沂市| 上饶县| 宣威市| 湘西|