Servlet之封装通用方法
思想:
将增删改查的Servlet改造成普通的方法放在一个AServlet中,这个Servlet类继承一个通用的DispatcherServlet,DispatcherServlet继承 HttpServlet,当调用AServlet的A方法时,优先调用父类DispatcherServlet的dopost通用,通过反射去调用A方法
步骤DispatcherServlet的实现
1、得到地址栏传递的方法名称localhost:8080/UserServlet/*
2、通过方法名称找到方法this.getClass().getMethods();,遍历 名字相同就返回方法
3得到方法通过方法.invoke去调用
4、考虑方法的参数,地址栏得到参数的情况、传递的时requeset、response的情况、传递对象的情况
5、得到方法的形参,判断形参的类型,HttpServletRequest类和HttpServletResponse类则直接给值给value,否则通过requset.getParameter得到数据,若没有数据,则考虑为传递的是一个对象
6、req.getParameterMap()得到传递的所有数据,通过BeanUtil.populate把map的数据封装成一个对象,这个方法需要导jar包,需要考虑时间转换的问题
7、把value放到数组中返回,在方法.invoke处作为参数传递
8、方法的调用会有返回值,在DispatcherServlet中封装一个方法进行转发或者重定向
commons-beanutils-1.8.3.jar
commons-collections-3.2.1.jar
commons-logging-1.1.1.jar
static {
//处理时间转换问题,jar包封装没有解决,需要手动解决
ConvertUtils.register(new SqlDateConverter(null), Date.class);
ConvertUtils.register(new Converter() {
@Override
public Object convert(Class type, Object value) {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
try{
return simpleDateFormat.parse(value.toString());
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}, Date.class);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//首先得到action的名字
String actionName=getActionName(request.getRequestURI());
System.out.println(actionName);
if (!StringUtils.isEmpty(actionName)){
//根据action名字找到方法
Method method=getMethodByActionName(actionName);
// System.out.println(method.getName());
//得到方法参数的名称为一个数组
Object[] args=actionMethodParameter(method,request,response);
if (method!=null){
try {
//调用方法
Object invoke = method.invoke(this, args);
//响应
responseClient(invoke.toString(),request,response);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}else {
System.out.println("你还没有【"+actionName+"】方法");
}
}else {
System.out.println("url中没有此action");
}
}
private String getActionName(String requestURI) {
// System.out.println(requestURI.substring(requestURI.lastIndexOf("/")+1));
return requestURI.substring(requestURI.lastIndexOf("/")+1);
}
private Method getMethodByActionName(String actionName) {
//子类调用对子类的方法进行获取
Method[] methods = this.getClass().getMethods();
for (int i=0;i<methods.length;i++){
String methodName = methods[i].getName();
if (methodName.equals(actionName)){
//如果action的名称和方法名称相同
return methods[i];
}
}
return null;
}
private Object[] actionMethodParameter(Method method, HttpServletRequest req, HttpServletResponse resp) {
//需要得到每个方法的参数个数
Object [] args=new Object[method.getParameterCount()];
//获取方法的形参对象
Parameter[] parameters = method.getParameters();
//通过形参的名字获取地址栏的信息
for (int i=0;i<parameters.length;i++){
Object value=null;
System.out.println(parameters[i].getName());
if ("HttpServletRequest".equals(parameters[i].getType().getSimpleName())){
value=req;
}else if ("HttpServletResponse".equals(parameters[i].getType().getSimpleName())){
value=resp;
}else {
value = parameMethod(req.getParameter(parameters[i].getName()),parameters[i].getType());
//如果value值为空说明需要封装成对象
if (value==null||"".equals(value)){
try {
//通过参数的类型生成对象
Object ins = parameters[i].getType().newInstance();
//得到地址栏参数的所有信息
Map<String, String[]> parameterMap = req.getParameterMap();
//直接把数据封装成对象
/**
* 地址栏参数的名字和对象的属性名要一致
*/
try {
BeanUtils.populate(ins,parameterMap);
value=ins;
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
args[i]=value;
}
return args;
}
private void responseClient(String result,HttpServletRequest request,HttpServletResponse response) {
String[] split = result.split(":");
//forward 或者是redirect
String type=split[0];
System.out.println(type);
//jsp页面
String page=split[1];
if ("forward".equals(type)){
try {
// System.out.println(request.getContextPath()+"/");
//转发的/寻找到当前项目的根,如果不加/,会在当前路径下寻找最后一个/,添加到后面
request.getRequestDispatcher(request.getContextPath()+"/"+page).forward(request,response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else if ("redirect".equals(type)){
try {
//重定向的/找所有项目的根,所以需要request.getContextPath()
//如果不加/,会在当前路径下寻找最后一个/,添加到后面http:localhost:8080/UserServlet/button.jsp,所以报错
//我们要进http:localhost:8080/button.jsp,所以要加/ ,request.getContextPath()上下文发布路径
response.sendRedirect(request.getContextPath()+"/"+page);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private Object parameMethod(String parameter, Class<?> type) {
//判断类型
if ("Integer".equals(type.getSimpleName())){
return Integer.parseInt(parameter);
}else if ("Double".equals(type.getSimpleName())){
return Double.parseDouble(parameter);
}else if ("Date".equals(type.getSimpleName())){
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
try {
return simpleDateFormat.parse(parameter);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
} else {
return parameter;
}
}