Spring MVC补充

Spring MVC框架中的细节:

1、静态资源的访问权限

由于Spring MVC的前端控制器DispatcherServlet中配置的路径是/,表示缺省的servlet 意味着当前端访问servlet的时候,当找不到,就会匹配该前端控制器的 DispatcherServelt

由于当使用spring mvc框架的时候,项目中就不需要编写Servlet了(JSP本质上也是 Servlet),因此当前端的请求来了会与jsp页面进行匹配,然后就会进入前端控制中。

思考:

1)如果前端访问的资源是静态资源呢?

经过测试,如果使用spring mvc框架配置了前端控制器,jsp页面仍旧可以直接访 问,但是静态资源(html\css\javascript)无法访问。这是由于访问静态资源的请求 在匹配不到jsp之后会进入前端控制器与方法进行映射,没有找到则会报错。

2)针对1)的问题该如何解决?

可以进行如下配置:

<mvc:resource mapping=”/js/**” location=”/js/”>

该配置表示当请求url中包含”/js/**”时,就去/js/路径去匹配相应的资源,而不进 入前端控制器

还可以配置<mvc:default-servlet-handler/>,该配置表示如果前端控制器没有匹配到 相应的资源,则采用原始的tomcat容器进入资源匹配。

2、请求数据的乱码问题

当前端使用post请求发送数据,如果数据包含中文时,后端接收数据会出现乱码问题。

get方式的请求,乱码问题tomcat内部已经解决)

1)如果采用request对象获取数据:

request.setCharacterEncoding(“utf-8”);

2)如果采用spring mvc框架进行前端控制,不需要直接操作request对象了,可以配置 一个过滤器,所有的请求来了都进入该过滤器并将编码设置成UTF-8即可。

备注:url-pattern/*表示所有的请求都进入该filer,优先级高,与1中的/相比,该路 径表示缺省,优先级低,是找不到再匹配该路径

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

3、请求参数的自动封装

当前端请求进入前端控制器之后,前端控制器从springmvc容器中获取对象并调用方法,这就涉及到请求中的参数与方法参数之间的一个映射关系。

请求中的参数是都是string类型的键值对,方法中的参数按类型可以分为是基本数据类型、对象、数组、集合。

1)当方法中的参数是基本数据类型

请求中的参数自动按相同的参数名称进行映射(请求中key值与方法形参相同时, value值作为实参传入方法)。

2)当方法中的参数是普通的java对象

请求中的参数自动按java对象相同的属性名称进行映射,将请求参数封装进一个 java对象,并将该对象作为实参传入方法。

3)当方法中的参数类型是数组

请求中的参数如果中存在相同的key对应不同的value值,将会自动将对应的key 组成一个数组,传给方法中与key值相同的形参。

4)当方法中的参数是集合

从上面1)和2)可知,springmvc参数的映射要么是请求的key值与形参相同,与某个对象的属性值相同,然后框架通过反射调用set方法进行封装的。

因此如果想要将一个前端请求的参数封装进行一个集合中,可以编写一个类,这个类定义一个集合的成员变量,然后方法的形参是与该成员变量相同,则框架底层会尝试将前端的数据封进该对象的属性(也就是集合)。问题是前端页面的参数只能是键值对,如何与集合中的元素对应起来?

因此,在前端页面的key值不仅要指定要属性名(key值与对象的成员变量相同),还要指定封进入集合中的那个位置(采用索引),还需要指定需要封进集合中该位置上对象的那个属性。格式如下:

<input type=”text” name=”userList[0].name” placeholder = “请填入姓名”>

备注:重点在userList[0].name的书写,如方法中的参数为UserList userListUserList类中有个private List<User> userList成员变量,此时需要将前端请求的参数封装进UserList对象,所以前端页面key值首先写userList,表示要封进UserList对象的userList属性中,由于该属性是一个集合,然后写[0]表示封进索引为0的元素中,然后写name表示封进索引为0的元素的name属性中(User对象有name属性)。

备注:如果前端页面通过adjax请求直接发送一个json格式的数据到Controller的方法,可以在该方法中的集合形参前面加上@RequestBody,表示将该adjax请求的数据直接封进集合中。

4SpringMVC RESTfu风格的请求

spring mvc中可以使用占位符来接收url路径上的值,将该值当作参数传递给占位符, 例如:

访问的url为:http://localhost:8080/test/demo/zhangsan

controller层:

@Controller

@RequestMapping(“/test”)

public class ControllerDemo{

@RequestMapping(“/demo/{name}”)

public void test(@PathVariable(value=”name”,required =”true”) String username){

System.out.println(name);

}

}

上述代码表示,@RequestMapping(“/demo/{name}”)中使用{name}作为占用符,用于接 收匹配到的url路径上的值,访问的是/test/demo/zhangsan,匹配到的路径是 “/test/demo/{name}”,其中占位符name会接受zhangsan这个参数,然后在方法的参数 列表中,@PathVariable(value=”name”) String username表示将占位符name获得的值给 username,其中requiredtrue表示,路径必有与占位符匹配上。

5、自定义转换器

(定义一个类实现Converter接口,指定泛型<T,S>表示将T类型的转成S类型,复写 conver方法,然后在spring-mvc.xml中配置ConversionServiceFactoryBeanBean对象, 将编写的转换器放入converters属性中,然后再在注解驱动中表示)

前端请求到达服务器端都是字符串类型的,但是已知当前端请求匹配到方法之后,会进 行数据的自动封装,而且封装的不一样是字符串,例如url中包含参数age=23,方法中 含有参数int age,此时字符串型的”23”能被封进整型的age中,这是由于spring mvc中 内置了默认的类型转化器,能自动实现类型转换。但是内置的默认类型转换器有时候并 不能满足需求,也可以自定义类型转换器,可以设置在遇到指定类型的数据时,让spring mvc按照指定的方法进行转换。

譬如:当url中包含date=2020-02-02时,内置的默认转换器无法将”2020-02-02”转成Date 对象,可以进行自定义。

spring mvc中提供了Converter接口,编写一个转换器实现该接口,该接口有泛型<T,S>T 表示需要被转换的类型,在url中的类型都是String,因此这里的T应该是String,而S 表示需要转成的类型,此处需要将String转成Date,这个S表示Date

public class DateConverter implements Converter<String,Date>{

public Date conver(String str){

SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd”);

Date date = format.parse(str);//这里会抛异常,try...catch...包裹或直接抛

return date;

}

}

然后在spring-mvc.xml进行配置:

<bean id = “converter” class=”ConversionServiceFactoryBean类全包名”>

<property name = “converters”>

<list>

<bean class = “自定义转换器的全类名”>

</list>

</property>

</bean>

<mvc:annotation-driven conversion-service =”converter”>

6、文件上传

备注:将前端页面的文件封装成一个MulitiPartFile对象并自动与方法中的形参进行匹 配,底层依赖commons-fileuploadcommons-io,因此需要导包。

文件上传三要素:

1、表单项type=”file”;

2、表单的提交方式为post;

3、表单的enctype属性是多部分表单形式,即enctype=”multipart/form-data”

<form action=${pageContext.request.contextPath}/test method = “post”

enctype=”multipart/form-data”>

名称:<input type =”text” name=”name”><br>

文件:<input type=”file” name=”file”><br>

<input type=”submit” value=”提交”>

</form>

Spring MVCCommonsMultipartResolver组件,可以将前端页面的文件封装成 MultipartFile对象。

CommonsMultipartResolver组件的配置:

<bean id = “multiPartResover” class =”CommonsMultipartResolver全类名”>

<property name=”defaultEncoding” value=”UTF-8”>

<property name=”maxUploadSize” value=”50000”>

</bean>

7、Spring MVC拦截器

(采用aop思想,当请求来了之后,在控制器方法执行之前、执行后返回视图前、返回 视图后,进行统一的逻辑操作)

spring mvc中的拦截器类似与filter,是针对前端发来的请求进行拦截并且只会拦截控制 器中的方法(html\css\javascript\jsp)不会拦截,采用aop的思想,可以在请求到达控 制器方法之前、控制方法执行之后视图返回之前和视图放回之后进行相应的操作。

自定义拦截器的步骤:

1)定义一个类实现HandlerInterceptor接口;

2)复写preHandle方法表示在请求到达控制器方法之前执行;

3)复写postHandle方法表示控制器方法执行之后视图返回之前执行;

4)复写afterCompletion方法表示视图返回之后执行。

5)上面三个方法按需要复习,也可以不复写。

6)spring-mvc.xml中配置拦截器

<mvc:interceptors>

<mvc:interceptor>

<mvc:mapping path=”/**”>

<mvc:exclude-mapping path=”指定路径uri”>

<bean class=”编写的拦截器的全类名”/>

</mvc:interceptor>

</mvc:interceptors>

备注:如果配置了多个拦截器,则按配置的路径依次执行。

8、Spring MVC中的异常处理

(针对不同的异常显示不同的页面)

web项目中daoservicecontroller层中都有可能出现异常,一旦出现异常,就应该 向前端页面显示指定的错误页面(避免把程序中的异常直接显示在前端页面)。在编写 dao\service\controller三层的时候,异常都直接抛出。spring mvc提供了异常处理器 HandlerExceptionResolver,可以在spring-mvc.xml中进行配置。

Spring MVC异常处理器:

1spring mvc内置的默认异常处理器SimpleMappingExceptionResolver

2、自定义异常处理器:

步骤:

1)定义一个类实现HandlerExceptionResolver接口;

2)复写resolveException方法;

3)在spring-mvc.xml中配置(配置该类的Bean对象即可)

posted @ 2020-05-17 06:41  wuyiping  阅读(158)  评论(0编辑  收藏  举报