spring boot thymleaf资源不适用于所有页面

时间:2018-02-04 10:50:20

标签: java jquery spring-boot thymeleaf

我是他们新的模板引擎。我有一个使用他们的模板引擎的spring boot web应用程序。以下是我的项目结构。

enter image description here

我有home.html我在其中调用了标题(在header.html)和页脚(在footer.html中)片段,而对于内容部分,我调用了另一个是familytree的片段(其中是在familytree.html),到目前为止,每件事情都很好。当我运行spring boot应用程序时,我得到了预期的视图。

问题:现在我创建了另一个名为viewfulltree.html的html页面(复制了home.html页面并粘贴在同一目录中,并将其重命名为viewfulltree.html,以确保每件事情都像与home.html相同)。此viewfulltree.html只是home.html的另一个副本,名称不同。现在,当我从我的控制器类返回到这个viewfulltree.html页面时,它无法找到css,js,images文件,因此视图混乱,没有样式,没有动作,没有图像。我不确定我在配置中犯了什么错误。由于两者都在同一目录中并使用相同的header.html片段,所以我希望两者都能以相同的方式访问静态内容。

控制器类::

@Controller
public class DefaultController {

    @GetMapping("/")
    public String defaultHome(){
        return "redirect:home";
    }

    @GetMapping(value = "/home", produces = MediaType.APPLICATION_JSON_VALUE)
    public String home(Model model){
        List<TreeNode> nodesList = null;
        nodesList = getNodes();
        ObjectMapper jsonMapper = new ObjectMapper();
        try {
            List<String> menuItems = new ArrayList<>();
            List<FamilyTree> treesList = familyTreeService.findAll();
            treesList.forEach( tree ->{
                menuItems.add(tree.getFamilyTreeName());
            });
            if(!menuItems.isEmpty()){
                model.addAttribute("menuItems", menuItems);
            }

            model.addAttribute("ft_items", 
jsonMapper.writeValueAsString(nodesList));
            model.addAttribute("profile", new Profile());
        } catch (JsonProcessingException e) {
            log.warn(e.getMessage());
        }
        return "/home";
    }

    @GetMapping(value = "/viewfulltree/{familyTreeId}", produces = MediaType.APPLICATION_JSON_VALUE)
    public String getTree(@PathVariable("familyTreeId") String familyTreeId, Model model){
        List<TreeNode> nodesList = null;
        nodesList = getTreeNodes(Long.valueOf(familyTreeId));
        ObjectMapper jsonMapper = new ObjectMapper();
        try {
            List<String> menuItems = new ArrayList<>();
            List<FamilyTree> treesList = familyTreeService.findAll();
            treesList.forEach( tree ->{
                menuItems.add(tree.getFamilyTreeName());
            });
            if(!menuItems.isEmpty()){
                model.addAttribute("menuItems", menuItems);
            }

            model.addAttribute("ft_items", jsonMapper.writeValueAsString(nodesList));
            model.addAttribute("profile", new Profile());
        } catch (JsonProcessingException e) {
            log.warn(e.getMessage());
        }
        return "/viewfulltree";
    }
}

注意:运行应用程序时我在这两个文件之间找到的唯一区别是url。我从浏览器转到home.html源代码,然后点击它给出了下面的url和找到的css文件的任何css文件。

found:http://localhost:7030/familytree/webjars/bootstrap/3.3.7/css/bootstrap.min.css

但是当我从浏览器查看viewfulltree.html来源并点击任何css文件时,它给了我下面的url并找不到css文件,给出了404错误。

not-found(404):http://localhost:7030/familytree/viewfulltree/webjars/bootstrap/3.3.7/css/bootstrap.min.css

我无法弄明白我需要在哪里更改代码。请告诉我如果需要提供代码的任何部分。

home.html的:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Family-tree</title>
    <div th:replace="header :: header-css" ></div>
    <div th:replace="familytree :: family-tree-css" ></div>
</head>
<body>
    <div th:replace="header :: header" ></div>
    <section layout:fragment="custom-content">
        <div th:replace="familytree :: family-tree" ></div>
    </section>

</body>
</html>

header.html中:

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <div th:fragment="header-css">
            <!-- this is header css -->
            <link rel="stylesheet" type="text/css" th:href="@{webjars/bootstrap/3.3.7/css/bootstrap.min.css}" />

        <style>
        h1{
            color:#0000FF;
        }

        h2{
            color:#FF0000;
        }

        footer{
            margin-top:60px;
        }
        </style>
    </div>
    </head>
    <body>
    <div th:fragment="header">
        <!-- this is header -->
        <nav class="navbar navbar-inverse" id="ft_menuItem">
            <div class="container">
                <div class="navbar-header">
                    <a class="navbar-brand active" th:href="@{/home}">Family Tree</a>
                </div>
                <div id="navbar" class="collapse navbar-collapse">
                    <ul class="nav navbar-nav">
                        <li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Trees
                            <span class="caret"></span></a>
                                <ul class="dropdown-menu">
                                <li th:unless="${#lists.isEmpty(menuItems)}" th:each="menuItem : ${menuItems}">
                                    <a th:href="@{/viewfulltree/2}" th:text="${menuItem}">Create new Tree</a>
                                </li>
                                <li class="divider"></li>
                                <li><a th:href="@{/createtreeform}">Create new Tree</a></li>
                            </ul>
                        </li>
                        <li><a th:href="@{/events}">Event Calendar</a></li>
                        <li><a th:href="@{/aboutus}">About Us</a></li>
                    </ul>
                </div>
            </div>
        </nav>
        <script th:src="@{webjars/jquery/3.1.1/jquery.min.js}"></script>
        <script th:src="@{webjars/bootstrap/3.3.7/js/bootstrap.min.js}"></script>
    </div>
    </body>
    </html>

