SpringMVC_Thymeleaf综合示例2

SpringMVC_Thymeleaf综合示例2

1. 登录

跳转至登录页面代码:

UserController.java

@RequestMapping("/")
public String showLogin(User user) {
    return "login";
}

登录页面login.html:

<!DOCTYPE html>
<html th:replace="~{layout::standard('用户登录',~{::div})}"
	xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
	<div align="center">
		<form th:action="@{/login}" method="post" th:object="${user}">
			<label th:text="${session.loginMsg}"></label>
            <table id="hor-minimalist-b">
				<tbody>
					<tr>
						<td>用户名</td>
						<td><input th:field="*{name}"></td>
					</tr>
					<tr>
						<td>密码</td>
						<td><input type="password" th:field="*{password}"></td>
					</tr>
					<tr>
						<td colspan="2"><input type="submit" value="登录"><input
							type="button" value="注册"
							th:onclick="|javascript:location.href='@{/register}';|"></td>
					</tr>
				</tbody>
			</table>
		</form>
	</div>
</body>
</html>

其中th:onclick中可以使用一对|对普通字符串与thymeleaf表达式进行拼接。否则我们要写成如下形式:

<input type="button" value="注册" th:onclick="'javascript:location.href=\''+@{/register}+'\';'">

这样会让整个表达式变得非常不清晰。

登录逻辑:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public String checkLogin(User user, HttpSession session) {
    boolean flag = userService.checkLogin(user);
    if (flag) {
        session.setAttribute("loginUser", user);
        session.removeAttribute("loginMsg");
        return "redirect:/findAllUser";
    } else {
        session.setAttribute("loginMsg", "用户名密码错误");
        return "redirect:/";
    }
}

2. 注册新用户

首先增加跳转至注册页面的controller逻辑

public final static Map<String, String> map = new HashMap<>();

static {
    map.put("swim", "游泳");
    map.put("game", "电竞游戏");
    map.put("run", "跑步");
    map.put("travel", "旅游");
}

@ModelAttribute("hobbyMap")
public Map<String, String> showHobbies() {
    return map;
}

@RequestMapping(value = "/register", method = RequestMethod.GET)
public String showRegister(User user) {
    user.setGender(true);
    return "register";
}

上述代码初始化了一个代表爱好的HashMap集合,并使用@ModelAttribute("hobbyMap")将该对象绑定到了模型对象中,方便在页面进行获取。

由于注册新用户的表单和更新用户信息的表单,从结构上来说都是一样的,我们可以利用Thymeleaf进行代码复用,首先在common.html中定义用于提交注册或更新的代码段:

<div th:fragment="user(actionPath)" align="center">
    <form th:action="${actionPath}" method="post" th:object="${user}">
        <input type="hidden" th:field="*{id}">
        <table id="hor-minimalist-b">
            <tbody>
                <tr>
                    <td>用户名</td>
                    <td><input th:field="*{name}"><span
                                                        th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span></td>
                </tr>
                <tr>
                    <td>密码</td>
                    <td><input type="password" th:field="*{password}"><span
                                                            th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span></td>
                </tr>
                <tr>
                    <td>生日</td>
                    <td><input th:field="*{birthday}"><span
                                                            th:if="${#fields.hasErrors('birthday')}" th:errors="*{birthday}"></span></td>
                </tr>
                <tr>
                    <td>性别</td>
                    <td><input type="radio" th:field="*{gender}" th:value="1"><input type="radio" th:field="*{gender}" th:value="0"></td>
                </tr>
                <tr>
                    <td>爱好</td>
                    <td><span th:each="kv:${hobbyMap}"><input
                                                              type="checkbox" th:field="*{hobbies}" th:value="${kv.key}">
                        <label th:for="${#ids.prev('hobbies')}" th:text="${kv.value}"></label>
                        </span></td>
                </tr>
                <tr>
                    <td colspan="2"><input type="submit" value="提交"></td>
                </tr>
            </tbody>
        </table>
    </form>
</div>

然后,在register.html中,对模板进行调用:

<!DOCTYPE html>
<html
	th:replace="~{layout::standard('用户注册',~{common::user(@{/register})})}"
	xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
