Spring Mvc 
通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,是为了简化开发,减少出错
 
Spring Mvc核心组件 
DispatcherServlet:前置控制器、是整个流程控制的核心、控制其他组件的执行、进行统一调度、降低组件之间的耦合性、总指挥 Handler:处理器、完成具体的业务逻辑、相当于 Servlet HandlerMapping:DispatcherServlet 接收到请求之后、通过 HandlerMapping 将不同的请求映射到不同的 Handler HandlerInterceptor:处理器拦截器、是一个接口、如果需要完成一些拦截处理、可以实现该接口 HandlerExecutionChain:处理器执行链、包括两部分内容:Handler 和 HandlerInterceptor(系统会有一个默认的 HandlerInterceptor、如果需要额外设置拦截、可以添加拦截器) HandlerAdapter:处理器适配器、Handler 执行业务方法之前、需要进行一系列的操作、包括表单数据的验证、数据类型的转换、将表单数据封装到 JavaBean 等、这些操作都是由 HandlerApater 来完成、开发者只需将注意力集中业务逻辑的处理上、DispatcherServlet 通过 HandlerAdapter 执行不同的 Handler ModelAndView:装载了模型数据和视图信息、作为 Handler 的处理结果、返回给 DispatcherServlet ViewResolver:视图解析器、DispatcheServlet 通过它将逻辑视图解析为物理视图、最终将渲染结果响应给客户端
 
Spring Mvc工作流程 
1、客户端请求被 DisptacherServlet 接收 2、根据 HandlerMapping 映射到 Handler 3、生成 Handler 和 HandlerIntercepto 、Handler 和 HandlerInterceptor 以 HandlerExecutionChain 的形式一并返回给 DisptacherServlet 4、DispatcherServlet 通过 HandlerAdapter 调用 Handler 的方法完成业务逻辑处理 5、Handler 返回一个 ModelAndView 给 DispatcherServlet 6、DispatcherServlet 将获取的 ModelAndView 对象传给 ViewResolver 视图解析器,将逻辑视图解析为物理视图 View 7、ViewResovler 返回一个 View 给 DispatcherServlet 8、DispatcherServlet 根据 View 进行视图渲染(将模型数据 Model 填充到视图 View 中) 9、DispatcherServlet 将渲染后的结果响应给客户端
 
Spring Mvc使用方法 
1 2 3 4 5 6 7 8 <dependencies >     <dependency >        <groupId > org.springframework</groupId >        <artifactId > spring-webmvc</artifactId >        <version > 5.1.11.RELEASE</version >      </dependency >    </dependencies >  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <web-app >   <display-name > Archetype Created Web Application</display-name >    <servlet >      <servlet-name > dispatcherServlet</servlet-name >      <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class >      <init-param >        <param-name > contextConfigLocation</param-name >        <param-value > classpath:spring-mvc.xml</param-value >      </init-param >    </servlet >    <servlet-mapping >      <servlet-name > dispatcherServlet</servlet-name >      <url-pattern > /</url-pattern >    </servlet-mapping >  </web-app > 
 
