通过上篇文章,我们已经对Java反射机制有了方方面面的了解,接下来结合前面的几篇内容来进一步实现我们自己的框架。
打开Eclipse,创建一个动态的web工程,结构如下:
第一步:创建URLFilter
package com.demo.filter;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet Filter implementation class URLFilter
*/
@WebFilter("/URLFilter")
public class URLFilter implements Filter {
/**
* Default constructor.
*/
public URLFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse rep = (HttpServletResponse) response;
String realPath = req.getServletContext().getRealPath("/");
String uri = req.getRequestURI();
System.out.println("Filter uri=====" + uri);
File file = new File(realPath + uri);
if (!file.exists() && !file.isDirectory()) {
String url = req.getRequestURL().toString();
System.out.println("Filter url=====" + url);
String rewriteUrl = "/index"; //默认入口
rewriteUrl += "?" + uri.trim();
System.out.println("Filter rewriteUrl=====" + rewriteUrl);
String query = req.getQueryString();
if (query != null) {
query = query.toString();
System.out.println("Filter query=====" + query);
rewriteUrl += "?" + query;
}
System.out.println("Filter rewriteUrl=====" + rewriteUrl);
if (null != rewriteUrl) {
request.getRequestDispatcher(rewriteUrl).forward(req, rep);
return;
}
}
// pass the request along the filter chain
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
这个代码主要过滤所有的请求连接,如果请求的是资源文件等,则直接返回内容,如果不是则进入我们的默认入口(/index)servlet,对接下来的内容进行封装显示。
第二步:配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Demo</display-name>
<welcome-file-list>
<welcome-file>index</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>urlFilter</filter-name>
<filter-class>com.demo.filter.URLFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>urlFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
第三步:创建入口servlet
package com.demo.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class index
*/
@WebServlet("/index")
public class index extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public index() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
/**
* @see Servlet#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Servlet#getServletConfig()
*/
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
/**
* @see Servlet#getServletInfo()
*/
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
String className = "index";
String methodName = "index";
if (request.getQueryString() != null) {
System.out.println("url ==== " + request.getRequestURL().toString());
System.out.println("uri ==== " + request.getRequestURI());
System.out.println("query ==== " + request.getQueryString().toString());
String query = request.getQueryString().toString();
String[] queryArr = query.split("\\?");
System.out.println("router to ===" + queryArr[0]);
String[] calssInfo = queryArr[0].trim().split("\\/");
if (calssInfo.length > 1) {
className = calssInfo[1].replaceAll("\\/", "").trim();
// 首字母大写
className = className.replaceFirst(className.substring(0, 1), className.substring(0, 1).toUpperCase());
System.out.println("class===" + calssInfo[1]);
}
if (calssInfo.length > 2) {
methodName = calssInfo[2].replaceAll("\\/", "").trim();
System.out.println("action===" + methodName);
}
}
try {
Class<?> c = Class.forName("com.demo.contorller." + className);
Class[] parameterTypes = { HttpServletRequest.class, HttpServletResponse.class };
Constructor<?> constructor = c.getConstructor(parameterTypes);
Object[] parameters = { request, response };
Object obj = constructor.newInstance(parameters);
Method method = c.getMethod(methodName + "Action", null);
method.invoke(obj, null);
} catch (Exception e) {
// TODO Auto-generated catch block
// e.printStackTrace();
// response.sendError(404);
response.setStatus(404);
PrintWriter out = response.getWriter();
out.println("404 Page Not Found!");
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
/**
* @see HttpServlet#doPut(HttpServletRequest, HttpServletResponse)
*/
protected void doPut(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doDelete(HttpServletRequest, HttpServletResponse)
*/
protected void doDelete(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doHead(HttpServletRequest, HttpServletResponse)
*/
protected void doHead(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doOptions(HttpServletRequest, HttpServletResponse)
*/
protected void doOptions(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doTrace(HttpServletRequest, HttpServletResponse)
*/
protected void doTrace(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
这里是关键代码,用到了java的反射机制,并传了两个关键的对象:HttpServletRequest, HttpServletResponse
Class<?> c = Class.forName("com.demo.contorller." + className);
Class[] parameterTypes = { HttpServletRequest.class, HttpServletResponse.class };
Constructor<?> constructor = c.getConstructor(parameterTypes);
Object[] parameters = { request, response };
Object obj = constructor.newInstance(parameters);
Method method = c.getMethod(methodName + "Action", null);
method.invoke(obj, null);
如果类没有找到,我们就捕获异常,并返回404页面
response.setStatus(404);
PrintWriter out = response.getWriter();
out.println("404 Page Not Found!");
第四步:创建Contorller基类
package com.demo.contorller;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Contorller {
String output = "";
public HttpServletRequest request;
public HttpServletResponse response;
public Contorller(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
}
public void load(String fileName) {
String realPath = request.getServletContext().getRealPath("/");
File file = new File(realPath + fileName);
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String tempString = "";
while ((tempString = reader.readLine()) != null) {
output += tempString + "\t\n";
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
}
public void display() throws IOException {
PrintWriter out = response.getWriter();
request.getServletContext();
out.println(output);
out.flush();
out.close();
}
}
第五步:实现我们自己的Contorller
package com.demo.contorller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Hello extends Contorller {
public Hello(HttpServletRequest request, HttpServletResponse response) {
super(request, response);
// TODO Auto-generated constructor stub
}
public void indexAction() throws IOException
{
PrintWriter out = response.getWriter();
out.println("This is index");
out.flush();
out.close();
}
public void worldAction() throws IOException
{
PrintWriter out = response.getWriter();
out.println("Hello world!");
out.flush();
out.close();
System.out.println("Hello world!");
}
public void homeAction() throws IOException
{
this.load("home.html");
this.display();
}
}
第六步:设置服务配置server.xml
主要是两个地方:一个端口号
<Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/>
一个文件地址
<Context docBase="Demo" path="/" reloadable="true" source="org.eclipse.jst.jee.server:Demo"/>
启动服务,在浏览器中输入http://localhost/hello/world 或 http://127.0.0.1/hello/world
我也不例外的用了这个 hellow world,你懂得。
看到页面返回了“Hello world”,通过该链接,我们访问到了com.demo.contorller下面的Hello的worldAction方法
如果随便输入一个地址我们会看到如下页面:会看到404页面,因为在com.demo.contorller下面没有找到相关的类home,程序抛出了异常,并被捕获到了。
到这里,我们的框架已经有了一个雏形了,但他很简陋,还需要增加更多的功能,比如:依赖,容器、ORM、 路由、事件,队列、 缓存、日志等等,往后会逐步来实现这些功能。
如果你感觉本文对你有帮助,你可以继续关注我的博客,我会一步一步把框架实现。
这个路还很长很长,非常希望能和大家一起交流,共同学习和进步。大家看过后觉得有启发的话可以顶一下这篇文章,让更多的朋友有机会看到它。也希望大家可以多留言来和我探讨框架相关的问题和知识。
最后,谢谢大家的支持!~~~