Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一
Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架
Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请 求的控制器,而无须实现任何接口。
支持 REST 风格的 URL 请求
采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性
org.springframework
spring-webmvc
4.3.20.RELEASE
springDispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:applicationcontext-springmvc.xml
1
springDispatcherServlet
/
Spring MVC 为控制器指定可 以处理哪些 URL 请求使用 @RequestMapping 注解
• 在控制器的类定义及方法定义处都可标注
@RequestMapping
– 类定义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
– 方法处:提供进一步的细分映射信息。相对于类定义处的 URL。若 类定义处未标注 @RequestMapping,则方法处标记的 URL 相对于 WEB 应用的根目录
DispatcherServlet 截获请求后,就通过控制器上
@RequestMapping 提供的映射信息确定请求所对应的处理 方法。
– param1: 表示请求必须包含名为 param1 的请求参数
– !param1: 表示请求不能包含名为 param1 的请求参数
– param1 != value1: 表示请求包含名为 param1 的请求参数,但其值 不能为 value1
– {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
/**
@RequestMapping
* value:请求路径,默认不写
* method:用于指定请求的方法
* params:指定参数规则
* – param1: 表示请求必须包含名为 param1 的请求参数
– !param1: 表示请求不能包含名为 param1 的请求参数
– param1 != value1: 表示请求包含名为 param1 的请求参数,但其值 不能为 value1
– {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
*/
/**
* – ?:匹配文件名中的一个字符
– *:匹配文件名中的任意字符
– **:** 匹配多层路径 包括0层
*/
@RequestMapping("/index/**/??")
public String index() {
return "login";
}
• 带占位符的 URL 是 Spring3.0 新增的功能,该功能在 SpringMVC 向 REST 目标挺进发展过程中具有里程碑的 意义
• 通过 @PathVariable 可以将 URL 中占位符参数绑定到控 制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过
@PathVariable(“xxx”) 绑定到操作方法的入参中。
/**
* 传递参数的方式:
* 第一种,采用路径直接传递参数
* @PathVariable 获取URL中的参数
*/
@RequestMapping("/del/{id}")
public String testPathVar(@PathVariable("id") String id) {
System.out.println(id);
return "login";
}
– value:参数名
– required:是否必须。默认为 true, 表示请求参数中必须包含对应 的参数,若不存在,将抛出异常
/**
* 传递参数的方式:
* 第二种,采用以往的传递参数的形式
* @RequestParam value:指定参数的名称
* required:默认为true,代表必须传参数
*/
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(value="id",required=true) String id) {
System.out.println(id);
return "login";
}
/**
* 使用POJO方式获取参数,注入到Java对象中,但对象的属性名必须与参数名相同
*
*/
@RequestMapping("/dologin2")
public String dologin(LoginUser user) {
System.out.println(user.getUsername()+user.getPassword());
System.out.println(user);
return "success";
}
/**
* 使用原始的servlet拿参数信息
*
*/
@RequestMapping("/testServlet")
public void testServlet(HttpServletRequest request,HttpServletResponse response,HttpSession session) throws IOException {
System.out.println(request.getParameter("id"));
response.sendRedirect("http://www.baidu.com");
}
/**
* 获取头文件
* @RequestHeader:指定参数的名称获取值
*
*/
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader("Accept-Encoding")String Encoding) {
System.out.println(Encoding);
return "login";
}
/**
* 获取cookie值
* @CookieValue:指定参数的名称获取值
*
*/
@RequestMapping("/testCookie")
public String testCookie(@CookieValue("JSESSIONID")String cookie) {
System.out.println(cookie);
return "login";
}
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
ModelAndView: 处理方法返回值类型为 ModelAndView时, 方法体即可通过该对象添加模型数据
Map 及 Model: 入参为 org.springframework.ui.Model、org.springframework.ui. ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
MoelAndView addObject(String attributeName, Object attributeValue)
ModelAndView addAllObject(Map modelMap)
void setView(View view)
void setViewName(String viewName)
/**
* 向页面传递模型数据1
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
ModelAndView modelAndView = new ModelAndView();
LoginUser loginUser = new LoginUser();
loginUser.setUsername("1234");
loginUser.setPassword("123456");
//键值对传参
modelAndView.addObject("loginuser", loginUser);
//向哪个页面传入参数
modelAndView.setViewName("success");
return modelAndView;
}
– Spring MVC 在调用方法前会创建一个隐 含的模型对象作为模型数据的存储容器。
– 如果方法的入参为 Map 或 Model 类 型,Spring MVC 会将隐含模型的引用传 递给这些入参。在方法体内,开发者可以 通过这个入参对象访问到模型中的所有数 据,也可以向模型中添加新的属性数据
/**
* 向页面传递模型数据2
*/
@RequestMapping("/testMap")
public String testMap(Map map) {
LoginUser loginUser = new LoginUser();
loginUser.setUsername("张三 ");
loginUser.setPassword("123456");
map.put("loginuser", loginUser);
return "success";
}
redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
forward:success.jsp:会完成一个到 success.jsp 的转发操作
/**
* 转发和重定向
* 仅仅只需要返回字符串中包含forward或redirect
*/
@RequestMapping("/testforward")
public String testforward() {
return "forward:hello";
}
@RequestMapping("/testredirect")
public String testredirect() {
return "redirect:hello";
}
Spring MVC 为文件上传提供了直接的支持,这种支持是通 过即插即用的== MultipartResolver ==实现的。Spring 用 Jakarta Commons FileUpload 技术实现了一个 MultipartResolver 实现类:CommonsMultipartResovler
Spring MVC 上下文中默认没有装配 MultipartResovler,因 此默认情况下不能处理文件的上传工作,如果想使用 Spring 的文件上传功能,需现在上下文中配置 MultipartResolver
FileUploadAction.java
package com.hqyj.action;
import java.io.File;
import java.io.IOException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
/**
* 1、引入文件上传相关的包io/upload
* 2、Spring配置文件中,配置
*
* 3、form表单:post请求形式,enctype="multipart/form-data"
* 4、后台接收文件MultipartFile.保存文件调用的是transferTo方法将文件传递到硬盘上
*/
@Controller
public class FileUploadAction {
/**
* 文件上传案例
*/
@RequestMapping("/testupload")
public String jump() {
return "upload";
}
@RequestMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file) {
/**
* transferTo()上传文件位置,文件名
*/
try {
file.transferTo(new File("d:\\SpringMvc-upload\\"+file.getOriginalFilename()));
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "success";
}
}
upload.jsp
主要处理 Handler 中用 @ExceptionHandler 注解定义的 方法。
@ExceptionHandler 注解定义的方法优先级问题:例如发 生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近 继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法
ExceptionHandlerMethodResolver 内部若找不 到@ExceptionHandler 注解的话,会找
@ControllerAdvice 中的@ExceptionHandler 注解方法
Testexception.java
package com.hqyj.action.exception;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class Testexception {
@RequestMapping("/testException")
public String testException(@RequestParam("id") int id) {
int i=10/id;
return "success";
}
}
GlobeException.java全局配置注解
package com.hqyj.action.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
/**
*
* 全局异常处理类
*/
@ControllerAdvice
public class GlobeException {
@ExceptionHandler(value= {ArithmeticException.class})
public ModelAndView handlException(Exception e) {
ModelAndView mv = new ModelAndView("error");
System.out.println("算术异常");
mv.addObject("error",e);
return mv;
}
@ExceptionHandler(value= {RuntimeException.class})
public String handlRuntimeException() {
System.out.println("运行时异常");
return "error";
}
}
error.jsp
出错了${error}
结果
pom.xml
4.0.0
com.hqyj
1809_spring-springmvc
0.0.1-SNAPSHOT
war
org.springframework
spring-context
4.3.20.RELEASE
runtime
org.aspectj
aspectjweaver
1.9.2
aopalliance
aopalliance
1.0
mysql
mysql-connector-java
5.1.40
org.springframework
spring-jdbc
4.3.20.RELEASE
com.mchange
c3p0
0.9.5.2
org.springframework
spring-webmvc
4.3.20.RELEASE
com.fasterxml.jackson.core
jackson-core
2.9.7
com.fasterxml.jackson.core
jackson-databind
2.9.7
commons-fileupload
commons-fileupload
1.3.3
web.xml
springDispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:applicationcontext-springmvc.xml
1
springDispatcherServlet
/
applicationcontext-springmvc.xml全局配置
LoginUser.java(实体类)
package com.hqyj.action;
public class LoginUser {
private String username;
private String password;
private Dept dept;
//、、、、、、、、、
//此处省略get和set方法,toString方法,无参构造方法
}
Dept.java
package com.hqyj.action;
public class Dept {
private int id;
private String deptname;
//、、、、、、、、、
//此处省略get和set方法,toString方法,无参构造方法
}
LoginAction.java(控制层)
package com.hqyj.action;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/login")
//@RequestMapping放在类上,一般表示一个模块,这样的话再访问下面的方法,可以写"/login/hello"
public class LoginAction {
/**
* value:请求路径,默认不写
* method:用于指定请求的方法
* params:指定参数规则
* – param1: 表示请求必须包含名为 param1 的请求参数
– !param1: 表示请求不能包含名为 param1 的请求参数
– param1 != value1: 表示请求包含名为 param1 的请求参数,但其值 不能为 value1
– {“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
*/
/*@RequestMapping(value:请求地址,
* method=RequestMethod.POST(以post方式请求),
* params"userid"(必须有userid参数且可以用表达式限制))
* header={"Connection=keep-alive"}
* */
public LoginAction() {
super();
// TODO Auto-generated constructor stub
System.out.println("构建控制器");
}
//响应请求的注解
@RequestMapping("/hello")
//响应一个hello的请求
public String login() {
return "login";
}
/**
* – ?:匹配文件名中的一个字符
– *:匹配文件名中的任意字符
– **:** 匹配多层路径 包括0层
*/
@RequestMapping("/index/**/??")
public String index() {
return "login";
}
/**
* 传递参数的方式:
* 第一种,采用路径直接传递参数
* @PathVariable 获取URL中的参数
*/
@RequestMapping("/del/{id}")
public String testPathVar(@PathVariable("id") String id) {
System.out.println(id);
return "login";
}
/**
* 传递参数的方式:
* 第二种,采用以往的传递参数的形式
* @RequestParam value:指定参数的名称
* required:默认为true,代表必须传参数
*/
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(value="id",required=true) String id) {
System.out.println(id);
return "login";
}
/**
* 获取头文件
* @RequestHeader:指定参数的名称获取值
*
*/
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader("Accept-Encoding")String Encoding) {
System.out.println(Encoding);
return "login";
}
/**
* 获取cookie值
* @CookieValue:指定参数的名称获取值
*
*/
@RequestMapping("/testCookie")
public String testCookie(@CookieValue("JSESSIONID")String cookie) {
System.out.println(cookie);
return "login";
}
/**
* 传统使用注解获取参数
* 每传一个参数都要使用@RequestParam去获取,效率非常低下
*
*/
@RequestMapping("/dologin1")
public String testdologin(@RequestParam("username")String username,@RequestParam("password")String password) {
System.out.println(username);
System.out.println(password);
return "success";
}
/**
* 使用POJO方式获取参数,注入到Java对象中,但对象的属性名必须与参数名相同
*
*/
@RequestMapping("/dologin2")
public String dologin(LoginUser user) {
System.out.println(user.getUsername()+user.getPassword());
System.out.println(user);
return "success";
}
/**
* 使用原始的servlet拿参数信息
*
*/
@RequestMapping("/testServlet")
public void testServlet(HttpServletRequest request,HttpServletResponse response,HttpSession session) throws IOException {
System.out.println(request.getParameter("id"));
response.sendRedirect("http://www.baidu.com");
}
/**
* 向页面传递模型数据1
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
ModelAndView modelAndView = new ModelAndView();
LoginUser loginUser = new LoginUser();
loginUser.setUsername("1234");
loginUser.setPassword("123456");
//键值对传参
modelAndView.addObject("loginuser", loginUser);
//向哪个页面传入参数
modelAndView.setViewName("success");
return modelAndView;
}
/**
* 向页面传递模型数据2
*/
@RequestMapping("/testMap")
public String testMap(Map map) {
LoginUser loginUser = new LoginUser();
loginUser.setUsername("张三 ");
loginUser.setPassword("123456");
map.put("loginuser", loginUser);
return "success";
}
/**
* 转发和重定向
* 仅仅只需要返回字符串中包含forward或redirect
*/
@RequestMapping("/testforward")
public String testforward() {
return "forward:hello";
}
@RequestMapping("/testredirect")
public String testredirect() {
return "redirect:hello";
}
}
login.jsp
登录
success.jsp
登录成功
欢迎你,${loginuser.username}
AjaxAction.java
package com.hqyj.action;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class AjaxAction {
@RequestMapping("/testajax")
public String ajax() {
return "ajax";
}
@RequestMapping("/doajax")
@ResponseBody//响应体,必须走响应体,否则返回的值会返回给处理器
//类似于response.getWriter().print()
public String testjaxdata() {
return "ok";
}
@RequestMapping("/doajaxjson")
@ResponseBody//响应体
public List testajaxjson() {
List users = new ArrayList<>();
// users.add(new LoginUser("zhangsan","123456"));
// users.add(new LoginUser("zhangsan2","123456"));
// users.add(new LoginUser("zhangsan3","123456"));
for(int i = 0;i<3;i++) {
LoginUser user = new LoginUser("zhangsan"+i,"123456");
Dept dept = new Dept();
dept.setId(i);
dept.setDeptname("ceshi"+i);
user.setDept(dept);
users.add(user);
}
return users;
}
}
ajax.jsp
用户名 密码 部门编号 部门名称
结果