【问题标题】:Springframework - property or field cannot be found on nullSpringframework - 在null上找不到属性或字段
【发布时间】:2018-03-31 00:39:51
【问题描述】:

我正在处理一个项目并不断收到错误消息。

<span style="font-style: italic;" th:text="${user != null} ? ${#strings.toUpperCase(user.username)} : 'user is null'"></span>

EL1007E: Property or field 'id' cannot be found on null

我是 thyemeleaf 和 spring 的新手,所以还在学习,所以不确定你需要什么来帮助解决这个问题,所以当我知道我需要提供什么时,我会更新。

登录/新用户模式所在的标题 HTML

<body>
  <div th:fragment="navbar">
    <div class="container">
      <nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
        <a class="navbar-brand active" href="https://inplaydesign.com/index.html">d|b</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
					<span class="navbar-toggler-icon"></span>
				</button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item">
              <a class="nav-link" href="https://blog.inplaydesign.com">blog</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="/gallery/gallery.html">gallery</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">shop</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="/faq/faq.html">f.a.q.</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="/contact/contact.html">contact</a>
            </li>
          </ul>
          <button type="button" class="btn btn-outline-dark">
						<i class="fa fa-shopping-cart"></i> Shopping Cart
					</button>
          <button sec:authorize="isAnonymous()" type="button" class="btn btn-outline-dark" data-toggle="modal" data-target="#accountAccess">
						<i class="fa fa-id-card"></i> Account
					</button>
          <a sec:authorize="isAuthenticated()" th:href="@{/myProfile}">
            <button type="button" class="btn btn-outline-dark">
							<i class="fa fa-id-card"></i> Account
						</button>
          </a>
          <a sec:authorize="isAuthenticated()" th:href="@{/logout}">
            <button type="button" class="btn btn-outline-dark">
							<i class="fa fa-power-off"></i> log-out
						</button>
          </a>
        </div>
      </nav>
    </div>
    <!-- Account modal -->
    <div class="modal fade" id="accountAccess" tabindex="-1" role="dialog" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">Account Login and Creation
            </h5>
          </div>
          <div class="modal-body">
            <ul class="nav nav-tabs" role="tablist">
              <li class="nav-item" th:classappend="${classActiveNewAccount}? 'active'">
                <a class="nav-link" data-toggle="tab" href="#tab-1" role="tab">Sign up</a>
              </li>
              <li class="nav-item" th:classappend="${classActiveLogin}? 'active'">
                <a class="nav-link active" data-toggle="tab" href="#tab-2" role="tab">User Login</a>
              </li>
              <li class="nav-item" th:classappend="${classActiveForgetPassword}? 'active'">
                <a class="nav-link" data-toggle="tab" href="#tab-3" role="tab">Forgot Password</a>
              </li>
            </ul>
            <div class="tab-content" style="margin-top: 10px;">
              <!-- New User -->
              <div class="tab-pane fade" id="tab-1" role="tabpanel" th:classappend="${classActiveNewAccount}? 'in active'">
                <form th:action="@{/newUser}" method="post">
                  <div class="container">
                    <div class="form-group">
                      <label for="email">Email Address</label>&nbsp;
                      <div class="alert alert-danger" th:if="${emailExists}">"Email already exists"</div>
                      <input type="email" class="form-control" id="email" name="email" placeholder="Enter Email Address" />
                    </div>
                    <div class="form-group">
                      <label for="NewUsername">Username</label>&nbsp;
                      <div class="alert alert-danger" th:if="${usernameExists}">"Username already exists"</div>
                      <input type="text" class="form-control" id="newUsername" name="NewUsername" tabindex="0" placeholder="Enter Username" />
                    </div>
                  </div>
                  <div class="modal-footer">
                    <button type="reset" class="btn btn-outline-dark btn-sm">
											<i class="fa fa-refresh"></i> Reset
										</button>
                    <button type="button" class="btn btn-outline-dark btn-sm">
											<i class="fa fa-user-plus"></i> Create New Account
										</button>
                  </div>
                </form>
              </div>

              <!-- login -->
              <div class="tab-pane fade show active" id="tab-2" role="tabpanel" th:classappend="${classActiveLogin}? 'active'">
                <div class="alert alert-danger" th:if="${param.error != null}">
                  <small>Please check your credentials and try again.</small>
                </div>
                <form th:action="@{/login}" method="post">
                  <div class="container">
                    <div class="form-group">
                      <label for="username">Username</label>
                      <input type="text" class="form-control" id="username" name="username" placeholder="Enter Username" />
                    </div>
                    <div class="form-group">
                      <label for="password">Password</label>
                      <input type="password" class="form-control" id="password" name="password" placeholder="Enter Password" />
                    </div>
                  </div>
                  <div class="modal-footer">
                    <button type="submit" class="btn btn-outline-dark btn-sm">
											<i class="fa fa-sign-in"></i> Log-In
										</button>
                  </div>
                </form>
              </div>

              <!-- Forgot password -->
              <div class="tab-pane fade" id="tab-3" role="tabpanel" th:classappend="${classActiveForgetPassword}? 'in active'">
                <div th:if="${emailNotExist}" class="alert alert-danger">Email does not exist</div>
                <div th:if="${forgetPasswordEmailSent}" class="alert alert-success">Please check your email for password reset token.</div>
                <form action="">
                  <div class="container">
                    <div class="form-group">
                      <label for="recoverEmail">User Email</label>
                      <input type="email" class="form-control" id="recoverEmail" placeholder="Enter Recovery Email" name="email" />
                    </div>
                  </div>
                  <div class="modal-footer">
                    <button type="submit" class="btn btn-outline-dark btn-sm">
											<i class="fa fa-external-link-square"></i> Submit
										</button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div th:fragment="body-bottom-scripts">
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" type="text/javascript"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" type="text/javascript"></script>
    <script src="/js/bootstrap.min.js" type="text/javascript"></script>
  </div>
