Spring Boot用户注册功能异常:页面跳转失败与500错误求助
Alright, let's break down what's going wrong here and fix it step by step.
Root Cause Analysis
Your error NotReadablePropertyException is directly caused by a mismatched field name between your form template and the DTO class, plus an unnecessary role input that conflicts with your backend logic. Let's unpack this:
- In
UserRegistrationDto, you defined the role field asprivate Collection<Roles> role;(singular), but yourregistration.htmlusesth:field="*{roles}"(plural). Thymeleaf tries to callgetRoles()on the DTO, which doesn't exist—hence the property not found error. - Your backend already hardcodes
ROLE_USERfor new users inUserServiceImp.save(), so letting users input a role in the form is not just redundant, it's a potential security risk.
Step-by-Step Fixes
1. Fix the Field Name Mismatch (Optional but Recommended for Consistency)
If you ever need to pass roles via the DTO later, rename the field to match your template's expectation. Ensure your getter/setter methods are correctly generated:
public class UserRegistrationDto { private String userName; private String password; // Rename to "roles" to match template expression private Collection<Roles> roles; // Correct getter/setter for the renamed field public Collection<Roles> getRoles() { return roles; } public void setRoles(Collection<Roles> roles) { this.roles = roles; } // Remaining constructors, getters/setters for userName and password }
2. Remove the Unnecessary Role Input from the Form
Since your backend already assigns ROLE_USER by default, delete the role input section entirely. Also, clean up the duplicate autofocus attributes (only one input should have this):
<form th:action="@{/registration}" method="post" th:object="${user}"> <div class="form-group"> <label class="control-label" for="userName"> Username </label> <input id="userName" class="form-control" th:field="*{userName}" required autofocus="autofocus" /> </div> <div class="form-group"> <label class="control-label" for="password"> Password </label> <input id="password" class="form-control" th:field="*{password}" required /> </div> <div class="form-group"> <button type="submit" class="btn btn-success">Add User</button> </div> </form>
3. Add a GET Request Mapping for the Registration Page
Your current controller only handles POST requests (form submission). You need a GET mapping to render the registration page when the "Create User" button is clicked:
@Controller public class UserRegistrationController { @Autowired private UserService userService; // Handle GET request to show the registration form @RequestMapping(value = "/registration", method = RequestMethod.GET) public String showRegistrationForm(Model model) { // Bind an empty DTO to the form model.addAttribute("user", new UserRegistrationDto()); return "registration"; } // Handle POST request for form submission @RequestMapping(value = "/registration",method = RequestMethod.POST) public String registerUserAccount(@ModelAttribute("user") UserRegistrationDto registrationDto) { userService.save(registrationDto); return "redirect:/showInventory?success"; } }
4. Verify Roles Entity Constructor
Ensure your Roles entity has a constructor that accepts a role name, since your service layer uses new Roles("ROLE_USER"):
@Entity public class Roles { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String name; // Required constructor for your service logic public Roles(String name) { this.name = name; } // Default constructor (required for JPA) public Roles() {} // Getters and setters }
After applying these changes, your registration flow should work as expected: clicking "Create User" will redirect to the registration form, submitting the form will create a user with ROLE_USER, and you'll no longer see the 500 error.
内容的提问来源于stack exchange,提问作者Hesham Eldawy