familytree.html

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Family-tree</title>
        <div th:fragment="family-tree-css">
        <link rel="stylesheet" th:href='@{css/jquery-ui-1.10.2.custom.css}'/>
        <link th:href='@{css/primitives.latest.css?3710}' media="screen" rel="stylesheet" type="text/css" />

    <style type="text/css">

    .table-user-information > tbody > tr {
        border-top: 1px solid rgb(221, 221, 221);
    }

    .table-user-information > tbody > tr:first-child {
        border-top: 0;
    }


    .table-user-information > tbody > tr > td {
        border-top: 0;
        font-size: 13px;
    }
    .toppad
    {
        margin-top:20px;
    }
        </style>
        </div>

    </head>
    <body>
    <div th:fragment="family-tree">
    <div class="container-fluid">
            <div class="row">
                <div class="col-md-8 col-lg-8 nopadding">
                    <div id="btn50">50%</div>
                    <div id="btn80">80%</div>
                    <div id="btn100">100%</div>
                    <div id="btn130">130%</div>
                    <div id="orgdiagram"  style="height: 480px; overflow: hidden; border-style: dotted; border-width: 1px;"></div>
                </div>
                <div class="col-md-4 col-lg-4 nopadding">
                    <div class="panel panel-info">
                        <div class="panel-heading">
                          <h4 class="panel-title">full Name here</h4>
                        </div>
                        <div class="panel-body">
                          <div class="row">
                                <div class=" col-md-12 col-lg-12 "> 
                                  <table class="table table-user-information">
                                    <tbody>
                                      <tr>
                                        <td><img alt="User Pic" src="images/male.png" class="img-circle img-responsive" width="50px"></img></td>
                                      </tr>
                                      <tr>
                                        <td>Gender</td>
                                        <td>Female</td>
                                      </tr>
                                      <tr>
                                        <td>Age</td>
                                        <td>30</td>
                                      </tr>
                                      <tr>
                                        <td>Date of Birth:</td>
                                        <td>06/23/2013</td>
                                      </tr>
                                      <tr>
                                        <td>Anniversary Date</td>
                                        <td>01/24/1988</td>
                                      </tr>
                                      <tr>
                                        <td>Child Of</td>
                                        <td>Parent Name goes here</td>
                                      </tr>
                                      <tr>
                                        <td>Marital status</td>
                                        <td>Married</td>
                                      </tr>
                                      <tr>
                                        <td>No. of Children</td>
                                        <td>4</td>
                                      </tr>
                                      <tr>
                                        <td>Phone Number</td>
                                        <td>
                                            123-4567-890(Landline)<br></br>
                                            555-4567-890(Mobile)
                                        </td>
                                      </tr>
                                    </tbody>
                                  </table>
                                </div>
                          </div>
                        </div>
                        <div class="panel-footer">
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div id="create-Profile-form" title="Create new user">
            <p class="validateTips">All form fields are required.</p>


            <form id="add-profile" th:object="${profile}">
                <table>
                    <tr>
                        <td>
                        </td>
                        <td>
                            <input type="hidden" id="in_parentId" th:field="*{parentId}"></input>
                        </td> 
                    </tr>
                    <tr>
                        <td>
                            Full Name
                        </td>
                        <td>
                            <input type="text" id="in_profileName" th:field="*{profileName}"/>
                        </td> 
                    </tr>
                    <tr>
                        <td>
                            First Name
                        </td>
                        <td>
                        <input type="text" id="in_firstName" th:field="*{firstName}"/>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            Last Name
                        </td>
                        <td>
                            <input type="text" id="in_lastName" th:field="*{lastName}"/>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            Gender
                        </td>
                        <td>
                            <select id="in_gender" th:field="*{gender}" >
                                <option th:value="male" th:text="Male">Male</option>
                                <option th:value="female" th:text="Fe-Male">Fe-Male</option>            
                            </select>

                        </td>
                    </tr>
                </table>    
            </form>
        </div>
        <script type="text/javascript" th:src='@{js/bootstrap.min.js}'></script>
        <script type="text/javascript" th:src='@{js/jquery-1.9.1.js}'></script>
        <script type="text/javascript" th:src='@{js/jquery-ui-1.10.2.custom.min.js}'></script>
        <script type="text/javascript" th:src='@{js/primitives.min.js?3710}'></script>
        <script th:inline="javascript">
        /*<![CDATA[*/
    jQuery(document).ready(function () {
        var dialog, form;
        var treeNodes = [[${ft_items}]];

        var options = new primitives.orgdiagram.Config();
        var items = [];
        var buttons = [];

        $('form').on('submit', function(e){
            e.preventDefault();
            return false;
        });
        dialog = $("#create-Profile-form").dialog({
            autoOpen: false,
            height: 400,
            width: 350,
            modal: true,
            buttons: {
                "Create an Profile": function(){

                    var profileData = {};
                    profileData.profileName = $("#in_profileName").val();
                    profileData.firstName = $("#in_firstName").val();
                    profileData.lastName = $("#in_lastName").val();
                    profileData.gender = $("#in_gender").val(),
                    profileData.parentId = $("#in_parentId").val();

                    $.ajax({
                        type: "POST",
                        url: "profile/save",
                        async: true,
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json'
                        },
                        data: JSON.stringify(profileData),
                        success: function(result){
                            console.log(result);
                            dialog.dialog("close");
                            items = treeNodesToItems(JSON.stringify(result.object));
                            updateTreeWithItems(items);
                            $("#add-profile").trigger("reset");
                        },
                        error: function(jqXhr, textStatus, errorThrown){
                            console.log(textStatus);
                             alert('error:' +textStatus + '\n:' +errorThrown);
                        }
                    });
                    dialog.dialog( "close" );
                },
                Cancel: function() {
                  dialog.dialog( "close" );
                }
              },
              close: function() {
                //form[ 0 ].reset();
                //allFields.removeClass( "ui-state-error" );
                $("#add-profile").trigger("reset");
              }
        });

        dialog.dialog("close");

        buttons.push(new primitives.orgdiagram.ButtonConfig("add", "ui-icon-person", "Add"));
        buttons.push(new primitives.orgdiagram.ButtonConfig("delete", "ui-icon-close", "Delete"));

        items = treeNodesToItems(treeNodes);

        options.pageFitMode = primitives.common.PageFitMode.None;
        options.items = items;
        options.buttons = buttons;          
        options.cursorItem = 0;
        options.hasSelectorCheckbox = primitives.common.Enabled.False;
        options.onButtonClick = function (e, data) {
            switch (data.name) {
                case "delete": 
                        if(data.context.parent==null || data.context.parent==''){
                            alert('you can not delete the parent node')
                        }
                        else{
                            $.ajax({
                                type: "DELETE",
                                url: "profile/delete/"+data.context.id,
                                //dataType: "json",
                                headers: {
                                    'Accept': 'application/json',
                                    'Content-Type': 'application/json'
                                } ,
                                success: function(result){
                                    items = treeNodesToItems(JSON.stringify(result.object));
                                    updateTreeWithItems(items);
                                    console.log(result);
                                },
                                error: function(jqXhr, textStatus, errorThrown){
                                    console.log(textStatus);
                                    alert('error:' +textStatus + '\n:' +errorThrown);
                                }
                            });
                        }
                    break;
                case "add": 
                    /* get items collection */
                    //var items = jQuery("#orgdiagram").orgDiagram("option", "items");
                    /* create new item */
                    $('#in_parentId').val(data.context.id);
                    dialog.dialog( "open" );
                    break;
            }
        };
        jQuery("#orgdiagram").orgDiagram(options);

        $("#btn50").button().click(function () { onScale(0.5); });
        $("#btn80").button().click(function () { onScale(.8); });
        $("#btn100").button().click(function () { onScale(1); });
        $("#btn130").button().click(function () { onScale(1.3); });
    });

    function treeNodesToItems(treeNodes){
        var itemsToIterate = JSON.parse(treeNodes);
        var new_items = [];
        for(var i=0; i<itemsToIterate.length; i++){
            new_items.push(
                    new primitives.orgdiagram.ItemConfig({
                        id: itemsToIterate[i].id,
                        parent: itemsToIterate[i].parent,
                        title: itemsToIterate[i].title,
                        description: itemsToIterate[i].description,
                        image: "images/"+itemsToIterate[i].gender+".png"
                    }));
        }
        return new_items;
    }

    function updateTreeWithItems(ft_items){
        jQuery("#orgdiagram").orgDiagram({
            items: ft_items
        });
        jQuery("#orgdiagram").orgDiagram("update", /*Refresh: use fast refresh to update chart*/ primitives.orgdiagram.UpdateMode.Refresh);
    }


    function onScale(scale) {
        if (scale != null) {
            jQuery("#orgdiagram").orgDiagram({ scale: scale });
        }
        jQuery("#orgdiagram").orgDiagram("update", primitives.orgdiagram.UpdateMode.Refresh);
    }

         /*]]>*/
        </script>
    </div>

    </body>
    </html>

1 个答案:

答案 0 :(得分:1)

转到您的header-css片段并更新您的css链接

<link rel="stylesheet" type="text/css" th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}" />