</body>
</html>
  • actionPath用来传入form表单的提交路径。
  • th:object="${user}用来声明表单所绑定的模型对象
  • *{属性名}用来获取表单绑定模型对象的属性值
  • th:if="${#fields.hasErrors('属性名')}"用来判断对应的属性是否存在错误消息
  • th:errors="*{属性名}"用来获取对应属性的错误消息

最后我们再来看用来生成多选框的这些代码:

<tr>
    <td>爱好</td>
    <td>
        <span th:each="kv:${hobbyMap}">
            <input type="checkbox" th:field="*{hobbies}" th:value="${kv.key}">
        	<label th:for="${#ids.prev('hobbies')}" th:text="${kv.value}"></label>
        </span>
    </td>
</tr>
  • th:each="kv:${hobbyMap}"用来循环后台准备好的爱好集合,${hobbyMap}为循环集合,kv为循环变量。th:each循环HashMap时,得到的循环单元为key-value对(entry)。
  • 由于多选框多半是由两个html标签组成的(一个input,一个文本),因此,代码中整个label标签是为了给前面这个多选框生成后面显示的文本的。
    • th:for="${#ids.prev('hobbies')}"表示它将会依据id查找某一个组件。
    • id值为多少,取决于${#ids.prev('hobbies')}
    • ${#ids.prev('hobbies')}表示为上一个hobbies生成的id值。其中#ids为模板引擎的id生成器(内置对象),在th:each循环运行后,它会为每一个html组件(多选框)创建一个id值,分别为hobbies1hobbies2…以此类推。我们调用prev()方法来获取为hobbies生成的上一个id值(#ids相应的还有next()方法,用来获取下一个生成的id值)。

User上的JSR303校验:

public class User {

	private Integer id;

	@NotNull
	@Size(min = 6, max = 8, message = "{name.size}")
	private String name;

	@NotNull
	@Size(min = 6, max = 8, message = "{password.size}")
	private String password;

	private Boolean gender;

	@DateTimeFormat(pattern = "yyyy-MM-dd")
	private Date birthday;

	private String hobby;

	private String[] hobbies;
    
    // getter & setter
    
}

注册逻辑:

@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(@Valid User user, Errors errors) {
    if (errors.hasErrors()) {
        return "register";
    }
    user.setHobby(ArrayUtils.toString(user.getHobbies()));
    userService.save(user);
    return "redirect:/findAllUser";
}

3. 更新用户信息

首先在listplus.html页面增加更新操作按钮:

<input type="button" value="更新"
	th:onclick="|javascript:location.href='@{/update?id=}${user.id}';|">

跳转至更新页面:

@RequestMapping(value = "/update", method = RequestMethod.GET)
public String showUpdate(int id, Model model) {
    User user = userService.findById(id);
    user.setHobbies(user.getHobby().split(","));
    model.addAttribute(user);
    return "update";
}

执行更新逻辑:

@RequestMapping(value = "/update", method = RequestMethod.POST)
public String update(@Valid User user, Errors errors) {
    if (errors.hasErrors()) {
        return "update";
    }
    user.setHobby(ArrayUtils.toString(user.getHobbies()));
    userService.update(user);
    return "redirect:/findAllUser";
}

4. 删除

listplus.html页面添加删除操作按钮:

<input type="button" value="删除"
	th:onclick="|javascript:location.href='@{/delete?id=}${user.id}';|">

删除逻辑:

@RequestMapping(value = "/delete", method = RequestMethod.GET)
public String delete(int id) {
    userService.delete(id);
    return "redirect:/findAllUser";
}

5. 登录拦截

为了防止用户在未登录的情况,访问内部页面,我们可以使用Spring提供的拦截机制。

首先编写拦截逻辑:

LoginInterceptor.java

public class LoginInterceptors implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		Object user = request.getSession().getAttribute("loginUser");
		if (user == null) {
			response.sendRedirect(request.getServletContext().getContextPath());
			return false;//拦截请求
		} else {
			return true;//放行请求
		}
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	}

}

然后在WebConfig中注册拦截器:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginInterceptors())
        //拦截路径
        .addPathPatterns("/**")
        //不拦截路径
        .excludePathPatterns("/", "/login");
}

er, Exception ex)
throws Exception {
}

}


然后在WebConfig中注册拦截器:

```java
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginInterceptors())
        //拦截路径
        .addPathPatterns("/**")
        //不拦截路径
        .excludePathPatterns("/", "/login");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值