1 2 3 4 5 6 7 8     <context:component-scan  base-package ="com.dream.xiaobo" />      <bean  class ="org.springframework.web.servlet.view.InternalResourceViewResolver" >          <property  name ="prefix"  value ="/" > </property >          <property  name ="suffix"  value =".jsp" > </property >      </bean >  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Controller @RequestMapping(value = "/hello") public  class  MyHandler   {    @RequestMapping(value = "/index",              method = RequestMethod.GET,             params = {"id=1","name=xiaobo", "sex=nan"})     public  String index (@RequestParam("id")  Integer sId,                          @RequestParam("name")  String sName,                         @RequestParam("sex")  String sSex)  {        System.out.println("控制器执行了" );         System.out.println(sId);         System.out.println(sName);         System.out.println(sSex);         return  "index" ;     } 
 
@RequestMapping:将URL请求与业务方法进行映射 @Controller:使其该类成为一个控制器、接受客户端请求、并将该类放入到IOC容器中 value:URL地址值 method:请求类型、get、post、put、delete params:请求中必须包含的参数、否则无法访问、限制请求参数 @RequestParam:与形参映射、给形参赋值、当形参和params参数相同时可自动赋值、否则需要@RequestParam赋值  
 
1 2 3 4 5 6 @RequestMapping(value = "/xiaobo/{id}/{name}", method = RequestMethod.GET)     public  String index2 (@PathVariable("id")  Integer id, @PathVariable("name")  String name)  {         System.out.println(id);         System.out.println(name);         return  "index" ;     } 
 
@ParhVariable:与形参映射、给形参赋值
 
1 2 3 4 5 @RequestMapping(value = "/cookie")     public  String cookie (@CookieValue(value = "JSESSIONID")  String sessionId)  {         System.out.println(sessionId);         return  "index" ;     } 
 
1 2 3 4 @RequestMapping("/forward") public  String forward ()  {    return  "forward:/index.jsp" ; } 
 
Spring Mvc默认是转发、所以可以省略
 
1 2 3 4 @RequestMapping("/redirect") public  String redirect ()  {    return  "redirect:/index.jsp" ; } 
 
Spring Mvc数据绑定 
后端直接获取客户端请求中的参数、将参数映射到形参中、数据绑定工作是由HandlerAdapter完成的
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @RestController @RequestMapping(value = "/data") public  class  MyHandler   {         @RequestMapping(value = "jiben")      public  String jiben (@RequestParam(value = "num",                                       required = false,                                     defaultValue = "0")                                     String[] name)  {        String string = Arrays.toString(name);         return  string;     }   } 
 
@ResponseBody 表示 Spring MVC 会直接将业务方法的返回值响应给客户端、如果不加 @ResponseBody 注解、Spring MVC 会将业务方法的放回值传递给 DispatcherServlet、再由 DisptacherServlet 调用 ViewResolver 对返回值进行解析、映射到一个 JSP 资源 @RestController:表示该控制器会直接将业务方法的返回值响应给客户端、不进行视图解析 @Controller:表示该控制器的每一个业务方法的返回值都会交给视图解析器进行解析 @RequestParam(value = “num”):将 HTTP 请求中名为 num 的参数赋给形参 id requried:设置 num 是否为必填项、true 表示必填、false 表示非必填 defaultValue = “0”:如果 HTTP 请求中没有 num 参数、默认值为0
 
List集合必须进行封装后操作
 
1 2 3 4 @Data public  class  UserList   {    private  List<User> users; } 
 
1 2 3 4 5 6 7 8 @RequestMapping("/list") public  String list (UserList userList)  {    StringBuffer str = new  StringBuffer();     for (User user:userList.getUsers()){         str.append(user);     }     return  str.toString(); } 
 
1 2 3 4 @Data public  class  UserMap   {    private  Map<String,User> users; } 
 
1 2 3 4 5 6 7 8 9 @RequestMapping("/map") public  String map (UserMap userMap)  {    StringBuffer str = new  StringBuffer();     for (String key:userMap.getUsers().keySet()){         User user = userMap.getUsers().get(key);         str.append(user);     }     return  str.toString(); } 
 
1 2 3 4 5 6 7          <dependency >        <groupId > com.alibaba</groupId >        <artifactId > fastjson</artifactId >        <version > 1.2.62</version >      </dependency >  
 
1 2 3 4 5   <servlet-mapping >      <servlet-name > default</servlet-name >      <url-pattern > *.js</url-pattern >    </servlet-mapping >  
 
1 2 3 4 5 6 7 8 9 10 <mvc:annotation-driven >                  <mvc:message-converters  register-defaults ="true" >              <bean  class ="org.springframework.http.converter.StringHttpMessageConverter" >                  <property  name ="supportedMediaTypes"  value ="text/html;charset=UTF-8" > </property >              </bean >              <bean  class ="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter" > </bean >          </mvc:message-converters >      </mvc:annotation-driven >  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <%@ page contentType="text/html;charset=UTF-8"  language="java"  %> <html> <head>     <title>json页面</title>     <script type="text/javascript"  src="js/jquery-3.2.1.min.js" ></script>     <script type="text/javascript" >         $(function () {             var  person = {                 "id"  : 1 ,                 "name"  : "xiaobo" ,                 "sex"  : "男"              };             $.ajax({                 url:"/data/json" ,                 type:"post" ,                 dataType:"JSON" ,                 contentType:"appliaction/json;charset=UTF-8" ,                 data:JSON.stringify(person),                 success:function (data) {                     alert(data.id + "---"  + data.name + "---"  + data.sex)                 }             })         });     </script> </head> <body> </body> </html> 
 
1 2 3 4 5 6 7 8 9 10 @RequestMapping(value = "/json", method = RequestMethod.POST)     public  Person json (@RequestBody  Person person)  {         System.out.println(person);         person.setId(666 );         person.setName("小博" );         person.setSex("男" );         System.out.println(person);         return  person;     } 
 
1 2 3 4 5 6 7 8 9 10 11 @RequestMapping(value = "servlet")     public  String httpServlet (HttpServletRequest request)  {         Person person = new  Person();         person.setId(1 );         person.setName("xiaobo" );         person.setSex("男" );         request.getSession().setAttribute("person" ,person);         return  "view" ;     } 
 
Spring Mvc REST 
资源表现层状态 URL简洁 有利于不同系统之间资源共享
 
使用方法 
GET用来表示获取资源(select) POST用来新建资源(insert) PUT用来表示修改资源(update) DELETE用来表示删除资源(delete)
 
1 2 3 4 5 6 7 8 9 10 public  interface  PersonRepository   {    public  Collection<Person> findAll ()  ;     public  Person findById (Integer id)  ;     public  void  saveOrUpdate (Person person)  ;     public  void  deleteById (Integer id)  ; } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Repository public  class  PersonRepositoryImpl  implements  PersonRepository  {    private  static  Map<Integer,Person> map;     static {         map = new  HashMap<>();         map.put(1 ,new  Person(1 ,"xiaobo" ,"男" ));         map.put(2 ,new  Person(2 ,"wyb" ,"男" ));         map.put(3 ,new  Person(3 ,"wangyibo" ,"男" ));     }     @Override      public  Collection<Person> findAll ()   {         return  map.values();     }     @Override      public  Person findById (Integer id)   {         return  map.get(id);     }     @Override      public  void  saveOrUpdate (Person person)   {         map.put(person.getId(),person);     }     @Override      public  void  deleteById (Integer id)   {         map.remove(id);     } } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @RestController @RequestMapping(value = "/reft") public  class  ReftController   {    @Autowired      private  PersonRepositoryImpl personRepository;     @GetMapping(value = "/findAll")      public  Collection<Person> findAll (HttpServletResponse response)  {         response.setContentType("text/json;charset=UTF-8" );         return  personRepository.findAll();     }     @GetMapping(value = "/findById/{id}")      public  Person findById (@PathVariable("id")  Integer id,HttpServletResponse response)  {         response.setContentType("text/json;charset=UTF-8" );         return  personRepository.findById(id);     }     @PutMapping(value = "/saveOrUpdate")      public  void  saveOrUpdate (@RequestBody  Person person)  {         personRepository.saveOrUpdate(person);     }     @DeleteMapping(value = "/deleteById/{id}")      public  void  deleteById (@PathVariable("id")  Integer id)  {         personRepository.deleteById(id);     } } 
 
文件上传(upload) 
1 2 3 4 5 6 7 8 9 10 11 <dependency >       <groupId > commons-io</groupId >        <artifactId > commons-io</artifactId >        <version > 2.5</version >      </dependency >      <dependency >        <groupId > commons-fileupload</groupId >        <artifactId > commons-fileupload</artifactId >        <version > 1.3.3</version >      </dependency >  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <%@ page contentType="text/html;charset=UTF-8"  language="java"  %> <%@ page isELIgnored="false"  %> <html> <head>     <title>上传</title> </head> <body> <form action="/file/upload"  method="post"  enctype="multipart/form-data" >     <input type="file"  name="sc" >     <input type="submit"  value="提交" > </form> <img src="${requestScope.path }" > </body> </html> 
 
1 <bean  id ="multipartResolver"  class ="org.springframework.web.multipart.commons.CommonsMultipartResolver"  /> 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Controller @RequestMapping(value = "/file") public  class  UploadController   {    @PostMapping(value = "/upload")      public  String upload (MultipartFile sc, HttpServletRequest request)  {         if (sc.getSize() > 0 ){                          String path = request.getServletContext().getRealPath("/file" );                          String filename = sc.getOriginalFilename();             File file = new  File(path,filename);             try  {                                  sc.transferTo(file);                                  request.setAttribute("path" ,"/file/" +filename);             } catch  (IOException e) {                 e.printStackTrace();             }         }         return  "upload" ;     } } 
 
同时上传多个文件 
1 2 3 4 5 6 7 8 9 10 11 <body> <form action="/file/upload"  method="post"  enctype="multipart/form-data" >     <input type="file"  name="sc" >     <input type="file"  name="sc" >     <input type="file"  name="sc" >     <input type="submit"  value="提交" > </form> <c:forEach items="${files}"  var ="file"  >     <img src="${file}"  width="300px" > </c:forEach> </body> 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @Controller @RequestMapping(value = "/file") public  class  UploadController   {    @PostMapping(value = "/upload")      public  String upload (MultipartFile[] sc, HttpServletRequest request)  {         List<String> list = new  ArrayList<>();         for (MultipartFile multipartFile: sc){             if (multipartFile.getSize() > 0 ){                                  String path = request.getServletContext().getRealPath("/file" );                                  String filename = multipartFile.getOriginalFilename();                 File file = new  File(path,filename);                 try  {                                          multipartFile.transferTo(file);                     list.add("/file/"  + filename);                                          request.setAttribute("files" ,list);                 } catch  (IOException e) {                     e.printStackTrace();                 }             }         }         return  "upload" ;     } } 
 
文件下载 1 2 3 4 5 <body> <a href="/file/download/springMvc" >springMvc.png</a> <a href="/file/download/IOC" >IOC.png</a> <a href="/file/download/MVC" >MVC.png</a> </body> 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Controller @RequestMapping(value = "/file") public  class  DownloadController   {    @GetMapping(value = "/download/{name}")      public  void  download (@PathVariable  String name, HttpServletRequest request, HttpServletResponse response)  {         if (name != null ){             name += ".png" ;             String path = request.getServletContext().getRealPath("file" );             File file = new  File(path,name);             OutputStream outputStream = null ;             if (file.exists()){                 response.setContentType("application/forc-download" );                 response.setHeader("Content-Disposition" ,"attachment;filename=" +name);                 try  {                     outputStream = response.getOutputStream();                     outputStream.write(FileUtils.readFileToByteArray(file));                     outputStream.flush();                 } catch  (IOException e) {                     e.printStackTrace();                 } finally  {                     if (outputStream != null ){                         try  {                             outputStream.close();                         } catch  (IOException e) {                             e.printStackTrace();                         }                     }                 }             }         }     } } 
 
Spring MVC 表单标签库 1 <%@ taglib prefix="form"  uri="http://www.springframework.org/tags/form"  %> 
 
1 2 3 4 5 6 7 @GetMapping("/get") public  ModelAndView get ()  {    ModelAndView modelAndView = new  ModelAndView("tag" );     Student student = new  Student(1 ,"xiaobo" ,21 );     modelAndView.addObject("student" ,student);     return  modelAndView; } 
 
1 2 3 4 5 6 <form:form modelAttribute="student" >         学生ID:<form:input path="id" /><br/>         学生姓名:<form:input path="name" /><br/>         学生年龄:<form:input path="age" /><br/>         <input type="submit"  value="提交" />     </form:form> 
 
Spring Mvc数据校验 
1 2 3 4 5 6 7 8 9 10 11 12 public  class  AccountValidator  implements  Validator   {    @Override      public  boolean  supports (Class<?> aClass)   {         return  Account.class.equals(aClass);     }     @Override      public  void  validate (Object o, Errors errors)   {         ValidationUtils.rejectIfEmpty(errors,"name" ,null ,"姓名不能为空" );         ValidationUtils.rejectIfEmpty(errors,"password" ,null ,"密码不能为空" );     } } 
 
1 2 <bean  id ="accountValidator"  class ="com.southwind.validator.AccountValidator" > </bean > <mvc:annotation-driven  validator ="accountValidator" > </mvc:annotation-driven > 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependency >   <groupId > org.hibernate</groupId >    <artifactId > hibernate-validator</artifactId >    <version > 5.3.6.Final</version >  </dependency > <dependency >   <groupId > javax.validation</groupId >    <artifactId > validation-api</artifactId >    <version > 2.0.1.Final</version >  </dependency > <dependency >   <groupId > org.jboss.logging</groupId >    <artifactId > jboss-logging</artifactId >    <version > 3.3.2.Final</version >  </dependency > 
 
1 <mvc:annotation-driven  /> 
 
1 2 3 4 5 6 7 8 9 10 11 @Data public  class  Person   {    @NotEmpty(message = "用户名不能为空")      private  String username;     @Size(min = 6,max = 12,message = "密码6-12位")      private  String password;     @Email(regexp = "^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\\\.[a-zA-Z0-9-]+)*\\\\.[a-zA-Z0-9]{2,6}$",message = "请输入正确的邮箱格式")      private  String email;     @Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\\\\\d{8}$",message = "请输入正确的电话")      private  String phone; } 
 
@Null                    被注解的元素必须为null @NotNull                  被注解的元素不能为null @Min(value)                 被注解的元素必须是一个数字,其值必须大于等于指定的最小值 @Max(value)                被注解的元素必须是一个数字,其值必须小于于等于指定的最大值 @Email                     被注解的元素必须是电子邮箱地址 @Pattern                  被注解的元素必须符合对应的正则表达式 @Length                   被注解的元素的大小必须在指定的范围内 @NotEmpty                  被注解的字符串的值必须非空
 
正确的开始、微小的长进、然后持续、嘿、我是小博、带你一起看我目之所及的世界……