首页 > 解决方案 > 如何使用 ModelAndView 对象解决 NullPointerException?

问题描述

当我在下面的控制器中使用对象“ModelAndView”时,我发现了“nullPointerException”(请求处理失败;嵌套异常是“java.lang.NullPointerException”)的问题。下面三种变量不能为空。我知道控制器中的变量“viewName”无法获取值,对象映射也可以带来明确的价值。此外,对象“ItemDTO”的变量“idto”具有空值而不是任何值。

如何修复适合变量的现有代码以获得正确的值?

以下是与我解释的内容相关的代码。

代码是下面的控制器。

 @Controller
    @RequestMapping("booksale")
    public class BookSaleController {
        @Inject
        private BookSaleService bService;
    
    @RequestMapping(value="/itemDetail/{ino}")
        public ModelAndView itemDetail(@PathVariable("ino")int ino, HttpServletRequest request, 
                                       HttpServletResponse response) {      
            
            String viewName = (String) request.getAttribute("viewName");    
            HttpSession session = request.getSession();     
            Map iMap = bService.itemDetail(ino);        
            ModelAndView mav = new ModelAndView(viewName);  
            mav.setViewName("/itemDetail/{ino}");       
            mav.addObject("iMap", iMap);        
            ItemDTO idto = (ItemDTO) iMap.get("idto");      
            appendItemQmenu(ino, idto, session);
             
            return mav;
            
            
        }
        
    
            
            
        private void appendItemQmenu(int ino, ItemDTO idto, HttpSession session) {
            // TODO Auto-generated method stub
            boolean existing_presence = false;
            List<ItemDTO> QuickItemList = 
            (List<ItemDTO>) session.getAttribute("QuickItemList");
            
            if (QuickItemList != null) {
                if (QuickItemList.size() < 3) {
                    for (int i = 0; i < QuickItemList.size(); i++) {
                        ItemDTO itemBean = QuickItemList.get(i);
                        String sIno = Integer.toString(ino);
                        
                        if (sIno.equals(itemBean.getIno())) {
                            existing_presence = true;
                            return;
                        }
                        
                    }
                    if (existing_presence== false) {
                        QuickItemList.add(idto);
                    }
                    
                }
            }else {
                QuickItemList = new ArrayList<ItemDTO>();
                QuickItemList.add(idto);
            }
            session.setAttribute("QuickItemList", QuickItemList);
            session.setAttribute("QuickItemListNum", QuickItemList.size());
        }

第二个代码是关于 servlet-context.xml 的,它链接到下面的 MyBatis。

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->

<beans:bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> 
    <beans:property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/> 
</beans:bean>
    <context:component-scan base-package="com.bookshop01" />
    
    <mvc:interceptors>
  <mvc:interceptor>
    <mvc:mapping path="/*/*.do"/> 
    <mvc:mapping path="/*/*/*.do"/> 
      <beans:bean class="com.bookshop01.common.interceptor.ViewNameInterceptor" />
  </mvc:interceptor>
 </mvc:interceptors>
 
    <!-- MultiPartResolver  -->
    <beans:bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
       <beans:property name="maxUploadSize" value="52428800" />
       <beans:property name="maxInMemorySize" value="52428800" />
       <beans:property name="defaultEncoding" value="utf-8" />
    </beans:bean>
    
 
</beans:beans>

最终代码是关于 itemDetail.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> 
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<c:set var="items" value="${itemMap.iDTO}"/>
<c:set var="imageList" value="${itemMap.imageList}"/>
<%
    pageContext.setAttribute("crcn", "\n");
    pageContext.setAttribute("br", "<br/>");
%>        
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
  
<title>Insert title here</title>
<style>
#layer {
    z-index: 2;
    position: absolute;
    top: 0px;
    left: 0px;
    width: 100%;
}

#popup {
    z-index: 3;
    position: fixed;
    text-align: center;
    left: 50%;
    top: 45%;
    width: 300px;
    height: 200px;
    background-color: #ccffff;
    border: 3px solid #87cb42;
}

#close {
    z-index: 4;
    float: right;
}
.modal{
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0);
    transition: 200ms ease-in-out;
    border: 1px solid black;
    border-radius: 10px;
    z-index: 10;
    background-color: white;
    width: 500px;
    max-width: 80%; 
}

