Spring MVC day02

2. 使用SpringMVC框架开发WEB项目

2.5. 显示页面

在SpringMVC中,当控制器接收到请求后,可以通过JSP页面向客户端呈现数据,或者使用其它的页面技术,例如Thymeleaf等。

如果需要使用Thymeleaf来呈现页面与数据,则需要在项目中添加Thymeleaf依赖,与Thymeleaf整合Spring的依赖:

<dependency>
	<groupId>org.thymeleaf</groupId>
	<artifactId>thymeleaf</artifactId>
	<version>3.0.11.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.thymeleaf</groupId>
	<artifactId>thymeleaf-spring4</artifactId>
	<version>3.0.11.RELEASE</version>
</dependency>

此前在控制器中返回String类型的数据,其值就是ModelAndView中的View,即返回的字符串表示视图名称,则需要通过ViewResolver得到视图组件,在使用Thymeleaf时,需要使用的ViewResolverThymeleafViewResolver

<!-- 配置模版解析器 -->
<!-- 1. ClassLoaderTemplateResolver,文件需要放在resources下 -->
<!-- 2. ServletContextTemplateResolver,文件需要放在webapp下 -->
<bean id="templateResolver"
	class="org.thymeleaf.templateresolver.ClassLoaderTemplateResolver">
	<property name="prefix"
		value="/templates/" />
	<property name="suffix"
		value=".html" />
	<property name="characterEncoding"
		value="utf-8" />
	<property name="templateMode"
		value="HTML" />
	<property name="cacheable"
		value="false" />
</bean>
	
<!-- 配置模版引擎 -->
<bean id="templateEngine"
	class="org.thymeleaf.spring4.SpringTemplateEngine">
	<property name="templateResolver"
		ref="templateResolver" />
</bean>
	
<!-- 配置视图解析器 -->
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
	<property name="templateEngine"
		ref="templateEngine" />
	<property name="characterEncoding"
		value="utf-8" />
</bean>

最后,在src/main/resources/下创建templates文件夹,并在文件夹下创建hello.html文件,并将控制器中处理请求的方法的返回值改为"hello"即可:

@RequestMapping("hello.do")
public String showHello() {
	System.out.println("UserController.showHello()");
	return "hello";
}

3. 创建新的案例

3.1. 案例目标

在浏览器中,输入http://localhost:8080/SpringMVC02/reg.do,在页面中将显示用户注册页面,在页面中,至少包含用户名、密码、年龄、手机号码、电子邮箱这5个输入框,和1个提交按钮。

3.2. 创建项目

创建Maven Project,创建时勾选Create a simple projectGroup Id输入cn.tedu.springArtifact Id输入SpringMVC02Packaging选择war

当项目创建完成后,需要:

  1. 生成web.xml文件;

  2. 添加Tomcat运行环境;

  3. 从前序项目的pom.xml中复制依赖的代码到当前项目中;

  4. 将前序项目中的spring.xml复制到当前项目中;

  5. 将前序项目中的web.xml中关于DispatcherServlet的配置复制到当前项目中;

  6. 检查web.xml中关于DispatcherSerlvet配置中加载的Spring配置文件的名称是否正确。

3.3. 通过控制器接收并处理请求

创建cn.tedu.spring包(请检查spring.xml中配置的组件扫描是否与之一致),并在该包之下创建UserController,在类的声明之前添加@Controller注解:

package cn.tedu.spring;

import org.springframework.stereotype.Controller;

@Controller
public class UserController {

}

然后,在类中添加处理请求的方法:

@RequestMapping("reg.do")
public String showReg() {
	// /templates/reg.html
	return "user/reg"; // 返回值可以理解为即将要创建的html文件的名称
}
3.4. 显示页面

先检查spring.xml是否存在关于视图解析器的配置,如果没有,从前序项目中复制过来!

检查关于视图解析器中的配置,如果使用的模版解析器是ClassLoaderTemplateResolver,则需要将HTML文件创建到src/main/resource下,如果使用的是ServletContextTemplateResolver,则需要将HTML文件创建到webapp下!

