#java #servlets
#java #сервлеты
Вопрос:
Каждый раз, когда я нажимаю ссылку на другие мои страницы, я получаю ошибку исключения нулевого указателя, я не знаю, в чем проблема.
Вот ошибка
05-Jul-2014 17:27:25.941 SEVERE [http-nio-8084-exec-14] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [itemServlet] in context with path [/servlet] threw exception
java.lang.NullPointerException
at com.etc.servlet.itemServlet.showProductList(itemServlet.java:172)
at com.etc.servlet.itemServlet.doPost(itemServlet.java:94)
at com.etc.servlet.itemServlet.doGet(itemServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:301)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1015)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:652)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1575)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1533)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Вот частичный код сервлета, который выдает исключение NullPointerException
public class itemServlet extends HttpServlet {
private memberDao usrdao = new memberDao();
private itemDao itmdao = new itemDao();
private noticeDao ntcdao=new noticeDao();
private articleDao atcdao=new articleDao();
private List<item> listItm;
private List<notice> listNtc;
private List<article> listAtc;
private List<member> listUsr;
private List<item> listpiece;
/**
* Constructor of the object.
*/
public itemServlet() {
super();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1 中文处理
request.setCharacterEncoding("gbk");
response.setContentType("text/html;charset=gbk");
//2 读取参数op
String op = request.getParameter("op");
//3 根据op调用不同的业务方法
if("add".equals(op)){
additem(request,response);//
}else if("findall".equals(op)){
showProductList(request,response);//展现所有商品
}else if("finddetail".equals(op)){
showProductDetail(request,response);//展现商品的细节
}else if("addcart".equals(op)){
addcart(request,response);//添加购物车
}
}
private void addcart(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException//展示商品细节
{
int itmID=Integer.parseInt(request.getParameter("itemID"));
System.out.println("获取本页的商品编号" itmID);
item additem = itmdao.findbyitmmID(itmID);
HttpSession session =request.getSession();
if(request.getSession().getAttribute("listpiece")==null){
listpiece=new ArrayList<item>();
listpiece.add(additem);
System.out.println("listpiece为空。将查到的商品作为单件加入listpiece的列表");
session.setAttribute("listpiece", listpiece);
}
else{
List<item> listpiece=(List<item>) request.getSession().getAttribute("listpiece");
listpiece.add(additem);
System.out.println("listpiece不为空,将查到的商品作为单件加入listpiece的列表");
session.setAttribute("listpiece", listpiece);
}
if(listItm==null)
{
response.getWriter().print("查询失败!");
return;
}
int itid = Integer.parseInt(request.getParameter("itemID"));
for(item it:listItm)
{
if(itid==it.getItemID())//找出该对象
{
request.setAttribute("it", it);
request.getRequestDispatcher("../itemdetail.jsp").forward(request, response);
return;
}
}
}
private void showProductDetail(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException//展示商品细节
{
if(listItm==null)
{
response.getWriter().print("查询失败!");
return;
}
int itid = Integer.parseInt(request.getParameter("itemID"));
for(item it:listItm)
{
if(itid==it.getItemID())//找出该对象
{
request.setAttribute("it", it);
request.getRequestDispatcher("../itemdetail.jsp").forward(request, response);
return;
}
}
}
private void showProductList(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException//商品成列
{
listItm = itmdao.findAll();
listNtc = ntcdao.findSix();
listAtc = atcdao.findTen();
request.setAttribute("listNtc", listNtc);
request.setAttribute("listAtc", listAtc);
request.setAttribute("listItm", listItm);
request.getRequestDispatcher("../showlist.jsp").forward(request, response);
}
private void additem(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException//添加一件新的商品
{
//1 图片上传
SmartUpload sm = new SmartUpload();
sm.initialize(this.getServletConfig(), request, response);
sm.setAllowedFilesList("jpg,jpeg,png,gif");
try
{
sm.upload();
sm.save("/pic");//在pic路径下按原来的名字进行保存
} catch (SmartUploadException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
response.getWriter().print("上传失败!添加失败!");
return;
}
//2 读取表单的其他数据,插入数据库
String itemName = sm.getRequest().getParameter("itemName");
float itemPrice = Float.parseFloat(sm.getRequest().getParameter("price"));
float itemPrice = Float.parseFloat(sm.getRequest().getParameter("itemPrice"));
String itemStatus = sm.getRequest().getParameter("itemStatus");
String itemBrief = sm.getRequest().getParameter("itemBrief");
int typeID =Integer.parseInt(sm.getRequest().getParameter("typeID"));
item newitem = new item(-1,itemName,itemPrice,itemStatus,itemBrief,typeID );
if (!itmdao.add(newitem))
{
response.getWriter().print("添加失败!");
return;
}
request.getRequestDispatcher("itemServlet?op=findall").forward(request, response);
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
}
Возможно ли, что нулевой указатель поступает из базы данных?
itmDao.findall()
public List<item> findAll()
{
System.out.println("itemDao的findAll被调用");
List<item> list = new ArrayList();
ResultSet rs = DBUtils.doQuery("select * from itemTable order by itemID desc");
try {
if (rs == null)
return list;
while (rs.next()) {
item item = new item(rs.getInt("itemID"),
rs.getString("itemName"), rs.getFloat("itemPrice"),rs.getString("itemStatus"),rs.getString("itembrief")
,rs.getInt("typeID"));
list.add(item);
}
} catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
DBUtils.close(rs, rs.getStatement(), rs.getStatement()
.getConnection());
} catch (Exception e2)
{
e2.printStackTrace();
}
}
return list;
}
ntddao.findsix()
public List<notice> findSix() //用在首页的 查找前六条的公告
{
System.out.println("noticeDao的findSix函数被调用");
List<notice> list = new ArrayList();
ResultSet rs = DBUtils.doQuery("select * from notice order by ntID desc");
try {
if (rs == null)
return list;
int i=1;
while (rs.next()amp;amp;i<=6) {
notice notice = new notice(rs.getInt("ntID"),
rs.getString("ntTitle"), rs.getString("ntTime"),rs.getString("ntText"),rs.getInt("adID"));
list.add(notice);
i ;
}
} catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
DBUtils.close(rs, rs.getStatement(), rs.getStatement()
.getConnection());
} catch (Exception e2)
{
e2.printStackTrace();
}
}
return list;
}
atcdao.findten()
public List<article> findTen() //用在首页的 查找前10条的公告
{
System.out.println("articleDao的findTen函数被调用");
List<article> list = new ArrayList();
ResultSet rs = DBUtils.doQuery("select * from article order by atID desc");
try {
if (rs == null)
return list;
int i=1;
while (rs.next()amp;amp;i<=10) {
article article = new article(rs.getInt("atID"),
rs.getString("atTitle"), rs.getString("atPic"),rs.getString("atTime"),rs.getString("atText"),rs.getInt("adID"));
list.add(article);
i ;
}
} catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
DBUtils.close(rs, rs.getStatement(), rs.getStatement()
.getConnection());
} catch (Exception e2)
{
e2.printStackTrace();
}
}
return list;
}
Комментарии:
1. Пожалуйста, придерживайтесь соглашений об именовании Java . Классы находятся в
PascalCase
—itemSevlet
неверно. Как и все ваши другие имена классов. Что такое строка172
?2. NPE означает, что вы вызываете метод по ссылке, присвоенной null. Вы должны присвоить значение ссылке перед вызовом метода для нее
Ответ №1:
Путь, который вы указываете getRequestDispatcher
, должен находиться в текущем контексте сервлета. Это означает, что вы не можете использовать что-то вроде "../showlist.jsp"
. Вам придется по-другому организовать структуру каталогов.
Комментарии:
1. Под «внутри текущего контекста сервлета» вы имеете в виду, что либо jsp, либо сервлет должны находиться в одной папке?
2. Я бы поместил JSP во вложенную папку с именем jsp. Но поместите эту папку в такое место, где вам не нужен «../» для ссылки на нее. Возможно, вам придется немного поэкспериментировать, чтобы увидеть, что работает с тем, как вы настроили свое приложение.
Ответ №2:
Не могли бы вы проверить наличие null в следующих объектах, пожалуйста?
listItm = itmdao.findAll();
listNtc = ntcdao.findSix();
listAtc = atcdao.findTen();
Я предполагаю, что один (или более) из них равен нулю, поэтому setAttribute выдает исключение.
В противном случае я настоятельно рекомендую не применять принудительное использование полей в сервлете, который выполняется как синглтон в памяти, а множественные пользовательские запросы могут нарушить согласованность ваших данных. Я говорю об этих полях:
private List<item> listItm;
private List<notice> listNtc;
private List<article> listAtc;
private List<member> listUsr;
private List<item> listpiece;
Моя другая рекомендация — следовать соглашению об именовании java. Например, измените первый символ вашего класса на заглавный: itemServlet -> ItemServlet.
Это более стандартный способ, который помогает нам лучше понять ваш код 🙂
Комментарии:
1. Нет, проблема не в этом. Все эти поля инициализированы новыми объектами, и нет кода, который мог бы вернуть им значение null.
2. listItm, или listNtc, или listAtc может быть нулевым, если dao может возвращать значение null. Вторая часть моего ответа касается потенциальной проблемы параллелизма, а не NPE
3. Здравствуйте, я предоставил свой код для itmdao.findAll(), ntcdao.findSix() и atcdao.findTen(), я немного спешу, поэтому я изменю свой код, если у меня будет время, действительно извините!
4. @Lexandro Да, эти переменные могут быть нулевыми; но это не приведет к NPE. OP спросил о NPE, и ваш ответ не объясняет NPE. Причиной NPE является расположение JSP — оно не имеет ничего общего с DAO.
5. Вы правы. Теперь я вижу в коде DAO, что он никогда не возвращает null. У меня было неверное предположение 🙂 Я отметил ваш ответ 1