【问题标题】:NullPointerException when trying to inject Controllers using map尝试使用地图注入控制器时出现 NullPointerException
【发布时间】:2016-05-31 08:31:10
【问题描述】:

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

对于多个控制器,我在 servlet 中创建了一个映射处理程序,它通过读取属性文件将请求映射到相关的控制器。我已经注入了映射处理程序,但我仍然得到一个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>

【问题讨论】:

    标签: servlets jakarta-ee model-view-controller ejb apache-tomee


    【解决方案1】:

    您在 WEB-INF 或 WEB-INF/classes/META-INF 中有 beans.xml 吗?否则在 tomee 1.x 上 CDI 不会被激活。

    【讨论】:

    • 是的,我刚刚添加了 beans.xml
    • 您添加的 sn-p 是 EE 7 beans.xml,因此对 TomEE 1 无效(对 TomEE 7 有效)。试试“”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    相关资源
    最近更新 更多