• Google Guice入门教程06Web & Servlet


    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的模块注入。

    public class MyGuiceServletContextListener extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
    return Guice.createInjector(new ServletModule());
    }
    }

    继续在web.xml中添加东西。

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

    显然我们需要将某个PATH映射到一个Servlet上,于是需要在ServletModule上做点事情。

    public class MyGuiceServletContextListener extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
    return Guice.createInjector(new ServletModule() {
    protected void configureServlets() {
    serve(“/helloworld”).with(HelloWorldServlet.class);
    }
    });
    }
    }

    这里将/helloworld这个地址映射到HelloWorldServlet上。好吧,先写个 “HelloWorld”的Servlet吧。

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

    注意,根据Guice的Servlet要求,每一个Servlet必须是单例的,因此这里强制加上@Singleton。

    好了,我们来看看输出。

    image

    3.2 注入服务

    当然了,既然是一个IOC的容器,那么在Guice中也是可以注入服务的。

    首先定义一个服务。

    @ImplementedBy(HelloWorldImpl.class)
    public interface HelloWorld {

    void execute() throws IOException;
    }

    接着是服务的实现,注意在我们的服务中需要request和response对象,并且我们的服务假定是与request绑定的,采用@RequestScoped标签来标识。

    @RequestScoped
    public class HelloWorldImpl implements HelloWorld {

    private HttpServletRequest request;
    private HttpServletResponse response;
    @Inject
    public HelloWorldImpl(HttpServletRequest request, HttpServletResponse response) {
    super();
    this.request = request;
    this.response = response;
    }

    public void execute() throws IOException{
    String name=request.getParameter(“user”);
    if(name==null||name.length()<1)name=”Guest”;
    response.getWriter().append(String.format(“Hello, %s. %s -> sessionId=%s,hashCode=%d \n”, name,new Date(),request.getSession().getId(),hashCode()));
    }

    }

    然后在我们的Servlet中可以采用如下实现。

    @Singleton
    public class HelloWorldServlet extends HttpServlet{
    private static final long serialVersionUID = 1L;
    @Inject
    private Injector inj;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
    IOException {
    inj.getInstance(HelloWorld.class).execute();
    inj.getInstance(HelloWorld.class).execute();
    }
    }

    这里我们自动注入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只是为了记录日志方便而已。

    首先定义一个服务,服务很简单输出服务器的状态。

    public interface Service {

    String getStatus();
    }

    public class ServiceImpl implements Service {

    public String getStatus() {
    return “I’am running.”;
    }
    }

    然后写一个Module绑定服务及其实现,当然如果偷懒可以使用@ImplementedBy,这里为了说明如果在配置文件中配置Module,所以单写一个Module。

    public class ServiceModule implements Module {
    @Override
    public void configure(Binder binder) {
    binder.bind(Service.class).to(ServiceImpl.class);
    }
    }

    然后写一个SessionScope级别的对象绑定访问次数。

    @SessionScoped
    public class AccessCounter {

    private AtomicInteger count = new AtomicInteger(0);

    public int visit() {
    return count.incrementAndGet();
    }

    @Override
    public String toString() {
    return String.format(“AccessCounter#%s:%d”, this.hashCode(), count.get());
    }
    }

    好了,我们的Servlet出场了。

    package cn.imxylz.study.guice.web.struts2;

    import com.google.inject.Inject;

    public class AccessStatusAction {

    final AccessCounter counter;
    final Service service;
    String message;

    @Inject
    public AccessStatusAction(AccessCounter counter, Service service) {
    this.counter = counter;
    this.service = service;
    }

    public String execute() {
    return “success”;
    }

    public int getCount() {
    return counter.visit();
    }

    public String getStatus() {
    return service.getStatus();
    }

    public String getMessage() {
    return message;
    }

    public void setMessage(String message) {
    this.message = message;
    }
    }

    可以看到我们很简单的服务又被Guice给入侵了,所以说Guice对我们业务逻辑的侵入是很大,估计这也是很多程序员不愿意推广Guice的一个原因吧。

    要写的Java代码就这么多,剩下的就是一堆的配置了。

    首先web.xml中配置struts2的filter,注意这里我们没必要再配置一个guice的listener了,因为在guice的struts2的插件中已经配置一个ServletModule了。

    <?xml version=”1.0″ encoding=”UTF-8″?>
    <web-app xmlns=”http://java.sun.com/xml/ns/javaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
    xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd”
    version=”2.5″>

    <display-name>guice</display-name>
    <description>xylz study project – guice</description>

    <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>
    <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher
    </filter-class>
    </filter>
    <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!– listener>
    <listener-class>cn.imxylz.study.guice.web.MyGuiceServletContextListener</listener-class>
    </listener –>
    </web-app>

    下面该配置struts.xml了。

    <!DOCTYPE struts PUBLIC
    “-//Apache Software Foundation//DTD Struts Configuration 2.0//EN”
    http://struts.apache.org/dtds/struts-2.0.dtd”>

    <struts>

    <constant name=”guice.module” value=”cn.imxylz.study.guice.web.struts2.ServiceModule”/>

    <package name=”default” extends=”struts-default”>
    <action name=”access-status”
    class=”cn.imxylz.study.guice.web.struts2.AccessStatusAction”>
    <result>access-status.jsp</result>
    </action>
    </package>

    </struts>

    在这里先配置我们的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页面。

    <%@ taglib prefix=”s” uri=”/struts-tags” %>

    <html>
    <body>
    <h1>Access Status</h1>
    <h3><b>Access in this session:</b>
    <s:property value=”count”/></h3>

    <h3><b>Status:</b>
    <s:property value=”status”/></h3>

    <h3><b>Message:</b>
    <s:property value=”message”/></h3>
    <h4><%=”sessionId=”+session.getId()%></h4>
    </body>
    </html>

    所有的工作就完成了,我们看看浏览器中的渲染结果。

    image

    即使如此,Guice整合Struts 2还是比较弱的。

  • 相关阅读:
    Android推送通知指南
    proteus ISIS学习笔记
    总结ACM 中的基本输入输出
    WINDOWS远程默认端口3389的正确修改方式
    SQL还原数据库后孤立用户问题处理(SQL 数据库 拥有对象 无法删除)
    利用计划任务定时备份Express2005数据库
    使用 bcompiler 给PHP代码加密编译
    Discuz X2.5 编辑DIY数据出现:Unknown column 'pid' in 'where clause' 的解决办法
    批处理解决SqlServer自动备份与自动清理7天以前的备份
    PHP去除全角空格与空白字符
  • 原文地址:https://www.cnblogs.com/kevinhigher/p/2180744.html
Copyright © 2020-2023  润新知