Spring 3 mvc and tiles - populate *.jsp page with

2019-09-02 04:03发布

I'm using Spring 3 mvc and Apache Tiles 3.0.

I don't know how to insert some data in *jsp page which I will later use for insert in template tiles *.jsp page.

Tiles defiontions file looks like this:

<tiles-definitions>
    <definition name="base.definition" template="/WEB-INF/views/layout.jsp">
        <put-attribute name="title" value=""  />
        <put-attribute name="banner" value="/WEB-INF/views/banner.jsp" />
        <put-attribute name="path" value="" />
        <put-attribute name="menu" value="/WEB-INF/views/menu.jsp" />
        <put-attribute name="data" value="" />
        <put-attribute name="position" value="" />
    </definition>   
    <definition name="/" extends="base.definition">
        <put-attribute name="title" value="Home" />
        <put-attribute name="path" value="/WEB-INF/views/path.jsp" />
        <put-attribute name="data" value="/WEB-INF/views/data.jsp" />
        <put-attribute name="position" value="/WEB-INF/views/position.jsp" />
    </definition>   
</tiles-definitions>

I want to populate "/WEB-INF/views/data.jsp" page with some data, for example - rows form database, and after that to use it like part of template page (in this case it's layout page).

Layout.jsp page looks like this:

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title><tiles:insertAttribute name="title" /></title>
    <link rel="stylesheet" href="<spring:theme code='body' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='page' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='banner' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='path' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='main' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='menu' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='source' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='position' />" type="text/css" />
    <link rel="stylesheet" href="<spring:theme code='data' />" type="text/css" />
</head>

    <body>
        <div id="page">
            <div id="banner">
                <tiles:insertAttribute name="banner" />
            </div>
            <div id="path">
                <tiles:insertAttribute name="path" />
            </div>
            <div id="main">
                <span id="menu">
                    <tiles:insertAttribute name="menu" />
                </span>
                <span id="source">
                    <span id="position">
                        <tiles:insertAttribute name="position" />
                    </span><br/>
                    <span id="data">
                        <span id="dataSource">
                            <tiles:insertAttribute name="data" />
                        </span>
                        <span id="dataSource">
                            <tiles:insertAttribute name="data" />
                        </span>
                        <span id="dataSource">
                            <tiles:insertAttribute name="data" />
                        </span>
                    </span>
                </span> 
            </div>
        </div>
    </body>
</html>

If I put <tiles:insertAttribute name="rowsFromDb" in "/WEB-INF/views/data.jsp" I've gotten an error:

SEVERE: Servlet.service() for servlet jsp threw exception
org.apache.tiles.template.NoSuchAttributeException: Attribute 'rowsFromDb' not found.

I don't know to how to send data to this attribute 'rowsFromDb'! I only know how to send data to variables that are on the layout page (template - parrent)

3条回答
劫难
2楼-- · 2019-09-02 04:17

Founded solution. Thanks all for helped me!

Code in controller:

...

@RequestMapping(value={"/"},method=RequestMethod.GET)
        public String home(HttpServletRequest request,Model model){
            JdbcTemplate jdbc=new JdbcTemplate(dataSource(request));

            String sql="SELECT * FROM products ORDER BY id ASC";        
            List<Product>products=jdbc.query(sql,new ProductMapper());

            sql="SELECT * FROM category ORDER BY (id)";
            List<Category>categories=jdbc.query(sql, new CategoryMapper());

            model.addAttribute("products", products);
            model.addAttribute("categories",categories);

            return "/";
        }

        ...

Code in *.jsp page

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:forEach var="p" items="${products}"> 
    <div id="dataRow">
        <form:form method="POST" action="/shoppingCart">        
            <div id="dataPicture"><img src="<%=request.getContextPath()%>/images/hard_diskovi/${p.getPicture()}"/></div>
            <div id="dataName">${p.getName()}</div>
            <div id="dataPrice">
                Price: 
                <fmt:formatNumber minFractionDigits="2" maxFractionDigits="2" value="${p.getPrice()}"/> 
                euro
            </div>
            <input type="hidden" value="${p.getId()}"/>
            <input id="dataSubmit" type="submit" value="add"/>
        </form:form>
    </div>  
</c:forEach>

Conclusion: data for page that isn't a template it need to send from controller and on the target page use 'jsp' or 'jstl' or ...

查看更多
迷人小祖宗
3楼-- · 2019-09-02 04:24

If you're intending to hold a list of records in the attribute rowsFromDb, then you should populate this in your controller and set the list in the model. Then in data.jsp you can iterate this list using the <c:forEach> tag. For example (a madeup example to illustrate the point):

Controller

@RequestMapping("/listRows")
public ModelAndView listRows() {
    List<Row> rows = myRepository.getAllRows(); // Hide the DB query code behind a repository
    ModelAndView modelAndView = new ModelAndView("/");
    modelAndView.addObject("rowsFromDb", rows); // Set the data in the model
    return modelAndView;
}

data.jsp

<c:forEach items="${rowsFromDb}" var="row">
    <c:out value="${row.someProperty}"/>
<c:forEach>

You should avoid doing any database query directly in the JSP itself (and avoid any Java in the JSP where possible). The JSP should just deal with rendering the data it is given by the controller.

查看更多
Bombasti
4楼-- · 2019-09-02 04:26

You can use Tiles org.apache.tiles.preparer.ViewPreparer for this purpose.

Create a new class that implements org.apache.tiles.preparer.ViewPreparer in your source folder. For example:

package com.example.tiles;
import ...

public class MyMenuPreparer implements ViewPreparer {

   @Override
   public void execute(TilesRequestContext tilesContext, AttributeContext attributeContext) {

      // The code here will be executed before rendering the view.      
      // For example, you can check for security (Spring Security)
      // or you can execute query to database to retrieve list of menus

      ...

      // You can add result to your request scope:
      tilesContext.getRequestScope().put("rowsFromDb", result);

      // To retrieve the value in a JSP:
      // <c:forEach var="item" items="${rowsFromDb}">
      //    ...
      // </c:forEach>


      // Or you can add it as attribute for the view
      attributeContext.putAttribute("rowsFromDb", result, true);

   }

}

In your Tiles definition, you must add preparer attribute in the definition, such as:

<definition name="menu" 
    template="/WEB-INF/layouts/menu.jspx" 
    preparer="com.example.tiles.MyMenuPreparer">
    ...
</definition>
查看更多
登录 后发表回答