</body>

import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.digitalblasphemy.domain.User;
import com.digitalblasphemy.domain.security.PasswordResetToken;
import com.digitalblasphemy.domain.security.Role;
import com.digitalblasphemy.domain.security.UserRole;
import com.digitalblasphemy.service.UserService;
import com.digitalblasphemy.service.impl.UserSecurityService;
import com.digitalblasphemy.utility.MailConstructor;
import com.digitalblasphemy.utility.SecurityUtility;

@Controller
public class HomeController {

  @Autowired
  private JavaMailSender mailSender;

  @Autowired
  private MailConstructor mailConstructor;

  @Autowired
  private UserService userService;

  @Autowired
  private UserSecurityService userSecurityService;

  @RequestMapping("/")
  public String index() {
    return "index";
  }

  @RequestMapping("/myAccount")
  public String myAccount() {
    return "myAccount";
  }

  @RequestMapping("/login")
  public String login(Model model) {
    model.addAttribute("classActiveLogin", true);
    return "myProfile";
  }

  @RequestMapping("/forgetPassword")
  public String forgetPassword(
    HttpServletRequest request,
    @ModelAttribute("email") String email,
    Model model
  ) {
    model.addAttribute("classActiveForgetPassword", true);
    User user = userService.findByEmail(email);

    if (user == null) {
      model.addAttribute("emailNotExist", true);
      return "index";
    }

    String password = SecurityUtility.randomPassword();

    String encryptedPassword = SecurityUtility.passwordEncoder().encode(password);
    user.setPassword(encryptedPassword);

    userService.save(user);

    String token = UUID.randomUUID().toString();
    userService.createPasswordResetTokenForUser(user, token);

    String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();

    SimpleMailMessage newEmail = mailConstructor.constructResetTokenEmail(appUrl, request.getLocale(), token, user, password);

    mailSender.send(newEmail);

    model.addAttribute("forgetPasswordEmailSent", "true");

    return "index";
  }

  @RequestMapping(value = "/newUser", method = RequestMethod.POST)
  public String newUserPost(
    HttpServletRequest request,
    @ModelAttribute("email") String userEmail,
    @ModelAttribute("username") String username,
    Model model
  ) throws Exception {
    model.addAttribute("classActiveNewAccount", true);
    model.addAttribute("email", userEmail);
    model.addAttribute("username", username);

    if (userService.findByUsername(username) != null) {
      model.addAttribute("usernameExists", true);

      return "index";
    }

    if (userService.findByEmail(userEmail) != null) {
      model.addAttribute("emailExists", true);

      return "index";
    }

    User user = new User();
    user.setUsername(username);;
    user.setEmail(userEmail);

    String password = SecurityUtility.randomPassword();

    String encryptedPassword = SecurityUtility.passwordEncoder().encode(password);
    user.setPassword(encryptedPassword);

    Role role = new Role();
    role.setRoleId(1);
    role.setName("ROLE_USER");
    Set < UserRole > userRoles = new HashSet < > ();
    userRoles.add(new UserRole(user, role));
    userService.createUser(user, userRoles);

    String token = UUID.randomUUID().toString();
    userService.createPasswordResetTokenForUser(user, token);

    String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();

    SimpleMailMessage email = mailConstructor.constructResetTokenEmail(appUrl, request.getLocale(), token, user, password);

    mailSender.send(email);

    model.addAttribute("emailSent", "true");

    return "myAccount";
  }

