MyBatis集成SpringMVC
本章主要内容包含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.xsdhttp://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(); //获取CookieString cookie = CookieUtils.getCookie(request,"userCode");//解密后的userCodeString 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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {response.addHeader("Access-Control-Allow-Origin", "*");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic 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)编写jsp
student.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.jsp
index.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应用实例等。
通过对这些内容的介绍说明和示例讲解,相信你已经学会使用了。
本文部分内容主要来自笔者博客园
MyBatis集成SpringMVC相关推荐
- 从web.xml谈谈SpringMVC集成spring的初始化流程及SpringBoot集成SpringMVC
一.关于servlet 详解servlet,https://www.runoob.com/servlet/servlet-tutorial.html 总览一下: servlet与servlet容器 J ...
- maven,spring,mybatis集成错误
maven,spring,mybatis集成的时候单元测试junit测试没问题,但mvn jetty:run 就报错误 错误: org.apache.ibatis.binding.BindingExc ...
- 【SpringBoot零基础案例02】【IEDA 2021.1】SpringBoot框架集成SpringMVC
新建一个模块,加入Spring Web依赖 创建完成后我们可以在右侧[Maven]选项卡中看到SpringBoot已经自动配置集成了json.tomcat.spring以及springmvc等信息,不 ...
- 使用MyBatis集成阿里巴巴druid连接池(不使用spring)
在工作中发现mybatis默认的连接池POOLED,运行时间长了会报莫名其妙的连接失败错误.因此采用阿里巴巴的Druid数据源(码云链接 ,中文文档链接). mybatis更多数据源参考博客链接 . ...
- springboot+mybatis集成自定义缓存ehcache用法笔记
今天小编给大家整理了springboot+mybatis集成自定义缓存ehcache用法笔记,希望对大家能有所办帮助! 一.ehcache介绍 EhCache 是一个纯Java的进程内缓存管理框架,属 ...
- (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合
http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...
- spring boot、mybatis集成druid数据库连接池,实现mysql cluster HA负载均衡访问
spring boot.mybatis集成druid数据库连接池,实现mysql cluster HA负载均衡访问 1.原理实现介绍 本质来说使用连接池是为了节省创建.关闭数据库连接的资源消耗,从而提 ...
- MyBatis6:MyBatis集成Spring事物管理(下篇)
前言 前一篇文章<MyBatis5:MyBatis集成Spring事物管理(上篇)>复习了MyBatis的基本使用以及使用Spring管理MyBatis的事物的做法,本文的目的是在这个的基 ...
- mybatis集成 c3p0数据源
为什么80%的码农都做不了架构师?>>> Mybatis集成c3p0数据源 要想集成其他数据源的话,其实可以直接继承UnpooledDataSourceFactory 即可 p ...
最新文章
- 编译器设计-代码优化
- android eclipse 报error loading /system/media/audio/ xxx 错的解决办法。
- 怎么删除顽固的服务器文件夹,实用技巧:删除Windows XP下顽固文件方法
- vue axios 配置上服务器后报错'Access-Control-Allow-Origin' header](亲测)
- 解决root用户登录Ubuntu12.04 LTS图形界面
- 中石油计算机组成原理a在线考试,计算机组成原理试题A.doc
- 最优化学习笔记(三)——梯度下降法
- 奇怪的电梯(洛谷-P1135)
- 读书日记 莫雨 《一个程序员的奋斗史》Java 面试 感悟 程序员
- OpenMP、MPICH与OpenMPI
- Atata——C# Web测试自动化框架
- B.最大岛屿(dfs)
- 好看的文章排版样式(转)
- Robot Framework操作
- ubuntu下使用code::blocks编译运行一个简单的gtk+2.0项目
- 第十五章笔记 虚拟机管理
- js去空格的其他方法
- 寻宝游戏设定_Excel寻宝游戏
- MyBatis Generator生成代码的几种方式
- 利用python生成二维码 以及批量生成二维码
热门文章
- 开课吧:数据分析的价值体现在哪些方面?
- Java经典基础面试题
- 行业深度见解•SD-WAN对于企业云的重要性 1
- common-jdbc:一个基于SpringJdbcTemplate的高性能数据库操作工具类库
- pg_lightool-postgres数据分布查看工具
- 国内搜索大哥iOS面试题
- Java魔法堂:自定义和解析注解
- 将字符串或数字倒序输出
- 查询软件和硬件列表清单[将文章里代码另存为 list.vbs,双击运行就会出现一个html页面]...
- EIGRP路由协议基本设置