SpringMVC

第一轮总结性笔记

针对表现层的 MVC

M : Model

V : View

C : Controller

不知道你们玩过Struts没,现在Struts都是一些传统的老项目维护在使用,基本是被市场淘汰了;

之前Struts出过几次比较重大失误,虽然后面也在更新,但是大家心里都怕了,所谓一朝被蛇咬,十年怕井绳,而SpringMVC又是由Spring提供的一个web层框架,Spring背后的社区力量可想而知,如今已经成为web层最优秀的框架;

SpringMVC主要是由前端控制器,处理器映射器,处理器适配器,后端控制器,视图解析器等组成

给我两块钱,我给你一张原理图:(面试常问)

  

第一步:用户向服务器发送请求,请求被Spring前端控制器 DispatcherServlet捕获;

第二步: DispatcherServlet调用HandlerMapping对请求URL进行解析,得到请求资源标识符(URL),获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

第三步: DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)

第四步:提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作: >> 1. HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息 >> 2. 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等 >> 3. 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期 >> 4. 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

第五步: Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;

第六步:根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;

第七步:ViewResolver 结合Model和View,将模型数据填充至视图中

第八步:将渲染结果返回给客户端。

SSM整合

https://www.cnblogs.com/msi-chen/p/10531638.html

Controller返回值

ModelAndView: 一般不用 ,Model装载数据,View指定视图

Void : 一般用于返回Json数据,当然也可以在形参上定义request和response

String : 返回的是视图名,可以转发和重定向 return " redirect / forward:index" ; //配合视图解析器

当方法上有@ResponsaBody注解时,mvc不会解析其为跳转路径

POJO:配合@ResponsaBody使用

常用注解和诸多玩法

常用注解

@Conrtoller @RequestBody @Requestarem @ResponseBody

@ResponsaBody注解:将返回的数据封装到Http Response Body中,不会放置到Model中,mvc也不会解析为跳转路径

Json是默认的的一种返回格式(需要相关 jar 的支持)

@RequestBody注解 :可以将请求的Json字符串中的值绑定到Bean上

@RequestMapping : 定义出路起映射规则 value={"/itemList","listItem"},可以是单个值也可以是多个映射规则 数组形式

参数绑定

简单类型参数绑定 保证请求参数key和形参名保持一致即可(8中基本数据类型和包装类和String均受理)

@RequestParam : 请求参数中key和形参名称不一致是使用,进行参数绑定

@RequestParam(value=" ",required=true,default=" ") // 参数名称 -- 是否必须有值 -- 默认给值

绑定POJO,要求参数中的key 和POJO中的属性名得保持一致

绑定包装POJO,页面请求参数如下 stu.name 对应的包装类Class类内有一属性 stu stu内有一属性name

使用简单类型数组接收批量传递的简单数据类型数据,比如String[ ] 或者 POJO内的属性 String[ ]

比如这个:http://localhost:8080/xxx/deleteItem?id=1&id=2&id=3 就可以用Integer[ ] 接收

若相拥List去接收传递的请求参数的话,List必须是一个POJO类内的一个属性,而不能直接以List接收

如果要接收Date类型数据,需要自定义转换器:Conveter

  public class DateConverter implements Converter<String, Date> {
         @Override
         public Date convert(String source) {
                  SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                  try {
                          return simpleDateFormat.parse(source);
                  } catch (ParseException e) {
                          e.printStackTrace();
                  }
                  return null;
         }
}

配置在springmvc.xml中配置Conveter

<!-- 加载注解驱动 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 转换器配置 -->

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
  <property name="converters">
    <set>
      <bean class="com.kkb.ssm.controller.converter.DateConverter"/>
    </set>
  </property>
</bean>

异常处理器

dao,service,controller出现异常都通过throw Exception向上抛出,最后由springmvc交由异常处理器进行异常处理

自定义异常类,继承Excption;

自定义异常处理类 实现HandlerReceptionResolver;

在springmvc.xml中注册该类即可;

图片上传

springmvc的上传,是由commons-fileupload这个jar包实现的

文件上出啊需要指定<form>标签的一个属性 : enctype=”multipart/form-data”

在springmvc中配置Multipart解析器

<!-- multipart类型解析器,文件上传 -->

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 上传文件的最大尺寸 5M-->

<property name="maxUploadSize" value="5242880"/>

</bean>

Controller类:

@RequestMapping(value = "/updateItem")
public String updateItem(Model model,Item item,MultipartFile pictureFile) throws Exception {
         if(pictureFile != null){
                  System.out.println(pictureFile.getOriginalFilename());
                  //原始图片名称
                  String originalFilename = pictureFile.getOriginalFilename();
                  //如果没有图片名称,则上传不成功
                  if(originalFilename != null && originalFilename.length()>0)
                  {
                          //存放图片的物理路径
                         String picPath = "E:\\03-teach\\07-upload\\temp\\";
                          //新文件的名称
                          String newFileName = UUID.randomUUID()+originalFilename.substring(originalFilename.lastIndexOf("."));
                          //新的文件
                          File newFile = new File(picPath+newFileName);
                          //把上传的文件保存成一个新的文件
                          pictureFile.transferTo(newFile);
                          //同时需要把新的文件名更新到数据库中
                          item.setPic(newFileName);
                  }else{
                          throw new BusinessException("图片名称不存在,上传不成功");
                  }
         }          
         // 根据页面传入的商品信息,调用修改方法,进行修改(此时还没有讲参数绑定,暂时无法进行)
         itemService.updateItem(item);
         return "success";

 

Json数据交互

KV结构,请求是Json(一般情况下),@ResponseBody默认响应也是Json 依赖 jackson-databind.jar 当然依赖传递进来的还有一个io.jar

Restful支持

理解:是一种软件架构风格,基于这个风格设计的软件更简洁,更有层次感,Rest指的就是一组架构条件而原则,满足额这个原则设计出来的应用就是Resuful风格

四个表示操作方式的动词: GET 、POST、PUT、DELETE,分别对应四种基本操作

springmvc对RESTful的支持:

web.xml中设置拦截规则为 / ,可以拦截RESTful请求

但也是因为设置了 /,就必须对静态资源进行访问处理

    <!-- 当DispatcherServlet配置为/来拦截请求的时候,需要配置静态资源的访问映射 -->
        <mvc:resources location=*"/js/"* mapping=*"/js/**"*/>
        <mvc:resources location=*"/css/"* mapping=*"/css/**"*/>

@PathVariable注解可以解析出URL中的模版变量 如下所示:

请求URL:http://localhost:8080/ssm/item/1/wangbadan

@RequestMapping(" {id} / {name} ")

public void queryItemByIDAndName(@PathVariable Integer id,@PathVariable String name ){}

@RequestMapping注解可以通过method属性,可以将同一个请求映射到不同的方法上 GET/POST/PUT/DELETE

以至于优化出了以下注解 @GetMapping 、@PostMapping、@PutMapping、@DeleteMapping,效果同上

拦截器:HandlerInterceptor

springmvc有自己的拦截器,实现对请求前后的相关逻辑处理,相当于Servlet的Filter过滤器

springmvc中定义一个Interceptor有一下四种方式:

实现HandlerInterceptor接口,或继承实现了该接口的类 ,比如HandlerInterceptorAdapter

实现Spring的 WebRequestInterceptor接口,或者继承实现了该接口的类

一般常用第一种,实现HandlerInterceptor接口,重写

preHandle :Handler执行前执行,比如登录认证,身份授权,返回Boolean

postHandle :进入Handler,并在返回ModelAndView前执行,一般用于统一指定视图

afterCompletion :执完Handler之后执行,比如异常处理,日志处理,释放资源等

配置拦截器(全局拦截器配置):

<!-- 配置全局mapping的拦截器 -->
<mvc:interceptors>
     <!-- 公共拦截器可以拦截所有请求,而且可以有多个 -->
     <bean class="com.kkb.ssm.interceptor.MyHandlerInterceptor1" />
    <bean class="com.kkb.ssm.interceptor.MyHandlerInterceptor2" />
         <!-- 如果有多个拦截器,则按照顺序进行配置 -->
         <mvc:interceptor>
                  <!-- /**表示所有URL和子URL路径 -->
                  <mvc:mapping path="/test/**" />
         <!-- 特定请求的拦截器只能有一个 -->
                  <bean class="com.kkb.ssm.interceptor.MyHandlerInterceptor3" />
         </mvc:interceptor>
</mvc:interceptors>

如果有多个拦截器,则配置到最上面的拦截器的优先级最高

SpringMVC父子容器

画了个图外加描述理解一下:​

  

Spring和SpringMVC是两个容器;

Spring容器中存放着mapper代理对象,service对象,而SpringMVC中存放的事Controller对象,子容器可以通过@Autowired访问父容器注册过的中的Java实列,反之父容器想注入子容器中的Java实列就不行,比如在service中注入Controller行不通的;

两个容器导入的配置文件,都只能在自己的容器里面使用,不具有传递性

跨域处理

跨域:域名,端口,协议的组合不同的访问就是跨域

解决跨域的方式有多种:基于Js,基于Jq的JSONP以及基于CORS的方式

JSONP只能解决get方式提交触发的跨域问题,CORS支持多种提交方式

CORS是一个W3C标准,全称:“跨资源共享”,他允许浏览器向跨源服务器发起Ajax请求,克服了Ajax只能同源访问的限制

CORS原理:只需要向响应头header中注入Access-Control-Allow-Origin,这样浏览器检测到header中的Access-Control-Allow-Origin,则就可以跨域操作了。

详情见:https://www.cnblogs.com/msi-chen/p/10511558.html

乱码解决

Get提交:

  手段一: 修改Tomcat的编码格式为 UTF-8

  手段二:对请求参数进行重新编码,String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")

Post提交:

  手段一:在web.xml中限定编码

<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>

  手段二:在RequestMapping注解中produces属性,指定响应体的编码格式

posted @ 2019-05-08 22:50  鞋破露脚尖儿  阅读(249)  评论(0编辑  收藏  举报