import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/**
* servlet自封装
* @author
* @date 20110323
*/
public class Action extends HttpServlet{ private static final long serialVersionUID = -6716601164831968512L;
//访问Action时可以省略的包路径
private String servletPackage;
//Action返回jsp时可以省略的路径
private String jspPath;
//发生错误时返回页
private String errorPage; protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//访问的方法名
String methodName = request.getParameter("method");
String uri = request.getRequestURI();
//访问的Action名
String className = uri.substring(1,uri.length()-3);
if(className.startsWith("jsp/") || className.startsWith("/")){
className = className.substring(className.lastIndexOf('/') + 1);
}
if(!className.startsWith(servletPackage)){
className = servletPackage + "." + className;
}
try {
Class clazz = Class.forName(className);
Method method = clazz.getDeclaredMethod(methodName,new Class[]{HttpServletRequest.class,HttpServletResponse.class});
Object forward = method.invoke(clazz.newInstance(), new Object[]{request,response});
if(forward == null){
return;
}else{
String forwardStr = forward.toString();
if(!forwardStr.startsWith("/")){
forwardStr = "/" + forwardStr;
}
if(!forwardStr.startsWith(jspPath)){
if(!forwardStr.startsWith("/jsp/face") && !forwardStr.startsWith("/jsp/login.jsp")){
forwardStr = jspPath + forwardStr;
}
}
String realPath = request.getSession().getServletContext().getRealPath(forwardStr);
boolean exists = new File(realPath).exists();
if(exists){
request.getRequestDispatcher(forwardStr).forward(request, response);
}else{
request.setAttribute("msg", "404,你懂的,未找到"+forwardStr);
request.getRequestDispatcher(errorPage).forward(request, response);
}
}
} catch (ClassNotFoundException e) {
request.setAttribute("msg", "404,你懂的,未找到"+className+"类");
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (SecurityException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (NoSuchMethodException e) {
request.setAttribute("msg", "未在" + className + "中找到" + methodName + "方法,或者该方法的参数不是HttpServletRequest和HttpServletResponse");
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (IllegalArgumentException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (IllegalAccessException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (InvocationTargetException e) {
//反射的Action抛出的异常
request.setAttribute("msg", e.getCause());
request.setAttribute("stackTrace", e.getCause().getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (InstantiationException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
}
} public void destroy() {
super.destroy();
} public void init() throws ServletException {
servletPackage = getServletConfig().getInitParameter("servletPackage");
jspPath = getServletConfig().getInitParameter("jspPath");
if(!jspPath.startsWith("/")){
jspPath = "/" + jspPath;
}
errorPage = getServletConfig().getInitParameter("errorPage");
super.init();
}
}
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/**
* servlet自封装
* @author
* @date 20110323
*/
public class Action extends HttpServlet{ private static final long serialVersionUID = -6716601164831968512L;
//访问Action时可以省略的包路径
private String servletPackage;
//Action返回jsp时可以省略的路径
private String jspPath;
//发生错误时返回页
private String errorPage; protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
} protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//访问的方法名
String methodName = request.getParameter("method");
String uri = request.getRequestURI();
//访问的Action名
String className = uri.substring(1,uri.length()-3);
if(className.startsWith("jsp/") || className.startsWith("/")){
className = className.substring(className.lastIndexOf('/') + 1);
}
if(!className.startsWith(servletPackage)){
className = servletPackage + "." + className;
}
try {
Class clazz = Class.forName(className);
Method method = clazz.getDeclaredMethod(methodName,new Class[]{HttpServletRequest.class,HttpServletResponse.class});
Object forward = method.invoke(clazz.newInstance(), new Object[]{request,response});
if(forward == null){
return;
}else{
String forwardStr = forward.toString();
if(!forwardStr.startsWith("/")){
forwardStr = "/" + forwardStr;
}
if(!forwardStr.startsWith(jspPath)){
if(!forwardStr.startsWith("/jsp/face") && !forwardStr.startsWith("/jsp/login.jsp")){
forwardStr = jspPath + forwardStr;
}
}
String realPath = request.getSession().getServletContext().getRealPath(forwardStr);
boolean exists = new File(realPath).exists();
if(exists){
request.getRequestDispatcher(forwardStr).forward(request, response);
}else{
request.setAttribute("msg", "404,你懂的,未找到"+forwardStr);
request.getRequestDispatcher(errorPage).forward(request, response);
}
}
} catch (ClassNotFoundException e) {
request.setAttribute("msg", "404,你懂的,未找到"+className+"类");
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (SecurityException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (NoSuchMethodException e) {
request.setAttribute("msg", "未在" + className + "中找到" + methodName + "方法,或者该方法的参数不是HttpServletRequest和HttpServletResponse");
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (IllegalArgumentException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (IllegalAccessException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (InvocationTargetException e) {
//反射的Action抛出的异常
request.setAttribute("msg", e.getCause());
request.setAttribute("stackTrace", e.getCause().getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
} catch (InstantiationException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("stackTrace", e.getStackTrace());
request.getRequestDispatcher(errorPage).forward(request, response);
}
} public void destroy() {
super.destroy();
} public void init() throws ServletException {
servletPackage = getServletConfig().getInitParameter("servletPackage");
jspPath = getServletConfig().getInitParameter("jspPath");
if(!jspPath.startsWith("/")){
jspPath = "/" + jspPath;
}
errorPage = getServletConfig().getInitParameter("errorPage");
super.init();
}
}
request.setAttribute("msg", "404,你懂的,未找到"+className+"类");
万恶的C S D N
2。有没有考虑是forward还是redirect?或者ajax??
3。出错提示太露骨。。要是用户访问了你一个不存在的action 那你会怎么提示:404,你懂的,未找到"+className+"类" 而且,楼主,你这思想是从struts1里面学过来吧?? 不过总的来说敢于自己写就是不错的。。敢于分享就是更好,只有分享,大家不断提建议,慢慢才会更好。
把类名方法名参数直接暴露在URL中。
我技术不是很好,所以也不知道forward还是redirect的区别,因为forward能在request里面放参数,所以一直用forward。
关于ajax这个时能实现的,只要自定义的方法返回void就行。却是安全方面没考虑 谢谢指正!!
既然你知道reflect、IO,为什么不跑类名、包名这些东西配置到properties、xml文件中
而且不必暴露在url上
import java.util.regex.Pattern;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;/**
* 拦截所有 Action 的 Servlet。此 Servlet 接到 Action 请求时,将根椐 URI 路径来确定具体实例化哪个 Action 实例,并调用 Action 实例的 execute() 方法。
* @author 林俊海(<a href='http://www.ialvin.cn' target="_blank"><b>ialvin.cn</b></a>) 广东 普宁 里湖
*/
@SuppressWarnings("serial")
public class Servlet extends HttpServlet {
private static final Log log = LogFactory.getLog(Servlet.class);
/**
* 保存记录的 ServletContext 对象
*/
private ServletContext application = null;
/**
* 所有 Action 类的基本包路径。
* 这个路径可以在 Servlet 的配置中,由 "serversPackage" 参数所指定
*/
private String servicesPackage = ""; /**
* 本方法会从 Servlet 配置中,获取 Servlet 参数 "serverPackage"<br/>
* 以方便用后在响应客户端请求时,"serverPackage" 参数指定的包中加载 Action 类以及实例。
*/
public void init() throws ServletException {
super.init();
this.application = this.getServletContext();
String serversPackage = this.getInitParamTrim("servicesPackage");
if (!"".equals(serversPackage))
this.servicesPackage = servicesPackage + ".";
}
/**
* 根据 URI 中请求的 Action 路径,以及基本 Action 包路径,加载一个 Action 类<br/>
* 如果不存在相应的 Action 类,将返回 null;
* @param className
* @return
*/
@SuppressWarnings("unchecked")
private Class<IAction> findClass(String className) {
try {
return (Class<IAction>)Class.forName(servicesPackage + className);
} catch (ClassNotFoundException e) {
return null;
}
}
/**
* 本方法将根据客户端请求此 Servlet 时的 URI 来判定所请求的 Action<br/>
* 方法中实现了对 Action 的加载和实例化,调用 Action 实例的特定方法。如:<br/>
* init()、execute()、destory() 等。
*/
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String actionPath = request.getServletPath();
final Pattern transformRegExp = Pattern.compile("^/|\\.[^.]+$");
actionPath = transformRegExp.matcher(actionPath).replaceAll("");
actionPath = actionPath.replace('/', '.'); // IAction 是个接口, action 必须实现这个接口
Class<IAction> cls = null;
if (null == (cls=this.findClass(actionPath))) {
response.sendError(404, "Action Not Found.");
return;
}
if (IAction.class.isAssignableFrom(cls)) {
response.sendError(404, "Action Not Found.");
return;
} IAction action = null;
try {
action = (IAction)cls.newInstance();
action.init(this, application, request, response);
action.beforeExecute();
action.execute();
} catch (RuntimeException e) {
Servlet.log.error("Action Runtime Exception", e);
response.sendError(500, "Server Error.");
} catch (Exception e) {
Servlet.log.error("Action Exception", e);
response.sendError(500, "Server Error.");
} finally {
if (action != null) action.destroy();
}
} /**
* 从 Servlet 配置中获取一个指定的参数
* @param name 指定的参数的名称
* @return String 内容的参数值,并且参数值已经去首尾空白字符。如果没有配置则返回空串""
*/
private String getInitParamTrim(String name) {
if (null == name) return "";
String value = this.getInitParameter(name);
if (null == value) return "";
return value.trim();
}
}package cn.ialvin.web;import java.io.IOException;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/**
* 定义 Action 类所必须实现的接口。
* @author 林俊海(<a href='http://www.ialvin.cn' target="_blank"><b>ialvin.cn</b></a>) 广东 普宁 里湖
*/
public interface IAction {
/**
* 用于 ActionServlet 在得到 Action 实例后,对该 Action 的初始化
* @param svl cn.ialvin.web.Servlet 的实例
* @param app 当前应用上下文对象
* @param request 客户端请求对象
* @param response 服务端响应对象
* @throws ServletException
* @throws IOException
*/
public void init(
Servlet svl,
ServletContext app,
HttpServletRequest request,
HttpServletResponse response
) throws ServletException, IOException; /**
* 实例所实现的 beforeExecute() 方法将会在 execute() 方法执行之前被执行
* @throws ServletException
* @throws IOException
*/
public void beforeExecute() throws ServletException, IOException;
/**
* 实例如对请求的具体响应方法。
* @throws ServletException
* @throws IOException
*/
public void execute() throws ServletException, IOException;
/**
* destory() 将会在响应完毕被调用,一些需要做善后处理的事情,应该在此方法中实现
* @throws ServletException
* @throws IOException
*/
public void destroy() throws ServletException, IOException;
}
package cn.ialvin.web;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/**
* 一个 Action 的基本模型,其中实现了部分 IAction 方法。<br>
* 未实现 IAction 中的 execute() 方法,此方法将由子类各自实现。<br>
* 类中并提供了多个常用方法,供子类使用。
* @author 林俊海(<a href='http://www.ialvin.cn' target="_blank"><b>ialvin.cn</b></a>) 广东 普宁 里湖
*/
public abstract class Action implements IAction {
/**
* cn.ialvin.web.Servlet 实例
*/
protected Servlet servlet = null;
/**
* ServletContext 对象,通称 application
*/
protected ServletContext application = null;
protected HttpServletRequest request = null;
protected HttpServletResponse response = null;
protected PrintWriter out = null; /**
* 此方法已被设置成 final 不可重写,主要用于 Action 实例在创建后<br>
* 由 cn.ialvin.web.Servlet 调用,对实例进行初始化。
*/
final public void init(Servlet servlet, ServletContext application,
HttpServletRequest request,
HttpServletResponse response) throws IOException {
this.servlet = servlet;
this.application = application;
this.request = request;
this.response = response;
} /**
* 方法中,对响应进行一些预处理<br>
* 如:设置请求的字符集编码,响应的 ContentType 等.<br>
* 子类可以对其进行重写
*/
public void beforeExecute() throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("ContentType", "text/html; charset=UTF-8");
response.setContentType("text/html; charset=utf-8");
this.out = this.getWriter();
}
/**
* 方法中默认对响应流进行关闭<br>
* 子类可以重写其实现内容
*/
public void destroy() throws ServletException, IOException {
if (null != out) {
out.flush();
out.close();
}
} /**
* 对字符串进行 HTML 实体编码<br>
* 如:encodeHTML("><&\"'") 得到 "><&"'"
* @param s 要编码的字符串
* @see cn.ialvin.web.Encoder#encodeHTML(String)
*/
protected String encodeHTML(String s) { return Encoder.encodeHTML(s); } /**
* 对字符串进行 URI 编码<br>
* 如:encodeURI("林俊海") 得到 "%E6%9E%97%E4%BF%8A%E6%B5%B7"
* @param s 要编码的字符串
* @see cn.ialvin.web.Encoder#encodeURIComponent(String)
*/
protected String encodeURI(String s) { return Encoder.encodeURIComponent(s); } /**
* 对字符串进行 escape 编码<br>
* 如:escape("林俊海") 得到 "%u6797%u4FCA%u6D77"
* @param s 要编码的字符串
* @see cn.ialvin.web.Encoder#escape(String)
*/
protected String escape(String s) { return Encoder.escape(s); } /**
* 获取响应流
* @return 响应流
*/
protected PrintWriter getWriter() {
if (null != out) return out;
try {
return this.response.getWriter();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 向客户端打印
* @param x 要输出的内容
*/
protected void w(Object x) {
if (x == null) return;
if (null == out) out = this.getWriter();
out.print(x.toString());
}
/**
* 向客户端打印一行
* @param x 要输出的内容
*/
protected void wln(Object x) { this.w(x); this.w("\r\n"); }
/**
* 向客户端输出脚本
* @param js 要输出的 javascript 代码
*/
protected void wScript(String js) {
this.wln("<script type=\"text/JavaScript\">//<![CDATA[");
this.wln(js);
this.wln("//]]></script>");
}
/**
* 向客户端输出 javascript 以让浏览器弹出消息框
* @param msg 要在客户端弹出的消息内容
*/
protected void alert(String msg) {
this.wScript("alert(unescape(\"" + this.escape(msg) + "\"));");
}
/**
* 向客户端输出 javascript 以让浏览器重定向并替换当前页面浏览历史记录
* @param target 重定向的目标路径
*/
protected void replace(String target) {
this.wScript("window.location.replace(unescape(\"" + this.escape(target) + "\"));");
}
/**
* 向客户端输出 javascript 以让浏览器执行后退操作
*/
protected void back() {
this.wScript("window.history.go(-1);");
}
/**
* 获取一个请求参数
* @param x 要获取的参数名称
* @return 获取的参数值
*/
protected String getParameter(String x) {
if (request == null) return "";
String v = request.getParameter(x);
return ((null == v) ? "" : v);
}
/**
* 获取一个请求参数,并将其首尾空白符号去掉
* @param x 要获取的参数名称
* @return 获取的参数值
*/
protected String getParamTrim(String x) {
return this.getParameter(x).trim(); //去字符串首尾空白字符
}
/**
* 获取一个浮点型的请求参数
* @param x 要获取的参数名称
* @return 获得的浮点数值
* @throws Exception 提交参数格式不合法时抛出
*/
protected double getDoubleParameter(String x) throws Exception {
double v = Double.parseDouble(this.getParamTrim(x));
if (Double.isNaN(v)) throw new Exception();
return v;
}
/**
* 获取一个整型的请求参数
* @param x 要获取的参数名称
* @return 获得的整数值
* @throws Exception 提交参数格式不合法时抛出
*/
protected int getIntParam(String x) throws Exception {
return Integer.parseInt(this.getParamTrim(x), 10);
}
/**
* 进行请求转发<br>
* 同:request.getRequestDispatcher(tar).forward(request, response);
* @param tar 要转发的目标路径
* @throws ServletException
* @throws IOException
*/
protected void forward(String tar) throws ServletException, IOException {
this.request.getRequestDispatcher(tar).forward(request, response);
}
}自定义 Action 需要去实现 IAction ,或者继承 cn.ialvin.web.Action
如果是表单提交你提交完以后,如果用forward转发回页面你刷新试试... 看会出现什么问题???你会发现表单重复提交了。。 这个时候其实应该是用redirect的。
如果是表