我试图从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);
答案 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不同于 原始
- 浏览器重新加载第二个网址不会重复原始请求,而是会提取第二个网址
- 重定向比转发略慢,因为它需要两个浏览器请求,而不是一个
- 放置在原始请求范围内的对象不可用于第二个请求
通常,如果在浏览器重新加载生成的网页时可以安全地重复操作,则应使用转发;否则,必须使用重定向。通常,如果操作在数据存储上执行编辑,则需要重定向而不是转发。这只是为了避免无意中重复编辑数据库的可能性。