上篇博客中我们建立了一个注解类C
和一个使用者类DemoC
,还记得DemoC
类中的helloString()
方法吗?对,你们猜的不错,接下来我们要做的就是访问DemoC
的helloString
方法。
在普通的Servlet中,要请求到服务端,服务端必需做一些Servlet让我们做的工作:编写Servlet子类并注册它。即使Spring/Struts这样的框架也得按套路出牌,因为它们都是对Servlet的封装。当然,我们也不例外。额外说一点的是,Spring在web.xml中注册的是Servlet,而Struts2在web.xml中注册的是Filter。我们采用Servlet方式。
我们新建一个Servlet,名为TransServlet
,按照约定,它应该在包com.billy.jee.framework.servlet
下,即它的全限定名是
com.billy.jee.framework.servlet.TransServlet
它的初始代码如下:
package com.billy.jee.framework.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TransServlet extends HttpServlet { /** */ private static final long serialVersionUID = 8719005417117579209L; @Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { System.out.print(System.currentTimeMillis()); }}
需要注意的是,我们并没有重写doGet()
或doPost()
方法而是直接重写了service()
方法,因为一个请求是先到达service()方法,处理后再分发到相应的方法如doGet()、doPost()、doPut()、doHead()、doTrace()等方法。 我们在service()方法里输出当前时间毫秒数,仅此而已。
接着我们就在把这个TransServlet注册到web.xml中,代码如下:
transServlet com.billy.jee.framework.servlet.TransServlet transServlet *.ts
从配置中可以看到,我们注册了TransServlet并将它的servlet-name配置成transServlet,并将请求路径配置成*.ts。
配置完成之后,我们就要访问这个服务端应用了。我们可以使用tomcat或Resin或GlassFish来部署这个web工程,为方便测试与调试,我在此处选择了jetty。
要使用jetty,我们需要在pom.xml中做一些配置。请回顾一下博客四中的pom.xml文件,我们在dependencies
节点下添加了两个依赖dependency
(依赖可以理解成classpath下的jar包),即junit和servlet-api,这里我们添加jetty的依赖,如下(请确保如下代码在dependencies节点下):
org.eclipse.jetty.aggregate jetty-all-server 7.6.1.v20120215 org.eclipse.jetty jetty-jsp 7.6.1.v20120215
此处我们要添加一个JettyServerStart工具类,代码较长,如下:
package com.billy.jee.framework.util;import java.io.File;import java.io.IOException;import java.lang.management.ManagementFactory;import java.net.DatagramSocket;import java.net.ServerSocket;import java.util.ArrayList;import java.util.List;import javax.management.MBeanServer;import org.eclipse.jetty.jmx.MBeanContainer;import org.eclipse.jetty.server.Handler;import org.eclipse.jetty.server.Server;import org.eclipse.jetty.util.Scanner;import org.eclipse.jetty.webapp.WebAppContext;public class JettyServerStart { private int port; private String context; private String webappPath; private int scanIntervalSeconds; private boolean jmxEnabled; private Server server; private WebAppContext webapp; public JettyServerStart(String webappPath, int port, String context) { this(webappPath, port, context, 0, false); } public JettyServerStart(String webappPath, int port, String context, int scanIntervalSeconds, boolean jmxEnabled) { this.webappPath = webappPath; this.port = port; this.context = context; this.scanIntervalSeconds = scanIntervalSeconds; this.jmxEnabled = jmxEnabled; validateConfig(); } private void validateConfig() { if (port < 0 || port > 65536) { throw new IllegalArgumentException("Invalid port of web server: " + port); } if (context == null) { throw new IllegalStateException("Invalid context of web server: " + context); } if (webappPath == null) { throw new IllegalStateException("Invalid context of web server: " + webappPath); } } public void start() { if (server == null || server.isStopped()) { try { doStart(); } catch (Throwable e) { e.printStackTrace(); System.err.println("System.exit() ......"); System.exit(1); } } else { throw new RuntimeException("Jetty Server already started."); } } private void doStart() throws Throwable { if (!portAvailable(port)) { throw new IllegalStateException("port: " + port + " already in use!"); } System.setProperty("org.eclipse.jetty.util.URI.charset", "UTF-8"); System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.Slf4jLog"); System.setProperty("org.eclipse.jetty.server.Request.maxFormContentSize", "20000000"); server = new Server(port); server.setHandler(getHandler()); if (jmxEnabled) { MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer); server.addBean(mBeanContainer); } if (scanIntervalSeconds > 0) { startFileWatchScanner(); } long ts = System.currentTimeMillis(); server.start(); ts = System.currentTimeMillis() - ts; System.err.println("Jetty Server started: " + String.format("%.2f sec", ts / 1000d)); server.join(); } protected Handler getHandler(){ webapp = new WebAppContext(webappPath, context); return webapp; } private void startFileWatchScanner() throws Exception { ListscanList = new ArrayList (); scanList.add(new File(webappPath, "WEB-INF")); Scanner scanner = new Scanner(); scanner.setReportExistingFilesOnStartup(false); scanner.setScanInterval(scanIntervalSeconds); scanner.setScanDirs(scanList); scanner.addListener(new Scanner.BulkListener() { @SuppressWarnings("rawtypes") public void filesChanged(List changes) { try { System.err.println("Loading changes ......"); webapp.stop(); webapp.start(); System.err.println("Loading complete.\n"); } catch (Exception e) { System.err.println("Error reconfiguring/restarting webapp after change in watched files"); e.printStackTrace(); } } }); System.err.println("Starting scanner at interval of " + scanIntervalSeconds + " seconds."); scanner.start(); } private static boolean portAvailable(int port) { if (port <= 0) { throw new IllegalArgumentException("Invalid start port: " + port); } ServerSocket ss = null; DatagramSocket ds = null; try { ss = new ServerSocket(port); ss.setReuseAddress(true); ds = new DatagramSocket(port); ds.setReuseAddress(true); return true; } catch (IOException e) { } finally { if (ds != null) { ds.close(); } if (ss != null) try { ss.close(); } catch (IOException e) { } } return false; } public static void main(String[] args) { String webapp = "D:/haocheng/workspace/com.cheng.spring.mvc.test/src/main/webapp"; new JettyServerStart(webapp, 8080, "/").start(); }}
工具类有了,接下来就是要调用工具类来让我们使用,与JettyServerStart
相比,JettyStarterTest
就很精简了。代码如下(请注意包名,该类是测试类,在src/test/java目录下,不在src/main/java下):
package test.billy.jee.framework.util.JettyServerStart;import com.billy.jee.framework.util.JettyServerStart;public class JettyStarterTest { public static void main(String[] args) { String webapp = "src/main/webapp"; int port = 2016; new JettyServerStart(webapp, port, "/webby").start(); }}
对!你没有看错,这就是个java程序,右键Run As Java Application就能启动该类,这时候在地址栏里输入http://127.0.0.1:2016/webby
即可访问到该项目。
需要注意的是,若你使用Eclipse或MyEclipse作为ide的话,上面的启动类的代码不用改变,但当你使用idea开发的话,请将webapp变量赋值为"项目名/src/main/webapp"即可。
右键项目Run As Maven install即可将项目安装到本地仓库,接着执行JettyStarterTest类启动服务,然后在地址栏项目名的基础上随便输入一个地址如http://127.0.0.1:2016/webby/aaaa.ts
,可以看到控制台打印出了系统当前时间毫秒数。也说明aaaa.ts是能请求到TransServlet的service()方法中的。
接着我们就要在TransServlet中进行调用DemoC的helloString()方法了。
我们将打印语句注释掉,并在其下添加如下代码:
DemoC demoC = new DemoC();demoC.helloString("这是DemoC");
重新启动服务,我们同样访问http://127.0.0.1:2016/webby/aaaa.ts
,看到后台的输出了吗?
param hello: 这是DemoC
我们确实调用了DemoC这个类的helloString()方法了。可以也遗留了几个问题:
- 我们把地址
- helloString()的参数是固定的,不能改变。
这两个问题其实也是一个问题,我们最终想要的结果可能是——
我在地址栏输出
http://127.0.0.1:2016/webby/demo/helloString.ts?hello=这是DemoC吗
,系统应该能定位到DemoC类的helloString()方法,并将参数hello传入。
这一个问题,或称两个问题我们下篇博客中会给出解决方案。