java 自己动手做框架之MVC

来源:互联网 发布:下一代网络结构和特点 编辑:程序博客网 时间:2024/06/04 18:27

开发工具 :Eclipse Tomcat
依赖jar包 :Gson
1.定义一个核心Servlet
MyServet.java

package com.zking.servlet;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.zking.utils.RequestProcessing;/** * 核心Servlet 如果没有此类整个框架没什么用 * @author Administrator * */@WebServlet(urlPatterns = "*.action")public class MyServlet extends HttpServlet {    private static final long serialVersionUID = -6919158984346575416L;    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doPost(request, response);    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        RequestProcessing processing = new RequestProcessing(request, response);        processing.init();    }}

RequestProcessing.java

package com.zking.utils;import java.io.IOException;import java.io.PrintWriter;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.zking.annotation.Controller;import com.zking.annotation.RequestMapping;import com.zking.annotation.RespnoseBody;import com.zking.type.MethodType;/** * 请求处理类 *  * @author Administrator * */public class RequestProcessing {    private HttpServletRequest request;    private HttpServletResponse response;    private static List<Object> controllerObj = new ArrayList<>();    public RequestProcessing(HttpServletRequest request, HttpServletResponse response) {        this.request = request;        this.response = response;    }    public void init() throws IOException, ServletException {        //获得所有带有Controller类的Class对象        List<Class<?>> list = ClassScanUtil.getClassByController();        //获得path 如/index.action        String path = null;        {            String url = request.getRequestURI();            String contextpath = request.getContextPath();            path = url.substring(contextpath.length(), url.length());        }        //调用控制器的速度 为保证控制器唯一 顾不能超过一        int count = 0;        //遍历所有控制器 直到找到匹配的控制器为止        for (int i = 0; i < list.size(); i++) {            Class<?> cls = list.get(i);            //获得类中带有RequestMapping注解的方法            Method[] methods = MethodFilterUtil.getMethodByRequestMapping(cls.getMethods());            for (Method method : methods) {                //获得该方法的RequestMapping注解                RequestMapping mapping = method.getAnnotation(RequestMapping.class);                //判断该方法是否是当前和当前请求的url对应                if (path.equals(mapping.path() + ".action")) {                    //判断该方法是否支持当前请求方式                    if (isMethod(mapping, EnumHandleUtil.getMethodTypeByMethod(request.getMethod()))) {                        try {                            //判断该url对应的方法是否调用过了                            if (count > 1) {                                throw new RuntimeException("重复url");                            }                            //创建该控制器的对象                            Controller controller = cls.getAnnotation(Controller.class);                            Object obj = null;                            //判断当前控制器是否是单例模式                            if (controller.singleCase()) {                                int index = contains(cls);                                if (index >= 0) {                                    obj = controllerObj.get(i);                                }else {                                    obj = cls.newInstance();                                    controllerObj.add(obj);                                }                            }else {                                obj = cls.newInstance();                            }                            //获得当前方法的所有形式参数类型                            Class<?>[] clss = method.getParameterTypes();                            //调用该方法                            Object object = MethodInvokeUtil.Invoke(method, obj, clss, request, response);                            if (object != null) {                                //判断该方法是否带有RespnoseBody注解 (如果有那么序列话json并输入到控制台)                                if (method.getAnnotation(RespnoseBody.class) == null) {                                    //判断该方法返回值是否为String (如果是那么判断是重定向还是请求转发)                                    if (object instanceof String) {                                        String p = object.toString();                                        if (p.contains("redirect:")) {                                            response.sendRedirect(request.getContextPath() + p.substring(p.lastIndexOf("/")) + ".action");                                        }else {                                            request.getRequestDispatcher("/" + p + ".jsp").forward(request, response);                                        }                                    }                                }else{                                    //将对象转为json并以UTF-8的方式打印到浏览器(依赖gson)                                    print(object);                                }                            }                            //方法调用完成后 标识变量增加                            count++;                        } catch (Exception e) {                            e.printStackTrace();                        }                    }                }            }        }        /**         * 如果没有找到对应控制器方法返回错误页面         */        if (count == 0) {            response.setCharacterEncoding("utf-8");            response.setStatus(404);            request.getRequestDispatcher("/err/err.jsp").forward(request, response);        }    }    /**     * 判断该方法是否支持当前请求类型     * @param mapping     * @param type     * @return     */    private boolean isMethod(RequestMapping mapping, MethodType type) {        if (mapping.method() == type) {            return true;        } else if (mapping.method() == MethodType.ALL) {            return true;        }        return false;    }    /**     * 将对象转为json并输出到浏览器     * @param object     * @throws IOException      */    private void print(Object object) throws IOException{        if (object instanceof String || object instanceof Character || object instanceof Short                || object instanceof Integer || object instanceof Byte || object instanceof Long                ||object instanceof Float || object instanceof Double) {            response.setCharacterEncoding("utf-8");            PrintWriter pw = response.getWriter();            pw.write(object.toString());            pw.close();        }else {            //获得当前线程的类加载器            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();            Object gson = null;            try {                Class<?> cls = classLoader.loadClass("com.google.gson.Gson");                Method method = cls.getMethod("toJson", Object.class);                gson = cls.newInstance();                //调用Gson的toJson方法生成json                String json = (String) method.invoke(gson, object);                response.setCharacterEncoding("utf-8");                PrintWriter pw = response.getWriter();                pw.write(json);                pw.close();            } catch (Exception e) {                System.err.println("没有在您的项目中找到Gson");            }            if (gson == null) {                response.setCharacterEncoding("utf-8");                PrintWriter pw = response.getWriter();                pw.write("没有在您的项目中找到Gson");                pw.close();            }        }    }     public int contains(Class<?> cls){        for (int i = 0; i < controllerObj.size(); i++) {            if (cls == controllerObj.get(i).getClass()) {                return i;            }        }        return -1;    }}

ClassScanUtil.java

package com.zking.utils;import java.io.File;import java.lang.annotation.Annotation;import java.util.ArrayList;import java.util.List;import com.zking.annotation.Controller;public class ClassScanUtil {    /**     * 获得所有类的全限定名     * @param files     * @param 请传null     * @return     */    private synchronized static List<String> getAllClass(File[] files,List<String> strings) {        if (strings == null) {            strings = new ArrayList<>();         }        for (File file : files) {            if (file.isFile()) {                if (file.getName().contains(".class")) {                    // 全限类名 等于项目路径减去类路径                    String classPath = file.getPath()                            .substring(new File(ClassScanUtil.class.getResource("/").getFile()).getPath().length() + 1,                                    file.getPath().lastIndexOf(".class"))                            .replace("\\", ".");                    strings.add(classPath);                }            }            if (file.isDirectory()) {                getAllClass(file.listFiles(),strings);            }        }        return strings;    }    private static List<Class<?>> controllerClass = new ArrayList<>();    /**     * 获得所有带Controller的类Class对象     * @return     */    public static List<Class<?>> getClassByController() {        if (controllerClass.size() <= 0) {            synchronized(ClassScanUtil.class){                if (controllerClass.size() > 0) {                    return controllerClass;                }                File file = new File(ClassScanUtil.class.getResource("/").getFile());                File[] files = file.listFiles();                List<String> strings = getAllClass(files, null);                for (int i = 0; i < strings.size(); i++) {                    try {                        Class<?> cls = Class.forName(strings.get(i));                        Annotation annotation = cls.getAnnotation(Controller.class);                        if (annotation != null) {                            controllerClass.add(cls);                        }                    } catch (ClassNotFoundException e) {                        e.printStackTrace();                    }                }                return controllerClass;            }        }        return controllerClass;    }    /**     * 请空集合      * 使用场景 Tomcat为热启动时 可以将Controller设置为单例模式 然后在控制器的构造方法中调用 (这样就类扫描器就会重新去扫描)     * 不建议使用 因为控制器为单例模式的话会造成数据冲突     */    @Deprecated    public static void clearControllerClass(){        if (controllerClass.size() > 0) {            synchronized (ClassScanUtil.class) {                if (controllerClass.size() > 0) {                    controllerClass.clear();                }            }        }    }    /**     * 增加一个类 (请保证这个类绝对有Controller这个注解)     * 使用场景和注意事项同clearControllerClass     * @param cls     */    @Deprecated    public synchronized static void addControllerClass(Class<?> cls){        int c = 0;        for (int i = 0; i < controllerClass.size(); i++) {            if (cls == controllerClass.get(i).getClass()) {                c++;            }        }        if (c == 0) {            controllerClass.add(cls);        }    }    /**     * 增加一个类 (请保证这个类绝对有Controller这个注解)     * 使用场景和注意事项同clearControllerClass     * @param className     * @throws ClassNotFoundException     */    @Deprecated    public static void addControllerClass(String className) throws ClassNotFoundException{        addControllerClass(Class.forName(className));    }}

MethodFilterUtil.java

package com.zking.utils;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import com.zking.annotation.RequestMapping;public class MethodFilterUtil {    /**     * 获得带有RequestMapping注解的方法     * @param methods     * @return     */    public static Method[] getMethodByRequestMapping(Method[] methods){        List<Method> list = new ArrayList<>();        for (Method method : methods) {            if (method.getAnnotation(RequestMapping.class) != null) {                list.add(method);            }        }        Method[] methods2 = new Method[list.size()];        for (int i = 0; i < list.size(); i++) {            methods2[i] = list.get(i);        }        return methods2;    }}

MethodType.java

package com.zking.type;/** * 请求类型枚举 * @author Administrator * */public enum MethodType {    ALL,    GET,    POST,    UPDATE,    DELETE}

EnumHandleUtil.java

package com.zking.utils;import com.zking.type.MethodType;public class EnumHandleUtil {    /**     * 根据请求类型字符串返回请求类型枚举     * @param method     * @return     */    public static MethodType getMethodTypeByMethod(String method){        method = method.toLowerCase();        MethodType type = MethodType.ALL;        if (method.equals("get")) {            type = MethodType.GET;        }else if(method.equals("post")){            type = MethodType.POST;        }else if(method.equals("update")){            type = MethodType.UPDATE;        }else if(method.equals("delete")){            type = MethodType.DELETE;        }        return type;    }}

MethodInvokeUtil.java

package com.zking.utils;import java.io.PrintWriter;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import com.zking.annotation.Param;public class MethodInvokeUtil {    /**     * 调用控制器方法     * @param method     * @param obj     * @param classes     * @param request     * @param response     * @return     * @throws Exception     */    public static Object Invoke(Method method,Object obj,Class<?>[] classes,HttpServletRequest request,HttpServletResponse response) throws Exception{        //声明参数集合        List<Object> objects = new ArrayList<>();        //判断参数类型 进行注入        for (int i = 0; i < classes.length; i++) {            if (classes[i] == HttpServletRequest.class) {                objects.add(request);            }else if (classes[i] == HttpServletResponse.class) {                objects.add(response);            }else if(classes[i] == HttpSession.class){                objects.add(request.getSession(true));            }else if(classes[i] == PrintWriter.class){                response.setCharacterEncoding("utf-8");                objects.add(response.getWriter());            }else {                //如果是普通参数 那么判断它是否有表单参数注解                Annotation[][] annotations = method.getParameterAnnotations();                Param param = null;                if (annotations[i].length > 0) {                    Annotation annotation = annotations[i][0];                    if (annotation.annotationType() == Param.class) {                        param = (Param) annotation;                    }                }                //如果有表单参数注解 那么取出表单的值进行注入                if (param != null) {                    //请求参数处理                    RequestParameter parameter = new RequestParameter(method,request, response,objects,classes[i],param);                    //初始化                    parameter.init();                }else {                    //判断是否是值类型                    if (classes[i] == Integer.class || classes[i] == int.class) {                        objects.add(0);                    }else if(classes[i] == Short.class || classes[i] == short.class){                        objects.add(0);                    }else if(classes[i] == Byte.class || classes[i] == byte.class){                        objects.add(0);                    }else if(classes[i] == Long.class || classes[i] == long.class){                        objects.add(0f);                    }else if(classes[i] == Float.class || classes[i] == float.class){                        objects.add(0f);                    }else if(classes[i] == Double.class || classes[i] == double.class){                        objects.add(0.0);                    }else {                        //如果不是值类型 那么以null填充                        objects.add(null);                    }                }            }        }        //通过反射调用方法        Object object = method.invoke(obj, objects.toArray());        return object;    }}

RequestParameter.java

package com.zking.utils;import java.io.IOException;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.zking.annotation.Param;public class RequestParameter {    private HttpServletRequest request;    private HttpServletResponse response;    private List<Object> list = null;    private Class<?> cls;    private Method method;    private Param param;    public RequestParameter(Method method, HttpServletRequest request, HttpServletResponse response, List<Object> list,            Class<?> cls, Param param) {        this.method = method;        this.request = request;        this.response = response;        this.list = list;        this.cls = cls;        this.param = param;    }    public void init() throws IOException {        // 将编码设置成utf-8        request.setCharacterEncoding("utf-8");        setValue();    }    /**     * 给方法参数设置     */    public void setValue() {        // 获得Param注解的name属性值        String paramName = param.name();        if (!paramName.equals("")) {            // 判断是否是八大基本数据类型            setValue(request.getParameter(paramName));                  }else{            Object object = null;            try {                object = cls.newInstance();            } catch (InstantiationException e1) {                // TODO Auto-generated catch block                e1.printStackTrace();            } catch (IllegalAccessException e1) {                // TODO Auto-generated catch block                e1.printStackTrace();            }            if (object != null) {                Field[] fields = cls.getDeclaredFields();                for (int i = 0; i < fields.length; i++) {                    fields[i].setAccessible(true);                    try {                        setValue(fields[i], object, request.getParameter(fields[i].getName()));                    } catch (IllegalArgumentException | IllegalAccessException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }            list.add(object);        }    }    public void setValue(Object object){            if(cls == Integer.class || cls == int.class){                if (object == null) {                    list.add(0);                }else {                    list.add(Integer.parseInt(object.toString()));                }            }else if(cls == Short.class || cls == short.class){                if (object == null) {                    list.add(0);                }else {                    list.add(Short.parseShort(object.toString()));                }            }else if(cls == Byte.class || cls == byte.class){                if (object == null) {                    list.add(0);                }else {                    list.add(Byte.parseByte(object.toString()));                }            }else if(cls == Long.class || cls == long.class){                if (object == null) {                    list.add(0l);                }else {                    list.add(Long.parseLong(object.toString()));                }            }else if(cls == Float.class || cls == float.class){                if (object == null) {                    list.add(0f);                }else {                    list.add(Float.parseFloat(object.toString()));                }            }else if(cls == Double.class || cls == double.class){                if (object == null) {                    list.add(0.0);                }else {                    list.add(Double.parseDouble(object.toString()));                }            }else if(cls == Character.class || cls == char.class){                if (object == null) {                    list.add((char)0);                }else {                    list.add(object.toString().charAt(0));                }            }else if(cls == String.class){                if (object == null) {                    list.add(null);                }else{                    list.add(object.toString());                }            }    }    public void setValue(Field field,Object object,Object value) throws NumberFormatException, IllegalArgumentException, IllegalAccessException{        Class<?> paramcls = field.getType();        if (object != null) {            if(paramcls == Integer.class || paramcls == int.class){                if (value == null) {                    field.set(object, 0);                }else {                    field.set(object, Integer.parseInt(value.toString()));                }            }else if(paramcls == Short.class || paramcls == short.class){                if (value == null) {                    field.set(object, 0);                }else {                    field.set(object, Short.parseShort(value.toString()));                }            }else if(paramcls == Byte.class || paramcls == byte.class){                if (value == null) {                    field.set(object, 0);                }else {                    field.set(object, Byte.parseByte(value.toString()));                }            }else if(paramcls == Long.class || paramcls == long.class){                if (value == null) {                    field.set(object, 0l);                }else {                    field.set(object, Long.parseLong(value.toString()));                }            }else if(paramcls == Float.class || paramcls == float.class){                if (value == null) {                    field.set(object, 0f);                }else {                    field.set(object, Float.parseFloat(value.toString()));                }            }else if(paramcls == Double.class || paramcls == double.class){                if (value == null) {                    field.set(object, 0.0);                }else {                    field.set(object, Double.parseDouble(value.toString()));                }            }else if(paramcls == Character.class || paramcls == char.class){                if (value == null) {                    field.set(object, (char)0);                }else {                    field.set(object, value.toString().charAt(0));                }            }else if(paramcls == String.class){                if (value == null) {                    field.set(object, null);                }else {                    field.set(object, value.toString());                }            }        }    }}

详情请见源码 链接:链接:链接:http://pan.baidu.com/s/1hs4y53A 密码:11bl
Tomcat 6.0
web.xml

<servlet>        <servlet-name>myServlet</servlet-name>        <servlet-class>com.zking.servlet.MyServlet</servlet-class>    </servlet>    <servlet-mapping>        <servlet-name>myServlet</servlet-name>        <!--只能写这个-->        <url-pattern>*.action</url-pattern>    </servlet-mapping>

Tomcat7.0 且 是动态web3.0 以上无需配置web.xml

使用方法 与SpringMVC一致
只需要将类声明为Controller 方法声明为RequestMapping
请求url为设置的加.action 只能是.action其他的不行
比如

package com.zking.controller;import com.zking.annotation.Controller;import com.zking.annotation.Param;import com.zking.annotation.RequestMapping;import com.zking.annotation.RespnoseBody;import com.zking.entity.Person;//@Controller 原型模式 @Controller(singleCase=true)(单例模式)@Controllerpublic class HelloController {    @RespnoseBody    @RequestMapping(path="/index")    public String index(@Param Person person,@Param(name ="address") String address,@Param(name="phone") long phone){        System.out.println(hashCode());        System.out.println(person);        System.out.println(address);        System.out.println(phone);        return "helloWord";    }}
@RequestMapping(path="/index",method=MethodType.ALL)

那么请求url就是 index.action

参数path必须是/开头

其他与Spring MVC使用一致

0 0