java - Spring Boot 2.1.x JSP 文件找到但未呈现
问题描述
我目前正在将一个小型应用程序迁移到 SpringBoot。我们有遗留代码,我希望通过将登录页面挂钩到 SpringBoot,我能够让 Web 应用程序的 JSP/JS 文件处理其余部分。
目前我已经成功地将我们滚动到 Spring 5,并使用 SpringBoot 2.1.8。
POM 片段:应用程序使用 Spring 提供的 Tomcat 默认值,并已拉入相关的 Jasper/JSTL JARS 以便 Tomcat 可以读取
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
根据这篇DZone 文章,我构建了一个小控制器来处理登录过程
@Controller
public class LoginController {
@Resource
private UserSessionService userSessionService;
@GetMapping(value = "/")
public String index() {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "LoginController: Hit /, returning index.jsp");
return "index";
}
@GetMapping(value = "/login")
public String login() {
Logger.getLogger(this.getClass().getName())
.log(Level.SEVERE, "LoginController: Hit /login, returning login.jsp");
return "login";
}
@GetMapping(value = "/loginFailed")
public String loginError(Model model) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "LoginController: Failed to login");
model.addAttribute("error", "true");
return "login";
}
@GetMapping(value = "/logout")
public String logout(SessionStatus session) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "LoginController: Logging out");
SecurityContextHolder.getContext().setAuthentication(null);
session.setComplete();
return "redirect:/login";
}
@PostMapping(value = "/postLogin")
public String postLogin(Model model, HttpSession session) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "LoginController: postLogin");
return "redirect:/";
}
}
login.jsp:遗留代码,修改为调用控制器。我正在尽最大努力让 Spring Security 处理调用我的 AuthenticaionProvider 和我的数据库的过程(为了简洁起见,我只显示关键区域的东西,无论如何页面都相当简单
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html>
<head>
<%@page contentType="text/html" pageEncoding="UTF-8" %>
<link type="text/css" href="${contextPath}/css/login.css" rel="stylesheet"/>
<link rel="stylesheet" href="${contextPath}/css/font-awesome/css/font-awesome.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body class="loginBody">
.
.
<div class="formdiv">
<form name='f' action='doLogin' method='POST'>
<div style="width: 215px; margin: 0 auto; ">
<label class="loginLabel">Login</label><br>
<input type="text" name="username".../>
<label class="loginLabel">Password</label><br>
<input type="password" size="25" name="password".../><br>
<input type="submit" class="header_btn_class" value="Login" id="loginButton" style="..."/>
</div>
</form>
</div>
.
.
</body>
</html>
index.jsp:遗留代码,处理主登陆页面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<%@include file="beforeHtml.jsp" %>
<html>
<head>
<%@include file="head.jsp" %>
<script type="text/javascript" src="${contextPath}/js/home/home.js"></script>
<title></title>
</head>
<body>
<%@include file="top.jsp" %>
<h2 style="margin-left: 60px;">Release Notes</h2>
<div id="changeLog" style=...">
</div>
<jsp:include page="../html/Changelog.html"/>
</body>
</html>
我有一个名为SecurityConfig的文件,让 SpringBoot 知道绕过“默认”登录页面:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/xxx").hasAnyRole("ADMIN", "USER")
.and()
.authorizeRequests().antMatchers("/login", "/resource/**").permitAll()
.and()
.formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password").permitAll()
.loginProcessingUrl("/doLogin")
.successForwardUrl("/postLogin")
.failureUrl("/loginFailed")
.and()
.logout().logoutUrl("/doLogout").logoutSuccessUrl("/logout").permitAll()
.and()
.csrf().disable();
}
我的application.properties文件中有这些字段
server.port=8888
server.servlet.context-path=/xxx
server.tomcat.additional-tld-skip-patterns=*mchange-commons-java*.jar
spring.mvc.view.prefix=/WEB-INF/view/jsp/
spring.mvc.view.suffix=.jsp
spring.mvc.servlet.load-on-startup=1
所有这些放在一起使我可以正常登录我请求的 URL localhost:8888/xxx/login
,然后登录,查看日志 Spring 找到我的设置并正常登录。问题是当它去获取登陆页面时,该页面是一个名为index.jsp
. 根据 SpringBoot/Application 的日志记录
Oct 09, 2019 2:44:37 PM org.springframework.core.log.LogFormatUtils traceDebug
FINE: GET "/xxx/login", parameters={}
Oct 09, 2019 2:44:37 PM org.springframework.web.servlet.handler.AbstractHandlerMapping getHandler
FINE: Mapped to public java.lang.String com.rhdjapan.xxx.controllers.LoginController.login()
Oct 09, 2019 2:44:37 PM com.xx.xxx.controllers.LoginController login
SEVERE: LoginController: Hit /login, returning login.jsp
Oct 09, 2019 2:44:37 PM org.springframework.web.servlet.view.ContentNegotiatingViewResolver getBestView
FINE: Selected 'text/html' given [text/html,...]
Oct 09, 2019 2:44:37 PM org.springframework.web.servlet.view.AbstractView render
FINE: View name 'login', model {}
Oct 09, 2019 2:44:37 PM org.springframework.web.servlet.view.InternalResourceView renderMergedOutputModel
FINE: Forwarding to [/WEB-INF/view/jsp/login.jsp]
Oct 09, 2019 2:44:38 PM org.springframework.web.servlet.FrameworkServlet logResult
FINE: Completed 200 OK
Oct 09, 2019 2:44:42 PM com.xx.xxx.services.common.security.service.UserDetailsServiceImpl loadUserByUsername
SEVERE: loadUserByUsername: looking up user [admin]
Oct 09, 2019 2:44:42 PM com.xx.xxx.services.common.security.service.UserDetailsServiceImpl loadUserByUsername
SEVERE: loadUserByUsername: userId found = [1111111]
Oct 09, 2019 2:44:42 PM org.springframework.core.log.LogFormatUtils traceDebug
FINE: "FORWARD" dispatch for POST "/xxx/postLogin", parameters={username:[admin], password:[admin]}
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.handler.AbstractHandlerMapping getHandler
FINE: Mapped to public java.lang.String com.xx.xxx.controllers.LoginController.postLogin(org.springframework.ui.Model,javax.servlet.http.HttpSession)
Oct 09, 2019 2:44:42 PM com.xx.xxx.controllers.LoginController postLogin
SEVERE: LoginController: postLogin
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.view.AbstractView render
FINE: View name 'redirect:', model {}
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.FrameworkServlet logResult
FINE: Exiting from "FORWARD" dispatch, status 302
Oct 09, 2019 2:44:42 PM org.springframework.core.log.LogFormatUtils traceDebug
FINE: GET "/xxx/", parameters={}
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.handler.AbstractHandlerMapping getHandler
FINE: Mapped to public java.lang.String com.xx.xxx.controllers.LoginController.index()
Oct 09, 2019 2:44:42 PM com.xx.xxx.controllers.LoginController index
SEVERE: LoginController: Hit /, returning index.jsp
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.view.ContentNegotiatingViewResolver getBestView
FINE: Selected 'text/html' given [text/html, ...]
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.view.AbstractView render
FINE: View name 'index', model {}
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.view.InternalResourceView renderMergedOutputModel
FINE: Forwarding to [/WEB-INF/view/jsp/index.jsp]
Oct 09, 2019 2:44:42 PM org.springframework.web.servlet.FrameworkServlet logResult
FINE: Completed 200 OK
这就是问题所在:虽然成功找到 JSP 文件,但页面没有呈现。我返回了一个空的 HTML 文件,并且使用 Web 调试器 (chrome) 仅显示 15 个空白行的来源。index.jsp
我认为它是我文件的长度;
我的问题是双重的
- HTML/JSP 未在我的屏幕上呈现的原因可能是什么?
- 如果有修复,对于我需要移动到 SpringBoot 下工作的所有其他遗留 JSP 文件,它们是否都需要类似的过程?
谢谢!
更新 为简洁起见,有人问我制作的WAR的结构,当我拉起档案时结构是这样的
WAR
|____css
|____dashboard_view
|____excel
|____images
|____jquery
|____js
|____jsp
|____META-INF
|____org
|____third-party
|____WEB-INF
|________classes
|________lib
|________view
|____________html
|____________jsp
|_________________index.jsp
|_________________login.jsp
考虑到我提供的登录和索引 jsp 文件,我想知道在渲染过程中是否有什么东西在某个地方默默地失败了?
解决方案
似乎是 servlet 无法找到某些有问题的文件,因此没有呈现任何内容,因为它找不到任何内容
我需要进一步验证。但是在 per 下移动后home.js
,WEB-INF/view/js/home
我index.jsp
开始从我的网页中获取一些堆栈跟踪
Exception: org.apache.jasper.JasperException: java.lang.NullPointerException
Stack Trace
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:516) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329) javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712)
org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:580)
org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:516)
org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequestDispatcher.include(HeaderWriterFilter.java:149)
org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:955)
org.apache.jsp.WEB_002dINF.view.jsp.index_jsp._jspService(index_jsp.java:150)
对于我登录 SpringBoot
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [/xxx] threw exception [java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:434)
at java.util.Properties.load0(Properties.java:353)
at java.util.Properties.load(Properties.java:341)
at com.xx.xxx.common.utils.common.GenericPropertiesUtil.loadProperties(GenericPropertiesUtil.java:16)
at com.xx.xxx.common.utils.common.EnvPropertiesUtil.getEnvironmentProperties(EnvPropertiesUtil.java:43)
at com.xx.xxx.common.utils.common.EnvPropertiesUtil.getParameterValue(EnvPropertiesUtil.java:23)
at com.xx.xxx.common.utils.common.EnvPropertiesUtil.getFlagParameterValue(EnvPropertiesUtil.java:37)
at com.xx.xxx.common.utils.Config.getFlagValue(Config.java:131)
at com.xx.xxx.common.utils.Config.isProd(Config.java:59)
at com.xx.xxx.common.utils.IO.debug(IO.java:514)
这似乎表明页面上现在有活动
如果需要,我会验证并重新打开。我会保留这篇文章,以防其他人有类似的问题
推荐阅读
- java - 从 Map 中删除值,同时将值与 List 进行比较
- go - 解释一下执行时间差
- html - 调整窗口大小时 Safari 跳跃的背景大小计算
- python - 我在 Python 数据框的列中有一个字典
- c - 使用 for 循环在 2D 浮点数组上输入值
- ios - Swift 4 - UICollectionView 页脚条件
- c# - 只能从代码中验证内存用户
- amazon-web-services - 如何通过 gitlab-ci 在 AWS EC2 实例上拉取 docker 容器?
- python - 从白色到红色的颜色图
- java - 如何从 mvn clean deploy 生成的 Maven 工件中删除日期时间后缀并增加 #?