抛出异常AS-WEB-CORE-00089转发到不同的servlet路径

时间:2014-08-27 12:55:32

标签: java jsp servlets

我试图从doPost转发到ControllerServlet的获取urlPattern =" / remove_person",所以我可以在ControllerServlet类的doGet方法中重新更新findAll查询,然后转发到remove_person。来自doGet方法的jsp,但抛出了AS-WEB-CORE-00089异常

WARNING:   StandardWrapperValve[ControllerServlet]: Servlet.service() for servlet ControllerServlet threw exception
javax.servlet.ServletException: AS-WEB-CORE-00089
    at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:863)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:739)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:575)
    at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:546)
    at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:428)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:378)
    at server.ControllerServlet.doPost(ControllerServlet.java:130)

其中ControllerServlet.java:130行在doPost()方法中:

request.getRequestDispatcher(url).forward(request, response);

这是servlet类的代码:

@WebServlet(
    name = "ControllerServlet", 
    loadOnStartup = 1,
    urlPatterns = {
        "/index", 
        "/search_person", 
        "/add_person",
        "/remove_person"})
public class ControllerServlet extends HttpServlet {

    @PersistenceUnit
    private EntityManagerFactory emf;
    @Resource
    private UserTransaction utx;
    private EntityManager em;

    @Override
    public void init() throws ServletException {
        assert emf != null;
        em = emf.createEntityManager();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String servletPath = request.getServletPath();

        if (servletPath.equals("/index")) {
        }
        else if (servletPath.equals("/search_person")) {
            List persons = em.createNamedQuery("Person.findAll").getResultList();
            request.setAttribute("findByNameAndYearBirth", persons);
        }
        else if (servletPath.equals("/add_person")) {
        }
        else if (servletPath.equals("/remove_person")) {
            List persons = em.createNamedQuery("Person.findAll").getResultList();
            request.setAttribute("findAll", persons);
        }
        String url = servletPath + ".jsp";
        request.getRequestDispatcher(url).forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String servletPath = request.getServletPath();

        if (servletPath.equals("/index")) {
        }
        else if (servletPath.equals("/search_person")) {
            String name = request.getParameter("name");
            String yearBirth = request.getParameter("yearBirth");

            Query query = em.createNamedQuery("Person.findAll");
            if (!name.isEmpty() && !yearBirth.isEmpty()) {
                query = em.createNamedQuery("Person.findByNameAndYearBirth");
                query.setParameter("name", name);
                query.setParameter("yearBirth", Short.parseShort(yearBirth));
            }
            else if (!name.isEmpty()) {
                query = em.createNamedQuery("Person.findByModel");
                query.setParameter("name", name);
            }
            else if (!yearBirth.isEmpty()) {
                try  {
                    Short sYearBirth = Short.parseShort(yearBirth);
                    query = em.createNamedQuery("Person.findByYearBirth");
                    query.setParameter("yearBirth", sYearBirth);
                } catch (NumberFormatException nfe) {}
            }
            List persons = query.getResultList();
            request.setAttribute("findByNameAndYearBirth", persons);
        }
        else if (servletPath.equals("/add_person")) {
            String name = request.getParameter("name");
            String hobby = request.getParameter("hobby");
            String yearBirth = request.getParameter("yearBirth");

            int personsLen = em.createNamedQuery("Person.findAll").getResultList().size();
            Person newPerson = new Person(
                ++personsLen, name, hobby, Short.parseShort(yearBirth)
            );
            try {
                utx.begin();
                em = emf.createEntityManager();
                em.persist(newPerson);
                utx.commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        else if (servletPath.equals("/remove_person")) {
            String id = request.getParameter("id");

            Person person = null;  
            try {
                utx.begin();
                person = em.find(Person.class, Integer.parseInt(id));
                em.remove(person);
                utx.commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
            servletPath = "/remove_person";
        }
        String url = servletPath;
        request.getRequestDispatcher(url).forward(request, response);
    }

}

问题是,我的内线是doPost方法

String url = path; 

不包含" .jsp"部分。

但如果我添加" .jsp"如果我没有在添加或删除实体后首先收集servlet doGet以收集新数据,那么如何在一个字符串url中更新findAll查询数据?

remove_person.jsp

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <h1>Remove Person</h1>
        <form action="remove_person" method="post">
            <table border="3">
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                </tr>
                <c:forEach var="person" begin="0" items="${findAll}"> 
                    <tr>
                        <td>${person.id}</td> 
                        <td>${person.name}</td> 
                    </tr> 
                </c:forEach>
            </table>
            <strong>Remove person: </strong>
            <select name="id">
            <c:forEach var="person" items="${findAll}">
                <option value="${person.id}">${person.id}. ${person.name} </option>
            </c:forEach>
            </select>
            <input type="submit" id="remove_person" value="Remove" />
        </form>
        <br>
        <a href="index">Home page</a>
    </body>
</html>

实际上,甚至可以从doPost转发到同一个servlet的doGet方法吗?我试图这样做的原因是因为,在doGet中我已经使用了这段代码:

List persons = em.createNamedQuery("Person.findAll").getResultList();
request.setAttribute("findAll", persons);

那么,当我可以从doPost转发到doGet方法并调用该代码时,为什么要在doPost方法中复制此代码呢?

更新

糟糕的做法:

String url = servletPath;
request.getRequestDispatcher(url).forward(request, response);

正确方法:

String url = request.getContextPath() + servletPath;
response.sendRedirect(url);

1 个答案:

答案 0 :(得分:4)

使用重定向而不是转发。模式(称为Post/Redirect/Get)是:

1)客户端调用post url,进行更新

2)servlet使用get的url向客户端发送重定向。

3)客户端从重定向调用url。

当GET的响应返回时,浏览器具有GET URL,因此浏览器最终得到一个可收藏的URL。此外,用户无法通过点击f5或多次点击来重新发布相同的数据。

有关何时使用转发与重定向的信息,请参阅this advice

  

转发

     
      
  • 由servlet在内部执行转发
  •   
  • 浏览器完全不知道它已经发生,因此其原始网址保持不变
  •   
  • 任何浏览器重新加载生成的页面都会使用原始网址
  • 简单地重复原始请求   
     

重定向

     
      
  • 重定向是一个两步过程,其中Web应用程序指示浏览器获取第二个URL,该URL不同于   原始
  •   
  • 浏览器重新加载第二个网址不会重复原始请求,而是会提取第二个网址
  •   
  • 重定向比转发略慢,因为它需要两个浏览器请求,而不是一个
  •   
  • 放置在原始请求范围内的对象不可用于第二个请求
  •   
     

通常,如果在浏览器重新加载生成的网页时可以安全地重复操作,则应使用转发;否则,必须使用重定向。通常,如果操作在数据存储上执行编辑,则需要重定向而不是转发。这只是为了避免无意中重复编辑数据库的可能性。