.modal .active{
    transform: translate(-50%, -50%) scale(1);
}
.modal-header{
    padding:  10px 15px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid black;
    
}
.modal-header .title{
    font-size: 1.25rem;
    font-weight: bold;
}
.modal-header .close-button{
    cursor: pointer;
    border: none;
    outline: none;
    background: none;
    font-size: 1.25rem;
    font-weight: bold;
}
.modal-body{
    padding: 10px 15px;
}
#overlay {
    position: fixed;
    opacity: 0;
    transition: 200ms ease-in-out;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0,0,0,.5);
    pointer-events: none;
}
#overlay .active{
    opacity: 1;
    pointer-events: all; 
}
</style>
<script type="text/javascript">
$(document).ready(function(){
    function add_cart(ino){
        $.ajax({
            type: "post",
            async: false,
            url: ${contextPath}/
            data: {
                ino:ino
                },
            success : function(data, textStatus){

                if(data.trim()=='add success'){
                        openModal(modal);
                }else if(data.trim()=='existing_presence'){
                        alert("Already choosen");
                    }
                
                },
                error : function(data, textStatus){
                    alert("Error occured"+data);
                } 
            });
        }

        var openModalButtons = document.querySelectorAll('[data-modal-target]');
        var closeModalButtons = document.querySelectorAll('[data-close-button]');
        var overlay = document.getElementById('overlay');

        openModalButtons.forEach(button =>){
            button.addEventListener('click', () =>){
                var modal = document.querySelector(button.dataset.modalTarget)
                openModal(modal);
            })
        })  
        
        overlay.addEventListener('click', () => {
            var modals = document.querySelectorAll('.modal.active')
            modals.forEach(modal => {
                closeModal(modal)
            })
        })

        closeModalButtons.forEach(button =>){
            button.addEventListener('click', () =>){
                var modal = button.closest('.modal')
                closeModal(modal);
            })
        })  
        
        
    function openModal(modal){
        if(modal == null) return
        modal.classList.add('active')
        overlay.classList.add('active') 
            
    }   

    function closeModal(modal){
        if(modal == null) return
        modal.classList.remove('active')
        overlay.classList.remove('active')  
            
    }
function fn_pickup_items(ino, ititle, price, filename){
    var LogOn = document.getElementById("LogOn");
    var isLogOn = LogOn.value;

    if(isLogOn == "false" || isLogOn == ''){
        alert("You can order if you sign in")
    }

    var total_price, final_total_price;
    var pcs = document.getElementById("pcs");

    var form = document.createElement("form");
    var i_ino = document.createElement("input");
    var i_ititle = document.createElement("input");
    var i_sales_price = document.createElement("input");
    var i_filename = document.createElement("input");
    var i_pcs = document.createElement("input");

    i_ino.name = "ino";
    i_ititle.name = "ititle";
    i_sales_price.name = "sales_price";
    i_filename.name = "filename";
    i_pcs.name = "pcs";

    i_ino.value = ino;
    i_ititle.value = ititle;
    i_sales_price.value = sales_price;
    i_filename.value = filename;
    i_pcs.value = pcs;

    form.appendChild(ino);
    form.appendChild(ititle);
    form.appendChild(sales_price);
    form.appendChild(filename);
    form.appendChild(pcs);

    document.body.appendChild(form);
    form.method="post";
    form.action="${contextPath}/pickup/pickupinsert.jsp";
    form.submit();   
}
        
}); 
</script>
</head>
<body>
    <%@ include file="../detailview/header.jsp" %>
    <%@ include file="../detailview/navbar.jsp" %>
    <div class="container">
    <div class="row">
        <div class="col-sm-4">
            <div class="bookimg">
                <img alt="" src="/resources/img/book.jpg">
            </div>
            <div class="stock">
                <label for="stock">Stock</label>                        
                <p>{dto.stock}</p>                          
            </div>  
        </div>
        <div class="col-sm-8">
            <div id="detail_table">
        <table>
            <tbody>
                <tr>
                    <td class="fixed">Net price</td>
                    <td class="active"><span>
                       <fmt:formatNumber  value="${dto.price}" type="number" var="price" />
                         ${price}
                    </span></td>
                </tr>
                <tr class="dot_line">
                    <td class="fixed">Selling price</td>
                    <td class="active"><span>
                       <fmt:formatNumber  value="${dto.price*0.9}" type="number" var="discounted_price"/>
                         ${discounted_price}(10% discount)</span></td>
                </tr>
                <tr>
                    <td class="fixed">Gathering Points</td>
                    <td class="active">${dto.point}P(10% mileage)</td>
                </tr>
                <tr class="dot_line">
                    <td class="fixed"> Additional mileage of points</td>
                    <td class="fixed">Getting 1,000 points if purcahsing more than 10,000 won, 
2,000 points if purchasing 50,000 won or additional mileage 300 points in using delivery service of convenient store</td>
                </tr>
                <tr>
                    <td class="fixed">published date</td>
                    <td class="fixed">
                       <c:set var="pub_date" value="${dto.publishDay}" />
                       <c:set var="arr" value="${fn:split(pub_date,' ')}" />
                       <c:out value="${arr[0]}" />
                    </td>
                </tr>
                <tr>
                    <td class="fixed">Total page</td>
                    <td class="fixed">${dto.totalPage}page</td>
                </tr>
                <tr>
                    <td class="fixed">Delivery fare</td>
                    <td class="fixed"><strong>Free of charge</strong></td>
                </tr>
                <tr>
                    <td class="fixed">Guide to deliver</td>
                    <td class="fixed"><strong>[One-day delivery]</strong> Start one-day delivery!<br> <strong>[Delivery for weekends]</strong>
                        Able to deliver for weekends</TD>
                </tr>
                <tr>
                    <td class="fixed">date to arrive</td>
                    <td class="fixed">Able to get next day if you order in the morning</td>
                </tr>
                <tr>
                    <td class="fixed">
                        <button id="pcs" type="button">Quantity</button>
                    </td>                            
                    </tr>
                </tbody>
            </table>
            <ul>
                <li><a class="buy" href="javascript:fn_pickup_items('${dto.ino}','${dto.ititle}','${dto.sales_price}','${dto.filename}');">Purchase </a></li>
                <li><a class="cart" href="javascript:add_cart('${dto.ino}')">Cart</a></li>          
            </ul>           
            </div>
        </div>
    </div>
