尝试使用map注入控制器时出现NullPointerException

时间:2016-05-31 08:31:11

标签: servlets java-ee model-view-controller ejb tomee

我正在建立一个以MVC架构为模型的webapp。来自JSP页面的表单数据被转发到Dispatcher Servlet,该Servlet委托给Controller。我设法注入了一个控制器,它运行得很好。

对于多个控制器,我在servlet中创建了一个Mapping Handler,它通过读入属性文件将请求映射到相关的Controller。我已经注入了映射处理程序,但我仍然得到NullPointerException

另一个ControllerBundle只是将Controller和方法名称抽象为一个对象。我正在使用tomee webprofile 1.7.4

DispatcherServlet.java:

package a1;

// imports

public class DispatcherServlet extends HttpServlet {

    @Inject
    @Named("MappingHandler")
    private MappingHandler MAPPING_HANDLER;

    // ** Single controller **
    // @Inject
    // @Named("customerController")
    // private CustomerController controller;

    @Override
    public void init() throws ServletException {
        MAPPING_HANDLER.generate();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            String pathInfo = req.getPathInfo();
            Controller controller = MAPPING_HANDLER.getController(pathInfo);
            String methodName = MAPPING_HANDLER.getMethod(pathInfo);
            Method method = controller.getClass().getDeclaredMethod(methodName, HttpServletRequest.class);

            method.setAccessible(true);
            method.invoke(controller, req);
            req.getRequestDispatcher("/results.jsp").forward(req, resp);

            // ** Single controller **
            // String methodName = "addCustomer";
            // Method method = controller.getClass().getDeclaredMethod(methodName, HttpServletRequest.class);
            //
            // method.setAccessible(true);
            // method.invoke(controller, req);
            // req.getRequestDispatcher("/success.jsp").forward(req, resp);

        } catch (SecurityException | IllegalArgumentException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}

MappingHandler.java:

package a1;

// imports

@Named("MappingHandler")
public class MappingHandler {

    private static final Map<String, ControllerBundle> CONTROLLER_BUNDLE_MAP = new HashMap<>();

    private static final String PACK = "a1.";

    void generate() {
        try {
            Properties props = new Properties();
            InputStream is1 = this.getClass().getClassLoader().getResourceAsStream("mappings_h6.properties");
            props.load(is1);

            Enumeration e = props.propertyNames();
            while (e.hasMoreElements()) {
                String left = (String) e.nextElement();
                String right = props.getProperty(left);

                // ControllerBundle: abstraction containing both the Controller and the name of the method
                ControllerBundle controllerBundle = new ControllerBundle(right, PACK);
                CONTROLLER_BUNDLE_MAP.put(left, controllerBundle);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    Controller getController(String pathInfo) {
        ControllerBundle controllerBundle = CONTROLLER_BUNDLE_MAP.get(pathInfo);
        Controller controller = controllerBundle.getController();
        return controller;
    }

    String getMethod(String pathInfo) {
        ControllerBundle controllerEntity1 = CONTROLLER_BUNDLE_MAP.get(pathInfo);
        String methodName = controllerEntity1.getMethodName();
        return methodName;
    }
}

ControllerBundle.java:

package a1;

// imports

public class ControllerBundle {

    private Controller controller;
    private String methodName;
    private static final Map<String, Controller> CONTROLLER_MAP = new HashMap<>();

    public ControllerBundle(String value, String pack) {
        String[] valueSplit = value.split("#");

        String controllerName = valueSplit[0];
        Controller controller = findController(pack, controllerName);
        String methodName = valueSplit[1];

        this.controller = controller;
        this.methodName = methodName;
    }

    // Keep only one copy of every controller
    private static Controller findController(String pack, String controllerName) {
        try {

            Class currentControllerClass = Class.forName(pack + controllerName);
            for (String s : CONTROLLER_MAP.keySet()) {
                Class existingControllerClass = CONTROLLER_MAP.get(s).getClass();
                if (currentControllerClass == existingControllerClass) {
                    return (Controller) existingControllerClass.newInstance();
                }
            }

            Controller currentController = (Controller) currentControllerClass.newInstance();
            CONTROLLER_MAP.put(controllerName, currentController);
            return currentController;

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    Controller getController() {
        return controller;
    }

    String getMethodName() {
        return methodName;
    }
}

mappings_h6.properties:

/customer/add=CustomerController#addCustomer
/customer/update=CustomerController#updateCustomer
/account/create=AccountController#createAccount
/account/freeze=AccountController#freezeAccount

的beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
       http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all">
</beans>

1 个答案:

答案 0 :(得分:-1)

你在WEB-INF或WEB-INF / classes / META-INF中有一个beans.xml吗?否则onmee 1.x CDI未激活。