SpringMVC
SpringMVC
视图View
负责页面的显示;与用户的交互。包含各种表单。 实现视图用到的技术有html/css/jsp/js等前端技术。
用户交互:用户鼠标点击页面;填写页面中各种表单........等等
模型Model
模型负责各个功能的实现(如登录、增加、删除功能)。模型用JavaBean实现
控制器Controller
控制器负责将视图与模型一一对应起来。相当于一个模型分发器。所谓分发就是:
①接收请求,并将该请求跳转(转发,重定向)到模型进行处理。
②模型处理完毕后,再通过控制器,返回给视图中的请求处。建议使用Servlet实现控制器。
在配置文件中配置SpringMVC
web.xml
<!-- 配置前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置SpringMVC核心文件的位置 默认去WEB-INF下寻找--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/springmvc-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> <!-- 所有请求都会被拦截 --> </servlet-mapping>
springmvc-servlet.xml
<!-- 配置映射关系 --> <bean name="/hello.action" class="com.wiscom.demo.FirstController"></bean> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"></property> <property name="suffix" value=".jsp"></property> </bean>
com.wiscom.demo.FirstController
package com.wiscom.demo; public class FirstController implements Controller{ public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { // 处理数据和界面 ModelAndView mav = new ModelAndView(); // 添加数据 mav.addObject("msg1", "hello"); mav.addObject("msg2", "springmvc"); // 设置界面 mav.setViewName("first");//WEB-INF/first.jsp return mav; } }
first.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML> <html> <head> </head> <body> welcome <hr> <p>${msg1}</p> <p>${msg2}</p> </body> </html>
使用注解方式配置SpringMVC
web.xml
<!-- 配置前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置SpringMVC核心文件的位置 默认去WEB-INF下寻找--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/springmvc-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
springmvc-servlet.xml
<!-- 开启包扫描 --> <context:component-scan base-package="com.wiscom.demo"></context:component-scan> <context:annotation-config></context:annotation-config> <!-- 开启mvc注解配置 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"></property> <property name="suffix" value=".jsp"></property> </bean>
com.wiscom.demo.FirstController
package com.wiscom.demo; @Controller //将FirstController交由Spring进行管理 public class FirstController { @RequestMapping("/test01.action") public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } @RequestMapping("/test02.action") public String test02(){ // 返回的字符串代表的是View的名称 return "first"; } }
first.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML> <html> <head> </head> <body> welcome <hr> <p>${msg1}</p> <p>${msg2}</p> </body> </html>
SpringMVC细节
可以在类上添加映射(@RequestMapping)
在类上添加@RequestMapping
在方法上添加@RequestMapping
@Controller //将FirstController交由Spring进行管理 @RequestMapping("/Detail02") public class FirstController { @RequestMapping("/test01.action") public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
@RequestMapping中的属性
可以配置多个路径
@RequestMapping({"/test01.action","/test01*.action"})
params:有这些属性时被请求传过来时才能够被调用执行
@RequestMapping(value="/test03.action",params={"username","password"})
method:method设置为POST时,只能接受POST的数据
@RequestMapping(value="/test03.action",method=RequestMethod.POST)
常用POST,GET
headers:只有传过来的请求包含相关头部时才会被调用(很少使用)
@RequestMapping(value="/test03.action",headers={"host"})
注解属举例
指定要将当前处理器绑定到哪个访问路径上。
可以配置多个路径。
@Controller //将FirstController交由Spring进行管理 public class FirstController { @RequestMapping({"/test01.action","/test01*.action"}) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
params
params
有这些属性时被请求传过来时才能够被调用执行
@Controller //将FirstController交由Spring进行管理 public class FirstController { @RequestMapping(value="/test03.action",params={"username","password"}) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
method
method=RequestMethod.POST
method设置为POST时,只能接受POST的数据
@Controller //将FirstController交由Spring进行管理 public class FirstController { @RequestMapping(value="/test03.action",method=RequestMethod.POST) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
headers
headers
只有传过来的请求包含相关头部时才会被调用
@Controller //将FirstController交由Spring进行管理 public class FirstController { @RequestMapping(value="/test03.action",headers={"host"}) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
处理器方法支持的参数类型和返回值类型
支持的方法参数类型
HttpServletRequest
代表当前请求的对象
HttpServletResponse
代表当前响应的对象
HttpSession
代表当前会话的对象
WebRequest
SpringMVC提供的对象,相当于是request和session的合体,可以操作这两个域中的属性
InputStream OutputStream Reader Writer
代表request中获取的输入流和response中获取的输出流
@PathVariable
可以将请求路径的指定部分获取赋值给指定方法参数
@RequestParam
public void test05(@RequestParam(value="nn") String nnn){ System.out.println(nnn); }
可以将指定请求参数赋值给指定方法参数,如果不写此注解,则默认会将同名的请求参数赋值给方法参数
@CookieValue
可以将请求中的指定名称的cookie赋值给指定方法参数
@RequestHeader
以将请求参数中的指定名称的头赋值给指定方法参数
Model和ModelMap和java.util.Map
向这些Model ModelMap Map中存入属性,相当于向模型中存入数据
MultipartFile
实现文件上传功能时,接收上传的文件对象
package com.wiscom.demo; @Controller //将FirstController交由Spring进行管理 @RequestMapping("/cbt") public class FirstController { @RequestMapping(value="/test01.action") // User中的属性在请求中要按照顺序发送 public void test05(User user){ System.out.println(user); } @RequestMapping(value="/test02.action") public void test05(@RequestParam(value="nn") String nnn){ System.out.println(nnn); } @RequestMapping("/test03.action") public void test06(String[] like){ // System.out.println(like); System.out.println(Arrays.toString(like)); } }
支持的返回值类型
ModelAndView
可以返回一个ModelAndView对象,在其中封装Model和View信息
View
可以直接返回一个代表视图的View对象
字符串
直接返回视图的名称
void
如果返回值类型是void,则会自动返回和当前处理器路径名相同的视图名
@ResponseBody
当方法被@ResponseBody修饰时,默认将返回的对象转为json写入输出
除以上之外返回的任何内容都会被当做模型中的数据来处理,而返回的视图名等同于当前处理器路径名
获取Request Response对象
获取请求参数
通过request对象获取
@RequestMapping(value="/test03.action") public void test03(HttpServletRequest request,HttpServletResponse response){ // 返回的字符串代表的是View的名称 System.out.println(request); // 获取请求参数 String username = request.getParameter("username"); int age = Integer.parseInt(request.getParameter("age")); String password = request.getParameter("password"); User user = new User(age,username,password); System.out.println(user); // System.out.println(response); System.out.println(username + "~~" +age); }
直接接收请求参数
@RequestMapping(value="/test04.action") public void test04(String username,int age){ // 返回的字符串代表的是View的名称 System.out.println(username + "~~" +age); }
自动封装请求参数信息到bean
@RequestMapping(value="/test05.action") public void test05(User user){ // 请求中的参数必须与bean中的属性一一对应 System.out.println(user); }
处理复杂类型
FirstController.java
@RequestMapping(value="/test01.action") public void test05(User user){ System.out.println(user); }
test2.jsp
<form action="${pageContext.request.contextPath}/cbt/test01.action" method="get"> 年龄:<input type="text" name="age"> 姓名:<input type="text" name="username"> 密码:<input type="text" name="password"> 狗龄:<input type="text" name="Dog.age"> 狗名:<input type="text" name="Dog.name"> <input type="submit" value="提交"> </form>
请求参数中的名称和属性名不同的处理@RequestParam
value
参数名字,即入参的请求参数名字,如value=“delId”
required
是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;
defaultValue
默认值,表示如果请求中没有同名参数时的默认值
@RequestMapping(value="/test02.action") public void test05(@RequestParam(value="nn") String nnn){ System.out.println(nnn); }
请求参数中存在多个同名参数
FirstController.java
@RequestMapping("/test03.action") public void test06(String[] like){ // System.out.println(like); System.out.println(Arrays.toString(like)); }
test3.jsp
<form action="${pageContext.request.contextPath}/cbt/test03.action" method="get"> <input type="checkbox" name="like" value="wzry"/>王者荣耀 <input type="checkbox" name="like" value="lol"/>英雄联盟 <input type="checkbox" name="like" value="dota"/>刀塔 <input type="checkbox" name="like" value="chij"/>绝地求生 <input type="submit" value="提交"> </form>
请求参数中的中文乱码
SpringMVC提供了过滤器用来解决全站乱码
只能解决post请求的乱码
web.xml
<!-- 使用SpringMVC的过滤器来解决中文乱码问题 针对于post提交 get提交无效 -->
<filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
get请求的乱码处理
System.out.println(new String(username.getBytes("iso8859-1"),"utf-8"));
日期数据的处理
test2.jsp
<form action="${pageContext.request.contextPath}/cbrt/test02.action" method="get"> 年龄:<input type="text" name="age"> 姓名:<input type="text" name="username"> 日期:<input type="date" name="tday"> <input type="submit" value="提交"> </form>
FirstController.java
@InitBinder public void binding(ServletRequestDataBinder bind){ // 设置日期默认的解析格式 bind.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); } @RequestMapping(value="/test02.action") public void test02(String username,int age,Date tday){ // 2019-08-21 2019/08/21 System.out.println(username); System.out.println(age); System.out.println(tday); }
SpringMVC文件上传
文件上传的三个必要条件
表单必须是Post提交
表单必须是enctype="multipart/form-data"
文件上传项必须有name属性
test2.jsp
<form action="${pageContext.request.contextPath}/cbrt/test02.action" method="post" enctype="multipart/form-data"> 年龄:<input type="text" name="age"> 姓名:<input type="text" name="username"> <input type="file" name="fx"> <input type="submit" value="提交"> </form>
springmvc-servlet.xml
在配置文件中配置文件上传工具
<!-- 配置文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上传最大体积 --> <!-- <property name="maxUploadSize"></property> --> <!-- 上传占用最大内存大小 --> <!-- <property name="maxInMemorySize"></property> --> <!-- 上传后存放临时文件夹的位置 --> <!-- <property name="uploadTempDir"></property> --> </bean>
FirstController.java
实现文件上传
@RequestMapping(value="/test02.action") public void test02(String username,int age,MultipartFile fx) throws IOException{ // 向本地c盘存放客户端上传的文件 getOriginalFilename:得到文件的原始名称 FileUtils.writeByteArrayToFile(new File("c://"+fx.getOriginalFilename()), fx.getBytes()); }
RESTFul风格的请求
普通的get请求
Url:localhost:XXXX/addUser.action?name=tom&age=18
restfull风格的请求
Url:localhost:XXXX/addUser/tom/18.action
FirstController.java
@Controller //将FirstController交由Spring进行管理 public class FirstController { @RequestMapping("/restful/{username}/{age}.action") public void restful(@PathVariable String username,@PathVariable int age){ System.out.println(username + "~" + age); } }
pringMVC中的重定向和转发的实现
// 转发 @RequestMapping("/test01.action") public String test01(){ return "forward:/index.jsp"; } // 转发 @RequestMapping("/test02.action") public String test02(){ return "forward:/test01.action"; } // 重定向 @RequestMapping("/test03.action") public String test03(){ return "redirect:/index.jsp"; }
SpringMVC中session的使用
model中的域默认是request域
可以通过在类上加@SessionAttributes注解将他变为session域
@Controller //将FirstController交由Spring进行管理 @SessionAttributes("msg") public class FirstController { // 四大作用域 // request: 默认SpringMVC使用的就是request // session:可以在处理器的形参中直接获取HttpSession对象 // 也可以先在处理器的形参中获取HttpServletRequest,然后再间接的获取session // servletContext:可以通过HttpServletRequest获取session,在获取servletContext // pageContext @RequestMapping("/test01.action") public String test01(Model model){ model.addAttribute("msg", "red apple"); return "first"; } }
异常处理
为当前Controller配置错误处理
当前Controller出错时执行的方法
@ExceptionHandler
FirstController.java
@Controller public class FirstController { // 作为异常的拦截方法 @ExceptionHandler public void exceptionDemo(Exception e){ System.out.println(e.getMessage()); } }
注解方式配置全局的错误处理
全局出现异常时使用此方法处理
@ControllerAdvice
FirstController.java
@Controller @ControllerAdvice //为全局配置异常拦截 public class FirstController { // 作为异常的拦截方法 @ExceptionHandler public void exceptionDemo(Exception e){ System.out.println(e.getMessage()); } }
实现返回一段数据 - AJAX
@RequestMapping("test07.action") @ResponseBody public Hero test07() throws IOException{ Hero hero = new Hero(); hero.setAge(16); hero.setName("张三丰"); hero.setJob("道士"); return hero; }