zoukankan      html  css  js  c++  java
  • Java进阶笔记(四):SpringMVC相关

    springMVC是什么:spring提供的用于简化web开发的框架。

    --------------------------------

    view:视图(html)
    Controller:只负责接收请求、转发请求
    service:处理业务逻辑
    Dao:操作数据库

    经典三层(代码架构):
    表现层(view、controller)
    业务层(service)
    Dao层(dao)

    MVC模式(代码组织方式/形式):
    Model模型(数据模型[pojo、vo、po]+业务模型[业务逻辑]):
    View视图(jsp、html):
    Controller控制器(servlet):

    pojo分为:
    vo:value Object,向前台传递数据的
    po:process Object,向数据库持久化数据

    【SpringMVC是表现层的框架,view和controller之间靠数据模型model交互数据。】

    SpringMVC属于web模块,是spring框架的一部分,是后续才出现的。
    SpringMVC通过一套注解,让一个简单的java类成为处理请求的控制器,而无需实现任何接口;同时它还支持RESTful编程风格的请求。
    SpringMVC是为了解决表现层问题的web框架,主要职责是处理前端HTTP请求。


    原生servlet模式:
    一个客户端中有多个servlet。

    SpringMVC模式:
    一个客户端中只有一个DispatcherServlet(前端控制器),这个servlet对应多个Controller。

    ================================

    SpringMVC搭建流程:
    1.使用idea创建maven->maven-archetype-webapp项目
    2.在main文件夹下创建java文件夹和resources文件夹,并配置好这两个文件夹的类型。(Mark Directory as,java文件夹选Sources Root,resources文件夹选Resources Root)
    3.在pom.xml中引入spring webmvc的依赖
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.1.12.RELEASE</version>
    </dependency>
    4.在web.xml中配置servlet标签,class是DispatcherServlet
    <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>springmvc</servlet-name>
      <url-pattern>/<url-pattern>
      <!--
      方式一:带后缀,比如*.action *.do *.aaa
      方式二:/ 不会拦截.jsp (这里用这个)
      方式三:/* 拦截所有,包括.jsp
      -->
    </servlet-mapping>

    5.创建一个java类,使用@Controller注解标注类;使用@RequestMapping注解设置接收请求的url;在方法中使用ModelAndView对象设置要跳转到的前端页面。(ModelAndView对象有addObject("UserName","abc")方法可以设置key与value,前端使用${UserName}获取;setViewName("/WEB-INF/jsp/success.jsp")方法设置要跳转到的页面。)

    6.在Resources文件夹下创建一个springmvc.xml,在其中配置以下信息:
    <!-- 开启Controller扫描 -->
    <context:component-scan base-package="com.xxx.test.controller" />
    <!-- 配置springmvc的视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/jsp/" />
      <property name="suffix" value=".jsp" />
    </bean>

    7.然后回到Controller.java,就可以省略要跳转的页面url的前后缀为:modelAndView.setViewName("success");

    8.再回到springmvc.xml,可以配置处理器映射器和处理器适配器(如果不配置,会使用默认的)
    <!-- 自动选择最合适的处理器映射器,处理器适配器 -->
    <mvc:annotation-driven/>

    9.回到web.xml,使用init-param标签将springmvc.xml引入进去,写在Servlet标签中:
    <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
      </init-param>
    </servlet>

    --------------------------------

    springmvc搭建流程总结:
    1.配置DispatcherServlet前端控制器
    2.开发处理具体业务逻辑的Handler(@Controller、@RequestMapping)
    3.xml配置文件配置controller扫描,配置springmvc三大件
    4.将xml文件路径告诉springmvc(DispatcherServlet)

    ================================

    前端控制器(DispatcherServlet,接收所有url请求,选择Controller,选择返回的页面或直接返回消息):
    负责接收用户请求,分发、获取处理结果后返回给用户。

    springmvc核心三大件:
    处理器映射器(HandlerMapping,类似map,装Controller)、处理器适配器(HandlerAdapter,找到具体执行的Handler并执行,返回ModelAndView)、视图解析器(ViewResolver,将逻辑视图地址转为物理视图地址,返回view对象)。

    Handler:在@Controller标注的类中,每个标注@RequestMapping的方法,都是一个Handler。

    SpringMVC九大组件:
    HandlerMapping(处理器映射器):类似map,用于存储handler,寻找目标handler。
    HandlerAdapter(处理器适配器):用于适配不同的handler执行。(因为@RequestMapping标识的方法接收参数时,可以是bean,可以是String等,需要适配)
    ViewResolver(视图解析器):用于将String类型的视图名和Locale解析为View类型的视图。
    HandlerExceptionResolver:处理Handler产生的异常情况。
    RequestToViewNameTranslator:从请求中获取ViewName。
    LocaleResolver:用于国际化处理。
    ThemeResolver:用于解析主题。
    MultipartResolver:用于上传请求。
    FlashMapManager:用于重定向时的参数传递。

    url-pattern配置问题:
    <url-pattern>/</url-pattern>
    不会拦截.jsp,但是会拦截.html以及其它静态资源。
    静态资源配置,解决方法1:
    在springmvc.xml中,配置一个标签:
    <mvc:default-servlet-handler />
    <!-- 原理:添加这个标签后,会在springMVC上下文中定义一个DefaultServletHttpRequestHandler对象,会对url请求过滤筛查,如果发现是一个静态资源请求,那么就会把请求转由web应用服务器(tomcat)默认的DefaultServlet来处理,如果不是静态资源请求,那么继续由springMVC框架处理 -->
    注意:
    需要把静态资源放在webapp下(但不在WEB-INF下)

    静态资源配置,解决方法2(springMVC框架自己处理静态资源):
    在springmvc.xml中,配置:
    <!-- mapping中的值表示,url以resources开头的,则去location的值那里找。【classpath的指resources文件夹】 -->
    <!-- location可以用逗号分隔,例如:"/,classpath:/" -->
    <mvc:resources location="classpath:/" mapping="/resources/**" />
    <mvc:resources location="/WEB-INF/js/" mapping="/js/**" />

    --------------------------------

    @RequestMapping标识的方法(即handler)接收参数时,可以使用Model、Map、ModelMap,以及直接用参数变量接收;之后可以在Model、Map、ModelMap中放入value,前端jsp使用${key}获取值。
    Model、Map、ModelMap这三种类型,运行时的具体类型都是BindingAwareModelMap,相当于用这些Map保存的数据都会放入Request域中。
    BindingAwareModelMap继承了ExtendedModelMap,ExtendedModelMap继承了ModelMap,实现了Model接口。

    --------------------------------

    1.如果要在springMVC中使用servlet原生对象,比如HTTPServletRequest/HttpServletResponse/HttpSession,直接在Handler方法形参中声明使用即可
    2.接收简单数据类型参数,直接在handler方法的形参中声明即可,框架会取出参数值然后绑定到对应参数上。【注意参数名称要一致】
    如果参数不一致,可以这么写:
    @RequestParam("ids")Integer id
    *使用时最好使用包装类型(Integer,而不是int),防止请求参数为null时后台报错。
    *对于Boolean类型的参数,请求时的参数值只能为true/false/1/0,否则后台会报错。

    3.handler如何绑定pojo类型参数:直接形参声明即可,类型就是pojo的类型,形参名无所谓。
    *要求传递的参数名需要和pojo的属性名保持一致

    4.handler如何绑定包装对象参数(一个pojo嵌套另一个pojo):要求传递的参数按规则(pojo.参数名),例如:
    url:http://127.0.0.1:8080/deal?user.id=1&user.name=abc&mid=1

    5.handler如何绑定日期类型参数:
    可以写一个转换用的类(自定义类型转换器),继承Converter接口;写好后,在springmvc.xml中注册,并与<mvc:annotation-driven/>关联
    <mvc:annotation-driven conversion-service="conversion-serviceBean" />

    --------------------------------

    restful风格请求是什么样的?
    restful特性:资源 表现层 状态转移
    rest是一个url请求的风格,基于这种风格设计请求的url
    没有rest的话,原有的url设计:
    url中定义了动作,参数具体锁定到操作的是谁。(http://localhost:8080/user/queryUserById.action?id=1)

    有了rest风格之后:
    rest认为互联网中的所有东西都是资源,既然是资源,就会有一个唯一的url标识它
    http://localhost:8080/user/1  代表的是id为1的用户记录(资源)
    锁定资源之后如何操作它呢?常规操作就是增删改查
    根据请求方式不同,代表要做不同的操作
    get 查询资源
    post 增加,新建资源
    put 更新
    delete 删除资源

    rest风格带来的直观体现:传递参数的变化
    参数是url的一部分(参数可以在uri中)


    对Restful风格请求支持:
    注解@PathVariable
    @RequestMapping(value="/handle/{id}",mathod = {RequestMethod.GET})
    public Model find(@PathVariable("id") Integer id){}

    --------------------------------

    springmvc解决post请求乱码:
    web.xml中配置filter
    <filter>
      <filter-name>encoding</filter-name>
      <filter-class>org.springframework.web.filter.CharacterEncodinngFilter</filter-class>
      <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
      </init-param>
    </filter>

    <filter-mapping>
      <filter-name>encoding</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

    解决GET请求乱码:
    需要修改Tomcat下的server.xml的配置。

    --------------------------------

    jsp中发送put等请求:
    直接配置method标签没有用,需要配置隐藏标签,并在web.xml中配置filter标签,拦截到隐藏标签后,发送指定模式的请求。

    --------------------------------

    Ajax json交互
    1.前端到后台:前端发json,后台直接接收为pojo参数,用注解@RequestBody
    2.前端到后台:后台返回pojo参数,前端接收为json,用注解@ResponseBody

    json数据交互所需jar,3个:
    jackson-core
    jackson-databind
    jackson-annotations


    ================================

    【js中使用$.ajax发送请求时,type为'POST',才会将data中写的参数封装到请求体中;如果type为'GET',则会将data中写的参数封装到url中。】
    【js中使用$.ajax发送json请求时,需要写明contentType:'application/json;charset=utf-8',否则服务器可能会报错】

    ================================

    后台添加@ResponseBody后,返回信息则不再走视图解析器的流程(返回ModelAndView等、返回目标页面的那个),而是等同于response直接输出。

    ================================

    @RequestMapping标识的方法(即handler)返回参数时,可以返回ModelAndView,String(网址或者内容)、

    ================================

    过滤器(Filter):作用在servlet之前,过滤请求。
    监听器(Listener):实现了javax.servlet.ServletContextListener接口的服务器端组件,它随Web应用的启动而启动,只初始化一次,然后会一直运行监视,随web应用的停止而销毁。
    作用一:做一些初始化工作。
    作用二:监听web中的特定事件,例如统计在线人数。(session的创建与销毁)
    拦截器(Interceptor):【是springMVC、Struts等表现层框架自己的】,不会拦截jsp/html/css/image的访问等,只会拦截访问的控制器方法(Handler)。
    可以拦截的地方:
    handler执行之前、
    在handler执行完毕但未跳转页面之前
    在跳转页面之后拦截一次

    配置位置:过滤器、监听器在web.xml中配置;而拦截器在springmvc.xml中配置。

    拦截器常用位置:在handler执行前拦截,进行权限校验。

    拦截器使用方法:
    1.新建一个类,实现HandlerInterceptor接口,类中重写三个方法,分别是:
    preHandle()//handler方法执行前
    postHandle()//handler方法执行后跳转页面前
    afterCompletion()//页面跳转后

    2.这些方法传入了Object handler参数,可以用这个确定是哪个handler。

    3.经常在preHandle()方法中进行权限校验工作,返回值boolean代表是否放行,true表示放行,false表示终止。

    4.可以在postHandle()方法中对返回的数据和视图信息进行修改,这个方法接收了ModelAndView参数。

    5.可以在afterCompletion()方法中进行异常捕获,这个方法接收了Exception参数,但是一般不用。

    6.之后,需要在springmvc.xml中注册这个自定义拦截器:
    <!-- 这样会拦截所有的handler -->
    <mvc:interceptors>
      <bean class="com.test.xxx.interceptor.MyIntercepter01" />
    </mvc:interceptors>

    <!-- 也可以配置拦截url的路径,使用exclude配置不拦截的url的路径 -->
    <mvc:interceptors>
    <mvc:interceptor>
      <mvc:mapping path="/**" />
      <mvc:exclude-mapping path="/demo/**" />
      <bean class="com.test.xxx.interceptor.MyIntercepter01" />
    </mvc:interceptor>
    </mvc:interceptors>

    如果配置了多个自定义拦截器,会按照springmvc.xml中拦截器的配置顺序进行拦截;preHandle()方法是顺序执行,postHandle()与afterCompletion()方法是逆序执行。

    ================================

    SpringMvc如何处理multipart形式的数据,也就是如何处理文件上传:
    对原生srevlet处理文件上传的方法进行了封装

    1.引入jar包commons-fileupload
    2.客户端:
    form表单
    (1)method=post
    (2)enctype=multipart
    (3)file组件
    3.服务端:
    原始方法servlet:解析文件上传流
    springmvc:
    (1)重命名(给一个唯一的名字)
    (2)存储到磁盘(考虑同一个目录文件过多,可以按照日期创建新的文件夹)
    (3)把文件路径更新到数据库
    4.springmvc中配置文件上传解析器

    --------------------------------

    文件上传具体代码:
    1.客户端:
    <fieldset>
    <form method="post" enctype="multipart/form-data" action="/upload">
      <input type="file" name="uploadFile" />
      <input type="submit" value="上传" />
    </form>
    </fieldset>

    2.后台:
    @RequestMapping(value = "/upload")
    public ModelAndView upload(MultipartFile uploadFile, HttpSession session) throws IOException{
      //处理上传文件
      //重命名,获取后缀
      String oriName = uploadFile.getOriginalFilename();
      String ext = oriName.substring(oriName.lastIndexOf(".")+1, oriName.length());
      String newName = UUID.randomUUID().toString() + "." + ext;
      //存储到指定文件夹
      //如果存储到WEB-INF中,就可以通过url直接访问该文件
      //考虑文件过多的情况,可以按照日期生成子文件夹
      //根据项目相对路径获取磁盘绝对路径
      String realPath = session.getServletContext().getRealPath("/uploads");
      String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
      File folder = new File(realPath + "/" + datePath);
      if(!folder.exits()){
        folder.mkdirs();
      }
      //存储文件目录
      uploadFile.transferTo(new File(folder, newName));
      
      //TODO 文件磁盘路径更新到数据库字段
      
      //跳转到成功页面
      ModelAndView modelAndView = new ModelAndView();
      modelAndView.addObject("msg","成功!");
      modelAndView.setViewName("success");
      return modelAndView;

    }

    3.在springmvc.xml配置文件中配置:
    <!-- 多元素解析器,id固定为multipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
      <!-- 设置上传文件大小上限,单位是字节,-1代表没有限制,默认为-1 -->
      <property name="maxUploadSize" value="5000000" />
    </bean>

    ================================

    SpringMVC异常处理机制:
    SpringMVC异常处理器,可以处理handler抛出的异常:
    1.在Controller类中创建一个方法,加注解:
    //可以指明一个异常类
    @ExceptionHandler(ArithmeticException.class)
    //下面声明的形参的异常范围性需要大于等于注解中的异常
    public void handleException(ArithmeticException exception,HttpServletResponse response){
      //异常处理逻辑
      try{
        response.getWriter().write(exception.getMessage());
      }catch(IOException e){
      }
      
    }

    2.写在一个Controller中,只会对当前Controller生效

    3.可以新建一个类,使用注解【@ControllerAdvice】,就可以捕获所有Controller类中的handle抛出的异常了。
    可以在新类中新建一个方法,使用【@ExceptionHandler】注解,捕获一类异常;
    然后return ModelAndView,让某类异常统一返回到一个错误页面。

    ================================

    springMVC重定向时参数传递的问题:
    转发与重定向的区别:

    转发:A->B->C
    url不会变,参数也不会丢失,一个请求

    重定向:A->B->A->C
    url会变,参数会丢失,需要重新携带参数,两个请求

    解决代码如下:
    @RequestMapping("/handle1")
    public String handle1(String name,RedirectAttributes redirectAttributes) {
      //这个方法设置了一个flash类型的属性,该属性会被暂存到session中,在跳转到页面之后,该属性会销毁
      redirectAttributes.addFlashAttribute("name",name);
      return "redirect:handle2";

    }

    @RequestMapping("/handle2")
    public ModelAndView handle2(@ModelAttribute("name")String name) {
      //从model中获取name
      System.out.println(name);
      ...
    }  


     

  • 相关阅读:
    Unstar A File:
    star 一个文件
    列出大星号文件
    删除用户
    curl -d
    创建用户
    Check Account Info
    List Accounts
    认证ping
    python 解接口返回的json字符串
  • 原文地址:https://www.cnblogs.com/codeToSuccess/p/13906191.html
Copyright © 2011-2022 走看看