  @RequestMapping("/newUser")
  public String newUser(
    Locale locale,
    @RequestParam("token") String token,
    Model model) {

    PasswordResetToken passToken = userService.getPasswordResetToken(token);

    if (passToken == null) {
      String message = "Invalid Token.";
      model.addAttribute("message", message);
      return "redirect:/badRequest";
    }

    User user = passToken.getUser();
    String username = user.getUsername();

    UserDetails userDetails = userSecurityService.loadUserByUsername(username);

    Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());

    SecurityContextHolder.getContext().setAuthentication(authentication);

    model.addAttribute("user", user);

    model.addAttribute("classActiveEdit", true);
    return "myProfile"; //possibly change to index page
  }
}

我在我的 Application.java 文件中有这个来创建一个用于测试目的的用户。

@Override
public void run(String...args) throws Exception {
  User user1 = new User();
  user1.setFirstName("Kyle");
  user1.setLastName("Drew");
  user1.setUsername("kd");
  user1.setPassword(SecurityUtility.passwordEncoder().encode("p"));
  user1.setEmail("kd@me.com");
  Set < UserRole > userRoles = new HashSet < > ();
  Role role1 = new Role();
  role1.setRoleId(1);
  role1.setName("ROLE_USER");
  userRoles.add(new UserRole(user1, role1));

  userService.createUser(user1, userRoles);
}

这是调试后的变量图。

【问题讨论】:

  • 它是空的,所以它不能渲染它。创建一个条件,如果它为空,则将用户名设为一些占位符文本
  • 模板上下文中没有名为user 的变量。发布负责此页面的 Spring MVC 控制器方法。
  • 添加了家庭控制器
  • 看起来您添加到模型中的user 对象是null,因此当您尝试渲染user.username 时,您会遇到第一个错误。尝试在调试器中单步执行您的控制器,以查看 user 的值是什么。
  • 当我启动服务器并连接到mysql中的数据库时,我得到确认User kd already Exists. Nothing will be done.

标签: java spring thymeleaf


【解决方案1】:

我发现了这个问题。在 SecurityConfig.Java 文件中,我没有 .loginPage 指向创建异常的正确位置。

http
  .csrf().disable().cors().disable()
  .formLogin().failureUrl("/login?error").defaultSuccessUrl("/")
  .loginPage("/login").permitAll()
  .and()
  .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
  .logoutSuccessUrl("/?logout").deleteCookies("remember-me").permitAll()
  .and()
  .rememberMe();
}

【讨论】:

    【解决方案2】:

    您可以通过检查user 是否为空来避免此异常。

    <span style="font-style: italic;" th:text="${user != null} ? ${#strings.toUpperCase(user.username)} : 'user is null'"></span>
    

    但是,更好的方法是确保 user 在未初始化的情况下不会被添加到模型中。

    【讨论】:

    • 我创建的令牌可以很好地访问个人资料页面,并且当我使用令牌时,用户名会显示在它应该出现的位置。但是当我尝试使用凭据登录时。我得到了异常Property or field 'id' cannot be found on null。我会问教练,但如果在 udemy 上没有他回应的问题页面有任何迹象,他显然不会回答问题。
    • 仍然出现异常。我做了一个调试器并添加了到达断点时得到的变量。
    【解决方案3】:

    在放入模型之前确保您的用户对象不为空

    【讨论】:

    • 根据我提供的信息向我解释您看到的东西 = null 的位置。唯一应该是 = null 是如果他们的用户名或电子邮件已经存在。
    • 应该null,而您的错误消息field username cannot be found *on null* 则表明并非如此。您可以在调试器中轻松解决它。
    • 这很好,但我不确定我在看什么。在寻找关于我应该寻找什么的好文档方面有任何帮助吗?正如我所说,我是这门语言的新手,讲师像 youtube 教程一样教授课程(即不解释任何内容,他解释的内容非常模糊,以至于它所做的只是导致挫败感)。
    • 在控制器中将用户添加到模型中的任何位置放置一个断点,例如。 model.addAttribute("user", user);。检查user的值,看是否为null
    • 好吧,我在 Eclipse 中添加了断点,它指出我在守护线程中的 throw new SpelEvaluationException(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL, name); 最后一项是 owns: NioEndpoint$NioSocketWrapper (id=122) 不管这意味着什么
    猜你喜欢
    • 2018-08-07
    • 2016-11-16
    • 1970-01-01
    • 2018-05-04
    • 2018-01-09
    • 2019-04-27
    • 2020-01-21
    • 2021-08-22
    • 1970-01-01
    相关资源
    最近更新 更多