再检查模版解析器中配置的前缀,以决定是否需要创建文件夹!

然后,在指定的文件夹中创建HTML页面。

4. 接收客户端提交的请求参数

4.1. 【不推荐】通过HttpServletRequest接收请求参数

可以在处理请求的方法的参数列表中添加HttpServletRequest类型的参数,在处理过程中,调用该参数对象的getParameter()方法即可获取客户端(例如网页)中提交的请求参数:

@RequestMapping("handle_reg.do")
public String handleReg(HttpServletRequest request) {
	System.out.println("UserController.handleReg()");
	String username = request.getParameter("username");
	String password = request.getParameter("password");
	String age = request.getParameter("age");
	String phone = request.getParameter("phone");
	String email = request.getParameter("email");
	System.out.println("username=" + username);
	System.out.println("password=" + password);
	System.out.println("age=" + age);
	System.out.println("phone=" + phone);
	System.out.println("email=" + email);
	return null;
}

一般,并不推荐使用这种方式接收请求参数!主要原因有:

  1. 获取参数的过程比较麻烦;

  2. 如果需要的参数不是String类型,则需要自行转换数据类型;

  3. 不便于执行单元测试。

4.2. 【推荐】直接将请求参数声明为处理请求的方法的参数

可以将请求参数声明为处理请求的方法的参数,使用时,可以直接将参数的类型声明为所期望的类型,例如希望age是数值型的,就可以直接声明为Integerint类型:

@RequestMapping("handle_reg.do")
public String handleReg(String username, String password, Integer age, String phone, String email) {
	System.out.println("UserController.handleReg()");

	System.out.println("username=" + username);
	System.out.println("password=" + password);
	System.out.println("age=" + (age + 1));
	System.out.println("phone=" + phone);
	System.out.println("email=" + email);
	
	return null;
}

使用这种做法时,需要保证请求参数的名称,与处理请求的方法中的参数名称是一致的!如果不一致,则处理请求的方法的参数值是null

这种做法简单,直接,便于执行单元测试,但是,不适用于请求参数的数量较多的应用场景!

4.3. 【推荐】使用封装的类型作用请求参数

当请求参数的数量较多时,可以先创建User类,在类中声明所有需要接收的请求参数:

public class User {

	private String username;
	private String password;
	private Integer age;
	private String phone;
	private String email;

}

注意:以上这种类,必须存在无参数的构造方法,并且,相关属性必须有正确的SET方法!

然后,将User作为处理请求的方法的参数即可:

@RequestMapping("handle_reg.do")
public String handleReg(User user) {
	System.out.println("UserController.handleReg()");

	System.out.println(user);
	System.out.println(user.getUsername());
	System.out.println(user.getPassword());
	System.out.println(user.getAge());
	System.out.println(user.getPhone());
	System.out.println(user.getEmail());
	
	return null;
}

这种做法也是SpringMVC推荐的做法!

4.4. 小结

以上3种获取请求参数的做法中,首先,始终不使用第1种做法!

当请求参数的数量较少,并且相对固定时,优先使用第2种(逐一声明所有参数)做法,否则,请求参数数量较多,或参数可能调整时,优先使用第3种(封装所有请求参数)做法!

并且,以上第2种做法和第3种做法可以同时使用!

5. 数据转发

5.1. 【不推荐】通过HttpServletRequest转发数据

在处理请求的方法的参数列表中添加HttpServletRequest参数,然后,在处理过程中,将需要转发的数据封装在HttpServletRequest对象中即可,例如:

String errorMessage = "登录失败!密码错误!";
request.setAttribute("msg", errorMessage);

完整代码示例:

@RequestMapping("handle_login.do")
public String handleLogin(
	HttpServletRequest request,
	String username, String password) {
	System.out.println("UserController.handleLogin()");
	
	System.out.println("username=" + username);
	System.out.println("password=" + password);
	
	// 假设root/1234是正确的用户名和密码
	// 先判断用户名是否正确
	if ("root".equals(username)) {
		// 用户名正确,判断密码
		if ("1234".equals(password)) {
			// 密码也正确,则登录成功
		} else {
			// 密码错误
			String errorMessage = "登录失败!密码错误!";
			request.setAttribute("msg", errorMessage);
			return "error";
		}
	} else {
		// 用户名错误
		String errorMessage = "登录失败!用户名错误!";
		request.setAttribute("msg", errorMessage);
		return "error";
	}
	
	return null;
}

后续,在HTML模版页面中,可以通过Thymeleaf表达式显示这些数据,例如:

<h3 th:text="${msg}"></h3>

如果处理请求的方法中有多个参数,在设计参数时,各参数并不区分先后顺序!

使用HttpServletRequest依然存在不便于执行单元测试的问题!

5.2. 【推荐】通过ModelMap转发数据

关于ModelMap的使用方式,与HttpServletRequest基本一致!

代码示例:

@RequestMapping("handle_login.do")
public String handleLogin(
	ModelMap modelMap,
	String username, String password) {
	System.out.println("UserController.handleLogin()");
	
	System.out.println("username=" + username);
	System.out.println("password=" + password);
	
	// 假设root/1234是正确的用户名和密码
	// 先判断用户名是否正确
	if ("root".equals(username)) {
		// 用户名正确,判断密码
		if ("1234".equals(password)) {
			// 密码也正确,则登录成功
		} else {
			// 密码错误
			String errorMessage = "登录失败!密码错误!";
			modelMap.addAttribute("msg", errorMessage);
			return "error";
		}
	} else {
		// 用户名错误
		String errorMessage = "登录失败!用户名错误!";
		modelMap.addAttribute("msg", errorMessage);
		return "error";
	}
	
	return null;
}

使用ModelMap时,相比HttpServletRequest,更加易于执行单元测试,并且,ModelMap的对象更加轻量级。

5.2. 【不推荐】使用ModelAndView作为处理请求的方法的返回值

将方法的返回值类型声明为ModelAndView,创建ModelAndView对象时,调用其ModelAndView(String viewName, Map<String, ?> model)构造方法,就可以快速的设置返回的视图名称(viewName)和数据(model)。

@RequestMapping("handle_login.do")
public ModelAndView handleLogin(
	String username, String password) {
	System.out.println("UserController.handleLogin()");
	
	System.out.println("username=" + username);
	System.out.println("password=" + password);
	
	ModelAndView mav;
	
	// 假设root/1234是正确的用户名和密码
	// 先判断用户名是否正确
	if ("root".equals(username)) {
		// 用户名正确,判断密码
		if ("1234".equals(password)) {
			// 密码也正确,则登录成功
		} else {
			// 密码错误
			String errorMessage = "登录失败!密码错误!";
			Map<String, Object> model = new HashMap<String, Object>();
			model.put("msg", errorMessage);
			mav = new ModelAndView("error", model);
			return mav;
		}
	} else {
		// 用户名错误
		String errorMessage = "登录失败!用户名错误!";
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("msg", errorMessage);
		mav = new ModelAndView("error", model);
		return mav;
	}
	
	return null;
}

-------------------------

附1:关于No Mapping Found错误的解决方案

该错误是在控制台提示的错误:

No mapping found for HTTP request with URI [/SpringMVC01/hello.do] in DispatcherServlet with name 'SpringMVC'

同时,在浏览器中,会显示404错误。

出现这种错误的原因可能有:

  1. 在Spring的配置文件中没有配置组件扫描;

  2. 控制器类没有放在组件扫描的包或其子包中;

  3. 控制器类没有添加@Controller注解,或者,添加了其它例如Component注解;

  4. 在控制器类中,处理请求的方法没有添加@RequestMapping注解;

  5. 在浏览器中输入的请求路径与控制器中配置的路径不一致。

附2:关于GET请求与POST请求

附3:封装

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值