共计 19583 个字符,预计需要花费 49 分钟才能阅读完成。
本章主要内容包含 SpringMVC 简介、MyBatis 整合 SpringMVC(主要是在前面的 MyBatis 整合 Spring 基础上进行)、Spring 应用实例等。
1.1 SpringMVC 简介
1.1.1 介绍
SpringMVC 因 Spring 的名气而得到大范围地应用,当然了,除此之外 SpringMVC 的确简单易学,同时其本身与 Struts2 比较够轻量。
1.1.2 SpringMVC 与 Struts2 比较
比较归纳为如下:
(1)入口不同:SpringMVC 的入口是 Servlet,Struts 的入口是 Filter。
(2)性能上:spring3 mvc 是方法级别的拦截,拦截到方法后根据参数上的注解,把 request 数据注入进去,在 spring3 mvc 中,一个方法对应一个 request 上下文。而 struts2 框架是类级别的拦截,每次来了请求就创建一个 Action,然后调用 setter getter 方法把 request 中的数据注入;struts2 实际上是通过 setter getter 方法与 request 打交道的;struts2 中,一个 Action 对象对应一个 request 上下文。
(3)拦截器实现机制上,Struts2 有以自己的 interceptor 机制,SpringMVC 用的是独立的 AOP 方式,这样导致 Struts2 的配置文件量还是比 SpringMVC 大。
(4)设计思想上,Struts2 更加符合 OOP 的编程思想,SpringMVC 就比较谨慎,在 servlet 上扩展。
(5)SpringMVC 集成了 Ajax,使用非常方便,只需一个注解 @ResponseBody 就可以实现,然后直接返回响应文本即可,而 Struts2 拦截器集成了 Ajax,在 Action 中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
(6)Spring MVC 和 Spring 是无缝的。从这个项目的管理和安全上也比 Struts2 高(当然 Struts2 也可以通过不同的目录结构和相关配置做到 SpringMVC 一样的效果,但是需要 xml 配置的地方不少)。
1.1.3 MVC 模式
三层架构在 Java 中是比较出名的,三层架构无非是数据访问层、业务逻辑层、Web 层 (又称 UI 层) 等。其中 Web 层中就涉及到 MVC 模式(模型 - 视图 - 控制器),MVC 模式可以以 SpringMVC 官方网站的一张图来表示:
1.2 整合 SpringMVC
一般通常整合 SpringMVC 并不需要花多大力气,很简单的。如果是 Spring+SpringMVC+MyBatis 整合,最好还是先将 Spring+MyBatis 先整合好,这样可以省去很多不必要的麻烦。然后就可以无缝集成 SpringMVC。
1.2.1 导入依赖
依赖复用可以参考 MyBatis 集成 Spring
直接可以将里面的依赖复用
1.2.2 编写 HelloController
package com.tutorialspoint;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.ModelMap;
@Controller
@RequestMapping(“/hello”)
public class HelloController{
@RequestMapping(method = RequestMethod.GET)
public String printHello(ModelMap model) {
model.addAttribute(“message”, “Hello Spring MVC Framework!”);
return “hello”;
}
}
1.2.3 修改 web.xml
<web-app id=”WebApp_ID” version=”2.4″
xmlns=”http://java.sun.com/xml/ns/j2ee”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd”>
<display-name>Spring MVC Application</display-name>
<servlet>
<description>spring mvc servlet</description>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
1.2.4 编写 application-mvc.xml
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:context=”http://www.springframework.org/schema/context”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd”>
<context:component-scan base-package=”com.tutorialspoint” />
<bean class=”org.springframework.web.servlet.view.InternalResourceViewResolver”>
<property name=”prefix” value=”/WEB-INF/jsp/” />
<property name=”suffix” value=”.jsp” />
</bean>
</beans>
1.2.5 在 WEB-INF 文件夹下新建 jsp 文件夹,并在 jsp 文件夹新建 hello.jsp 文件
<%@ page contentType=”text/html; charset=UTF-8″ %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2>${message}</h2>
</body>
</html>
1.2.6 启动项目并在浏览器输入对应的地址会显示对应的视图结果
1.3 SpringMVC 应用实例
应用实例不少以下只列出这么几个?(1)异常处理;(2)文件上传;(3)跨域请求;(4)表单处理;(5)重定向;
1.3.1 异常处理
异常处理,对于项目开发至关重要,总不能用户点击一个页面出错了,直接报 500,那样用户体验多不好啊!
所以这里讲的是 SpringMVC 对异常的处理,希望能给大家带来一定的 帮助和启发。
(1)编写实体
package com.tutorialspoint;
public class Student {
private Integer age;
private String name;
private Integer id;
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
}
(2)编写异常
package com.tutorialspoint;
public class SpringException extends RuntimeException{
private String exceptionMsg;
public SpringException(String exceptionMsg) {
this.exceptionMsg = exceptionMsg;
}
public String getExceptionMsg(){
return this.exceptionMsg;
}
public void setExceptionMsg(String exceptionMsg) {
this.exceptionMsg = exceptionMsg;
}
}
(3)编写测试 Controller
package com.tutorialspoint;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
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.servlet.ModelAndView;
import org.springframework.ui.ModelMap;
@Controller
public class StudentController {
@RequestMapping(value = “/student”, method = RequestMethod.GET)
public ModelAndView student() {
return new ModelAndView(“student”, “command”, new Student());
}
@RequestMapping(value = “/addStudent”, method = RequestMethod.POST)
@ExceptionHandler({SpringException.class})
public String addStudent(@ModelAttribute(“HelloWeb”)Student student,
ModelMap model) {
if(student.getName().length() < 5){
throw new SpringException(“Given name is too short”);
}else{
model.addAttribute(“name”, student.getName());
}
if(student.getAge() < 10 ){
throw new SpringException(“Given age is too low”);
}else{
model.addAttribute(“age”, student.getAge());
}
model.addAttribute(“id”, student.getId());
return “result”;
}
}
(3)在 application-mvc.xml 补充如下内容
<bean class=”org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”>
<property name=”exceptionMappings”>
<props>
<prop key=”com.tutorialspoint.SpringException”>
ExceptionPage
</prop>
</props>
</property>
<property name=”defaultErrorView” value=”error”/>
</bean>
(4)编写 JSP
student.jsp
<%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
<html>
<head>
<title>Spring MVC Exception Handling</title>
</head>
<body>
<h2>Student Information</h2>
<form:form method=”POST” action=”/HelloWeb/addStudent”>
<table>
<tr>
<td><form:label path=”name”>Name</form:label></td>
<td><form:input path=”name” /></td>
</tr>
<tr>
<td><form:label path=”age”>Age</form:label></td>
<td><form:input path=”age” /></td>
</tr>
<tr>
<td><form:label path=”id”>id</form:label></td>
<td><form:input path=”id” /></td>
</tr>
<tr>
<td colspan=”2″>
<input type=”submit” value=”Submit”/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
error.jsp
<html>
<head>
<title>Spring Error Page</title>
</head>
<body>
<p>An error occured, please contact webmaster.</p>
</body>
</html>
ExceptionPage.jsp
<%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
<html>
<head>
<title>Spring MVC Exception Handling</title>
</head>
<body>
<h2>Spring MVC Exception Handling</h2>
<h3>${exception.exceptionMsg}</h3>
</body>
</html>
result.jsp
<%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
<html>
<head>
<title>Spring MVC Form Handling</title>
</head>
<body>
<h2>Submitted Student Information</h2>
<table>
<tr>
<td>Name</td>
<td>${name}</td>
</tr>
<tr>
<td>Age</td>
<td>${age}</td>
</tr>
<tr>
<td>ID</td>
<td>${id}</td>
</tr>
</table>
</body>
</html>
(5)运行项目出现如图所示,表示成功
在 SpringMVC 中有两种处理异常的方式,那么就存在一个优先级的问题:
当发生异常的时候,SpringMVC 会如下处理:
a.SpringMVC 会先从配置文件找异常解析器 HandlerExceptionResolver
b. 如果找到了异常异常解析器,那么接下来就会判断该异常解析器能否处理当前发生的异常
c. 如果可以处理的话,那么就进行处理,然后给前台返回对应的异常视图
d. 如果没有找到对应的异常解析器或者是找到的异常解析器不能处理当前的异常的时候,就看当前的 Controller 中有没有提供对应的异常处理器,如果提供了就由 Controller 自己进行处理并返回对应的视图
e. 如果配置文件里面没有定义对应的异常解析器,而当前 Controller 中也没有定义的话,那么该异常就会被抛出来。
1.3.2 文件上传
传统的图片服务器 ftp,就现在而言已经没几个人在用了,当然了,wordpress 相关的插件安装和主题下载就用到 ftp。
当然了,还有不少企业将上传文件 (包含图片等) 放入线上 tomcat 某个文件夹下或者项目里面,这样的弊端使项目会越来越庞大,之前庞大是因为不断增长的需求,代码不得不越多,因此也会扩充容量。
不过目前很多企业通常采用比如腾讯云、阿里云、七牛云等对象存储,作为图片存储。
今天我们就以腾讯云的对象存储为例。
(1)导入依赖
<!– 腾讯云 –>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.2.4</version>
</dependency>
(2)编写工具类
package com.custome;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.URL;
import java.util.Date;
import java.util.Random;
public class COSClientUtil {
//todo 这些变量信息自行到 腾讯云对象存储控制台 获取
private COSClient cOSClient;
private static final String ENDPOINT = “test.com”; // 用户可以指定域名,不指定则为默认生成的域名
//secretId
private static final String secretId = “AKIDCJ”;
// secretKey
private static final String secretKey = “CD7”;
// 存储通名称
private static final String bucketName = “test”;// 公有读私有写
// 1 初始化用户身份信息(secretId, secretKey)
private static COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
// 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
private static ClientConfig clientConfig = new ClientConfig(new Region(“ap-beijing-1”));
// 3 生成 cos 客户端
private static COSClient cosclient = new COSClient(cred, clientConfig);
public COSClientUtil() {
cOSClient = new COSClient(cred, clientConfig);
}
/**
* 销毁
*/
public void destory() {
cOSClient.shutdown();
}
/**
* 上传图片
*
* @param url
*/
public void uploadImg2Cos(String url) throws Exception {
File fileOnServer = new File(url);
FileInputStream fin;
try {
fin = new FileInputStream(fileOnServer);
String[] split = url.split(“/”);
this.uploadFile2Cos(fin, split[split.length – 1]);
} catch (FileNotFoundException e) {
throw new Exception(“ 图片上传失败 ”);
}
}
public String uploadFile2Cos(MultipartFile file) throws Exception {
if (file.getSize() > 10 * 1024 * 1024) {
throw new Exception(“ 上传图片大小不能超过 10M!”);
}
// 图片名称
String originalFilename = file.getOriginalFilename();
System.out.println(“originalFilename = ” + originalFilename);
// 图片后缀
String substring = originalFilename.substring(originalFilename.lastIndexOf(“.”)).toLowerCase();
System.out.println(“substring = ” + substring);
Random random = new Random();
// 生成新的图片名称(随机数 0 -9999+ 系统当前时间 + 上传图片名)
String name = random.nextInt(10000) + System.currentTimeMillis() + “_” + substring;
try {
InputStream inputStream = file.getInputStream();
this.uploadFile2Cos(inputStream, name);
return name;
} catch (Exception e) {
throw new Exception(“ 图片上传失败 ”);
}
}
/**
* 获得图片路径
*
* @param fileUrl
* @return
*/
public String getImgUrl(String fileUrl) {
return getUrl(fileUrl);
}
/**
* 获得 url 链接
*
* @param key
* @return
*/
public String getUrl(String key) {
// 设置 URL 过期时间为 10 年 3600l* 1000*24*365*10
Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
// 生成 URL
URL url = cOSClient.generatePresignedUrl(bucketName, key, expiration);
if (url != null) {
return url.toString();
}
return null;
}
/**
* 上传到 COS 服务器 如果同名文件会覆盖服务器上的
*
* @param instream
* 文件流
* @param fileName
* 文件名称 包括后缀名
* @return 出错返回 ”” , 唯一 MD5 数字签名
*/
public String uploadFile2Cos(InputStream instream, String fileName) {
String ret = “”;
try {
// 创建上传 Object 的 Metadata
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(instream.available());
objectMetadata.setCacheControl(“no-cache”);
objectMetadata.setHeader(“Pragma”, “no-cache”);
objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf(“.”))));
objectMetadata.setContentDisposition(“inline;filename=” + fileName);
// 上传文件
PutObjectResult putResult = cOSClient.putObject(bucketName, fileName, instream, objectMetadata);
ret = putResult.getETag();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (instream != null) {
instream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return ret;
}
/**
* Description: 判断 Cos 服务文件上传时文件的 contentType
*
* @param filenameExtension 文件后缀
* @return String
*/
public static String getcontentType(String filenameExtension) {
if (filenameExtension.equalsIgnoreCase(“bmp”)) {
return “image/bmp”;
}
if (filenameExtension.equalsIgnoreCase(“gif”)) {
return “image/gif”;
}
if (filenameExtension.equalsIgnoreCase(“jpeg”) || filenameExtension.equalsIgnoreCase(“jpg”)
|| filenameExtension.equalsIgnoreCase(“png”)) {
return “image/jpeg”;
}
if (filenameExtension.equalsIgnoreCase(“html”)) {
return “text/html”;
}
if (filenameExtension.equalsIgnoreCase(“txt”)) {
return “text/plain”;
}
if (filenameExtension.equalsIgnoreCase(“vsd”)) {
return “application/vnd.visio”;
}
if (filenameExtension.equalsIgnoreCase(“pptx”) || filenameExtension.equalsIgnoreCase(“ppt”)) {
return “application/vnd.ms-powerpoint”;
}
if (filenameExtension.equalsIgnoreCase(“docx”) || filenameExtension.equalsIgnoreCase(“doc”)) {
return “application/msword”;
}
if (filenameExtension.equalsIgnoreCase(“xml”)) {
return “text/xml”;
}
return “image/jpeg”;
}
}
(3)编写测试 Controller
@PostMapping(value=”/uploadPicture”,produces=”application/json;charset=utf-8″)
public JSONObject upModify(HttpServletRequest request, MultipartFile file) {
JSONObject json = new JSONObject();
try {
COSClientUtil cosClientUtil = new COSClientUtil();
// 获取 Cookie
String cookie = CookieUtils.getCookie(request,”userCode”);
// 解密后的 userCode
String decodeStr = Base64.decodeStr(cookie);
if(!file.isEmpty()) {
String name = cosClientUtil.uploadFile2Cos(file);
// 图片名称
System.out.println(“name = ” + name);
// 上传到腾讯云
String img_url = cosClientUtil.getImgUrl(name);
System.out.println(“img_url = ” + img_url);
// 数据库保存图片地址
String db_img_url = img_url.substring(0,img_url.indexOf(“?”));
System.out.println(“db_img_url = ” + db_img_url);
SysUser user = new SysUser();
user.setUserCode(decodeStr);
user.setAvatar(db_img_url);
// 调用修改逻辑
boolean isModifyUser = userService.updateById(user);
if(isModifyUser) {
json.put(“returnCode”, “000000”);
json.put(“returnMsg”, “ 上传文件成功 ”);
}else {
json.put(“returnCode”, “111111”);
json.put(“returnMsg”, “ 上传文件失败 ”);
}
}else {
json.put(“returnCode”, “222222”);
json.put(“returnMsg”, “ 参数异常 ”);
}
} catch (Exception e) {
e.printStackTrace();
json.put(“returnCode”, “333333”);
json.put(“returnMsg”, “ 特殊异常 ”);
}
return json;
}
(4)编写简单的 html 测试
<!DOCTYPE html>
<html>
<head>
<meta charset=”UTF-8″>
<title> 上传图片测试 </title>
<script type=”text/javascript” src=”../js/jquery-1.8.0.min.js”></script>
<script type=”text/javascript”>
function setImg(obj){// 用于进行图片上传,返回地址
var f = $(obj).val();
if(f == null || f == undefined || f == ”){
return false;
}
if(!/\.(?:png|jpg|bmp|gif|PNG|JPG|BMP|GIF)$/.test(f))
{
alertLayel(“ 类型必须是图片(.png|jpg|bmp|gif|PNG|JPG|BMP|GIF)”);
$(obj).val(”);
return false;
}
var data = new FormData();
$.each($(obj)[0].files,function(i,file){
data.append(‘file’, file);
});
var upload_img = $(“#uploadinput”)[0].files[0];
var url = window.URL.createObjectURL(upload_img);
$.ajax({
type: “POST”,
url: “uploadPicture”,
data: data,
cache: false,
contentType: false, // 必须 false 才会自动加上正确的 Content-Type
processData: false, // 必须 false 才会自动加上正确的 Content-Type
dataType:”json”,
success: function(data) {
alert(data.returnMsg)
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
// 状态
alert(XMLHttpRequest.readyState);
// 错误信息
alert(textStatus);
}
});
}
</script>
</head>
<body>
<input type=”file” id=”uploadinput” name=”file” onchange=”setImg(this)”/>
</body>
</html>
1.3.3 跨域请求
(1)编写拦截器
package com.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class CORSInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
response.addHeader(“Access-Control-Allow-Origin”, “*”);
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 {
}
}
(2)application-mvc.xml 配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path=”/**”/>
<bean class=”com.interceptor.CORSInterceptor”/>
</mvc:interceptor>
</mvc:interceptors>
(3)编写 html 测试
<html>
<head>
<meta charset=”utf-8″>
<script src=”jquery-1.8.0.min.js”></script>
<script>
function test(){
var str=”test”;
$.ajax({
url:”http://192.168.1.125:8080/test-web/user/getCookie”,
type:”POST”,
data : {“str”:str},
dataType : ‘json’,
success:function(data){
alert(data.returnMsg);
},error:function(XMLHttpRequest, textStatus, errorThrown){
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus);
}
});
}
</script>
</head>
<body onload=”test()”>
</body>
1.3.4 表单处理
(1)编写实体
实体可以复用前面的,之所以列出来防止一些读者不理解。
package com.tutorialspoint;
public class Student {
private Integer age;
private String name;
private Integer id;
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
}
(2)编写 Controller
package com.tutorialspoint;
import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;
import org.springframework.ui.ModelMap;
@Controller
public class StudentController {
@RequestMapping(value = “/student”, method = RequestMethod.GET)
public ModelAndView student() {
return new ModelAndView(“student”, “command”, new Student());
}
@RequestMapping(value = “/addStudent”, method = RequestMethod.POST)
public String addStudent(@ModelAttribute(“SpringWeb”)Student student,
ModelMap model) {
model.addAttribute(“name”, student.getName());
model.addAttribute(“age”, student.getAge());
model.addAttribute(“id”, student.getId());
return “result”;
}
}
ModelMap 同 ModelAndView 相同点,将数据已键值对形式返回到前台,而前台只需知道对应的键即可,就可以获得对应的值。
当然就视图与数据分离而言,尽量不要使用 ModelAndView,尽量使用 Model 或者 ModelMap 也可以。
(3)编写 jspstudent.jsp
<%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
<html>
<head>
<title>Spring MVC Form Handling</title>
</head>
<body>
<h2>Student Information</h2>
<form:form method=”POST” action=”/spring-example/addStudent”>
<table>
<tr>
<td><form:label path=”name”>Name</form:label></td>
<td><form:input path=”name” /></td>
</tr>
<tr>
<td><form:label path=”age”>Age</form:label></td>
<td><form:input path=”age” /></td>
</tr>
<tr>
<td><form:label path=”id”>id</form:label></td>
<td><form:input path=”id” /></td>
</tr>
<tr>
<td colspan=”2″>
<input type=”submit” value=”Submit”/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
result.jsp
<%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
<html>
<head>
<title>Spring MVC Form Handling</title>
</head>
<body>
<h2>Submitted Student Information</h2>
<table>
<tr>
<td>Name</td>
<td>${name}</td>
</tr>
<tr>
<td>Age</td>
<td>${age}</td>
</tr>
<tr>
<td>ID</td>
<td>${id}</td>
</tr>
</table>
</body>
</html>
(4)测试启动应用测试,结果如图:
1.3.5 重定向
说到重定向不得不提到一个转发。这里概述一下转发与重定向的区别:
重定向和转发有一个重要的不同:当使用转发时,JSP 容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程。与之相反,重定向方式的含义是第一个页面通知浏览器发送一个新的页面请求。因为,当你使用重定向时,浏览器中所显示的 URL 会变成新页面的 URL, 而当使用转发时,该 URL 会保持不变。重定向的速度比转发慢,因为浏览器还得发出一个新的请求。同时,由于重定向方式产生了一个新的请求,所以经过一次重 定向后,request 内的对象将无法使用。转发和重定向的区别不要仅仅为了把变量传到下一个页面而使用 session 作用域,那会无故增大变量的作用域,转发也许可以帮助你解决这个问题。
重定向:以前的 request 中存放的变量全部失效,并进入一个新的 request 作用域。转发:以前的 request 中存放的变量不会失效,就像把两个页面拼到了一起。
比如 session 的保存,就是转发的一个应用实例。
Session 通过 setAttribute 以键值对的形式保存 Session, 而要获得该 session, 只需 getAttribute 对应的键即可,当然了,Session 也有它的生命周期,即有效期,超过这个有效期则会发生 session 失效问题。
通常 session 有效默认为 30 分钟,可以通过 web.xml 配置修改
<session-config>
<session-timeout>60</session-timeout>
</session-config>
(1)编写示例
package com.tutorialspoint;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class WebController {
@RequestMapping(value = “/index”, method = RequestMethod.GET)
public String index() {
return “index”;
}
@RequestMapping(value = “/redirect”, method = RequestMethod.GET)
public String redirect() {
return “redirect:finalPage”;
}
@RequestMapping(value = “/finalPage”, method = RequestMethod.GET)
public String finalPage() {
return “final”;
}
}
(2)编写 index.jsp 和 final.jspindex.jsp
<%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
<html>
<head>
<title>Spring Page Redirection</title>
</head>
<body>
<h2>Spring Page Redirection</h2>
<p>Click below button to redirect the result to new page</p>
<form:form method=”GET” action=”/spring-example/redirect”>
<table>
<tr>
<td>
<input type=”submit” value=”Redirect Page”/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
final.jsp
<%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
<html>
<head>
<title>Spring Page Redirection</title>
</head>
<body>
<h2>Redirected Page</h2>
</body>
</html>
(3)启动服务器,输入对应的地址
点击红色标记处,会出现如图,这样就表示正常,否则可能是 500,那就是代码有问题或者环境问题
1.4 小结
本章内容主要有 SpringMVC 简介、MyBatis 整合 SpringMVC(主要是在前面的 MyBatis 整合 Spring 基础上进行)、Spring 应用实例等。
通过对这些内容的介绍说明和示例讲解,相信你已经学会使用了。
本文部分内容主要来自笔者博客园