</div>
        <div class="container">
        <ul class="nav nav-tabs">
            <li class="active"><a href="#t1">Classification on book</a></li>
            <li><a href="#t2">information on book</a></li>
            <li><a href="#t3">Table of contents & Contents</a></li>
            <li><a href="#t4">Information on writer</a></li>
            <li><a href="#t5">Introduction by writer</a></li>       
        </ul>
            <div class="tab_container">
                <div class="tab_content" id="t1">
                    <h4>Classification on book</h4>
                    <p>${fn:replace(dto.classify,crcn,br)}</p>
                    <c:forEach var="img" items="${imageList}">
                        <img src="${contextPath}/.?">
                    </c:forEach>
                </div>
            </div>
            <div class="tab_content" id="t2">
                <h4>Information on book</h4>
                <p>${fn:replace(dto.prolog,crcn,br)}</p>                
            </div>
            <div class="tab_content" id="t3">
                <h4>Table of contents & Contents</h4>
                <div class="Table_of_Content">Table of contents</div>   
                <p>${fn:replace(dto.TC,crcn,br)}</p>
                <div class="contents">Contents</div>
                <p>${fn:replace(dto.contents,crcn,br)}</p>              
            </div>
            <div class="tab_content" id="t4">
                <h4>Information on writer</h4>                  
                <p>${fn:replace(dto.iwriter,crcn,br)}</p>
                <p>${fn:replace(dto.iwri_pro,crcn,br)}</p>
            </div>
            <div class="tab_content" id="t5">
                <form name="form" method="post" action="#">
                <input type="hidden" name="membno" id="membno">
                <input type="hidden" name="bookcd" id="bookcd" value="100993608">
                <input type="hidden" name="device" value="p">
                <input type="hidden" name="actionType" id="rev_ins_type">
                <input type="hidden" name="review_no" id="rev_ins_no">
                <input type="hidden" name="valuation" id="rev_ins_rate">
                <div class="writeArea">
                    <h3 id="noView">You can be capable of leaving your feeling as reader if you sign in.</h3>       
                    <img src="#" alt="You can be capable of leaving your feeling as reader if you sign in.">
                        <dl>
                        <dt>Grades on book</dt>
                        <dd>
                        <input type="radio" value="1" name="radio_revRate" class="writeRadio">
                        <img src="/resources/img/star.png">
                        <input type="radio" value="2" name="radio_revRate" class="writeRadio">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <input type="radio" value="3" name="radio_revRate" class="writeRadio">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <input type="radio" value="4" name="radio_revRate" class="writeRadio">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <input type="radio" value="4" name="radio_revRate" class="writeRadio">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        <img src="/resources/img/star.png">
                        </dd>
                        <dt>Contents</dt>
                        <dd>
                        <textarea name="review_content" id="review_content" class="writeText"
                        style="height:47px;" onclick="review_popup('login');" 
                        onkeyup="fc_chk_byte(this, 4000);checkByteLength($(this).val(), 'review_content', 'tcount');"
                        hname="contents" required></textarea>
                        <a href="javascript:review popup('login');" 
                        class="mL10 reg-btn">Registration</a>
                        </dd>
                        <dd id="tcount">0/2000(Max 2000 letters)</dd>
                        </dl>                   
                    </div>
                </form>
            </div>                  
        </div>
        <div class="clear"></div>
        <button data-modal-target="#modal"></button>
        <div class="modal" id="modal">
            <div class="modal-header">
                <div class="title"></div>
                <button data-close-button class="close-button">&times;</button>
            </div>
            <div class="modal-body">
            
            </div>
        </div>
        <div class="active" id="overlay"></div>
    </body>
</html> 

标签: javahtmlspringmodel-view-controllermodelandview

解决方案


从您的问题中,我了解到从该行中的地图返回的值是空的。

ItemDTO idto = (ItemDTO) iMap.get("idto");

您看到此错误是因为 Map 不包含与键“idto”相对应的条目。请检查这些值是否应该存在于地图中,如果要存在该条目,那么为什么该条目丢失了。

您可以在同一行中执行的其他操作

ItemDTO idto = (ItemDTO) iMap.getOrDefault("idto", "DefaultValue");

这将尝试找到与键“idto”对应的条目,如果该条目不存在,则返回默认值“DefaultValue”。

您可以查看更多详细信息https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#getOrDefault-java.lang.Object-V-


推荐阅读