有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在模板解析Spring引导时出错

我用模块(患者、笔记、报告、域)创建了Maven多模块应用程序。问题出在使用MongoDB的模块注释中

当我想运行时,我遇到了这个问题:GET addNote view-@GetMapping(“/note/add/{patientId}”)。GET note list视图工作正常,其他视图也正常

控制台问题:

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Tue Aug 24 18:47:06 CEST 2021
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "URL [file:src/main/resources/templates/note/add.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "URL [file:src/main/resources/templates/note/add.html]")
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:366)
    at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:190)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1396)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1141)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:831)
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "patientNote.patientId" (template: "note/add" - line 43, col 21)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
    at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
    ... 48 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "patientNote.patientId" (template: "note/add" - line 43, col 21)
    at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:292)
    at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
    at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
    at org.thymeleaf.standard.expression.LinkExpression.resolveParameters(LinkExpression.java:339)
    at org.thymeleaf.standard.expression.LinkExpression.executeLinkExpression(LinkExpression.java:285)
    at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:85)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
    at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
    at org.thymeleaf.standard.processor.AbstractStandardExpressionAttributeTagProcessor.doProcess(AbstractStandardExpressionAttributeTagProcessor.java:144)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
    at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
    at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
    at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314)
    at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleOpenElementEnd(TemplateHandlerAdapterMarkupHandler.java:304)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:278)
    at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleOpenElementEnd(OutputExpressionInlinePreProcessorHandler.java:186)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:124)
    at org.attoparser.HtmlElement.handleOpenElementEnd(HtmlElement.java:109)
    at org.attoparser.HtmlMarkupHandler.handleOpenElementEnd(HtmlMarkupHandler.java:297)
    at org.attoparser.MarkupEventProcessorHandler.handleOpenElementEnd(MarkupEventProcessorHandler.java:402)
    at org.attoparser.ParsingElementMarkupUtil.parseOpenElement(ParsingElementMarkupUtil.java:159)
    at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:710)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
    ... 50 more
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'patientId' cannot be found on null
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:406)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:92)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:337)
    at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:265)
    ... 74 more

NoteController:

@RestController
public class NoteController {

    @Autowired
    private NoteService noteService;

    /* GET note list view */
    @GetMapping("/note/list/{patientId}")
    public ModelAndView getAllNotesByPatientId(@PathVariable("patientId") String patientId, Model model) {
        ModelAndView mav = new ModelAndView();
        if (patientId != null) {
            model.addAttribute("noteList", noteService.findAllNotesByPatientId(patientId));
            model.addAttribute("patientId", patientId);
            mav.setViewName("note/list");
        }
        log.info("LOG: Number of note on list by patient id: " + noteService.findAllNotesByPatientId(patientId).size());
        return mav;
    }

    /* GET addNote view */
    @GetMapping("/note/add/{patientId}")
    public ModelAndView addNote(@ModelAttribute("patientId") String patientId, Model model) {
        ModelAndView mav = new ModelAndView();
        Note note = new Note();
        model.addAttribute("note", note);
        model.addAttribute("patientId", patientId);
        mav.setViewName("note/add");
        log.info("LOG: Show addNote form");
        return mav;

    }

    /* POST save addNote */
    @PostMapping(value = "/note/save/{patientId}")
    public ModelAndView save(@PathVariable("patientId") String patientId, @Valid Note note, BindingResult result, Model model) {
        ModelAndView mav = new ModelAndView();
        if (!result.hasErrors()) {
            model.addAttribute("note", note);
            model.addAttribute("patientId", patientId);
            mav.setViewName("note/add");
            return mav;
        }
        PatientNote patientNote = noteService.findNoteById(patientId);
        if (patientNote != null) {
            patientNote = new PatientNote(patientId);
        }
        patientNote.getNotes().add(note);
        noteService.createNote(patientNote);
        model.addAttribute("noteList", noteService.findAllNotesByPatientId(patientId));
        mav.addObject("patientId", patientId);
        mav.setViewName("redirect:/note/list/{patientId}");
        log.info("Add Note " + note.toString());
        return mav;
    }
}

患者注意:

@Document(collection = "PatientNote")
public class PatientNote {
    
    @Field("patientId")
    private String patientId;

    @Field("notes")
    private List<Note> notes;

    public PatientNote() {
        this.notes = new ArrayList<>();
    }

    public PatientNote(String patientId) {
        super();
        this.patientId = patientId;
    }

    public String getPatientId() {
        return patientId;
    }

    public void setPatientId(String patientId) {
        this.patientId = patientId;
    }

    public List<Note> getNotes() {
        return notes;
    }

    public void setNotes(List<Note> notes) {
        this.notes = notes;
    }

}

注意:

public class Note {
    
    @Field("note")
    @NotBlank(message = "Note field is mandatory.")
    private String note;
    
    public Note() {

    }

    public Note(String note) {
        this.note = note;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

}

NoteRepository:

public interface NoteRepository extends MongoRepository<PatientNote, String> {

    List<PatientNote> findNotesByPatientId(String patientId);

    Optional<PatientNote> findById(String patientId);
}

模板-注意/添加。html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">
    
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Add Note</title>

<!-- Bootstrap -->
<link rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
    integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l"
    crossorigin="anonymous">
</head>

<body>
    <nav class="navbar navbar-expand-lg navbar-light" style="background-color: #e3f2fd;">
        <div class="container-fluid">
            <a class="navbar-brand" href="#"> <img
                th:src="@{/images/logo-01.png}" alt="" width="60" height="68"
                class="d-inline-block align-text-center"> Mediascreen
            </a>

            <button class="navbar-toggler" type="button" data-toggle="collapse"
                data-target="#navbarToggler" aria-controls="navbarToggler"
                aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>

            <div class="collapse navbar-collapse" id="navbarToggler">
                <ul class="navbar-nav ml-auto">
                    <li class="nav-item"><a class="nav-link" href="http://localhost:8081/patient/list">Patients</a></li>
                    <li class="nav-item"><a class="nav-link active" aria-current="page" href="/patient/list">Notes</a></li>
                    <li class="nav-item"><a class="nav-link" href="http://localhost:8080/patient/list">Reports</a></li>
                </ul>
            </div>
        </div>
    </nav>
    
    <div class="container col-md-12 mb-2">
        <div class="row">           
            <form action="#" th:action="@{/note/save/{patientId}(patientId=${patientNote.patientId})}" th:object="${patientId}" method="post" class="form-horizontal" style="width: 100%">
                <div class="form-group">
                    <label for="patientId" class="col-sm-2 control-label">Patient ID</label>
                    <div class="col-sm-12">
                        <input type="text" th:field="*{patientId}" id="patientId" placeholder="PatientID" class="col-4" readonly="true">
                        <p class="text-danger" th:if="${#fields.hasErrors('patientId')}" th:errors="*{patientId}"></p>
                    </div>
                </div>
                <div class="form-group">
                    <label for="note" class="col-sm-2 control-label">Note</label>
                    <div class="col-sm-12">
                        <textarea input type="text" th:field="*{note.note}" id="note" placeholder="Add note for patient." class="col-4" rows="6"></textarea>
                        <p class="text-danger" th:if="${#fields.hasErrors('note.note')}" th:errors="*{note.note}"></p>
                    </div>
                </div>
                
                <div class="form-group">
                    <div class="col-sm-12">
                        <input class="btn btn-success btn-sm" type="submit" value="Save">
                        <a th:href="@{'/note/list/' + ${patientId}}" class="btn btn-success btn-sm">Cancel</a>
                    </div>
                </div>
            </form>
        </div>
    </div>
    
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
        integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
        crossorigin="anonymous"></script>
    <script
        src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
        integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
        crossorigin="anonymous"></script>
    <script
        src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js"
        integrity="sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF"
        crossorigin="anonymous"></script>

</body>

</html>

共 (1) 个答案

  1. # 1 楼答案

    从错误消息中

    Exception evaluating SpringEL expression: "patientNote.patientId" (template: "note/add" - line 43, col 21)

    必须在addNote函数中设置patientNote的值

    /* GET addNote view */
    @GetMapping("/note/add/{patientId}")
    public ModelAndView addNote(@ModelAttribute("patientId") String patientId, Model model) {
        ModelAndView mav = new ModelAndView();
        Note note = new Note();
        model.addAttribute("note", note);
        model.addAttribute("patientId", patientId);
    
        >>>>>
        PatientNote patientNote = new PatientNote();
        model.addAttribute("patientNote", patientNote);
        <<<<<
    
        mav.setViewName("note/add");
        log.info("LOG: Show addNote form");
        return mav;
    
    }