springmvc学习笔记(超详细)

编程入门 行业动态 更新时间:2024-10-11 03:24:12

springmvc<a href=https://www.elefans.com/category/jswz/34/1770117.html style=学习笔记(超详细)"/>

springmvc学习笔记(超详细)

springmvc

1 springmvc初识

1.1 第一个基于注解的 SpringMVC程序

所谓 SpringMVC 的注解式开发是指,在代码中通过对类与方法的注解,便可完成处理器在 springmvc 容器的注册。注解式开发是重点

完成功能:用户提交一个请求,服务端处理器在接收到这个请求后,给出一条欢迎信息,在响应页面中显示该信息

1.1.1 新建maven项目导入web骨架支持

1.1.2 pom.xml
servlet依赖
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope>
</dependency>
springmvc依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.5.RELEASE</version>
</dependency>插件
<build><plugins><!-- 编码和编译和JDK版本 --><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins>
</build>
1.1.3 注册中央调度器

在web.xml中配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns=""xmlns:xsi=""xsi:schemaLocation=" .xsd"version="4.0"><!--1、声明和注册springmvc的核心对象DispatcherServlet2、需要在tomcat服务器启动后,创建DispatcherServlet对象的实例。3、为什么要创建DispatcherServlet对象的实例呢?4、因为DispatcherServlet在他的创建过程中, 会同时创建springmvc容器对象,读取springmvc的配置文件,把这个配置文件中的对象都创建好, 当用户发起请求时就可以直接使用对象了。servlet的初始化会执行init()方法。DispatcherServlet在init()中{//创建容器,读取配置文件WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");//把容器对象放入到ServletContext中getServletContext().setAttribute(key, ctx);}启动tomcat报错,读取这个文件 /WEB-INF/springmvc-servlet.xml(/WEB-INF/myweb-servlet.xml)springmvc创建容器对象时,读取的配置文件默认是/WEB-INF/<servlet-name>-servlet.xml--><servlet><servlet-name>myweb</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--自定义springmvc读取的配置文件的位置--><init-param><!--springmvc的配置文件的位置的属性--><param-name>contextConfigLocation</param-name><!--指定自定义文件的位置--><param-value>classpath:springmvc.xml</param-value></init-param><!--在tomcat启动后,创建Servlet对象load-on-startup:表示tomcat启动后创建对象的顺序。它的值是整数,数值越小,tomcat创建对象的时间越早。 大于等于0的整数。--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>myweb</servlet-name><!--使用框架的时候, url-pattern可以使用两种值1. 使用扩展名方式, 语法 *.xxxx , xxxx是自定义的扩展名。 常用的方式 *.do, *.action, *.mvc等等不能使用 *.jsphttp://localhost:8080/myweb/some.dohttp://localhost:8080/myweb/other.do2.使用斜杠 "/"--><url-pattern>*.do</url-pattern></servlet-mapping>
</web-app>
1.1.3.1 全限定性类名

该中央调度器为一个 Servlet,名称为 DispatcherServlet。

中央调度器的全限定性类名在导入的 Jar 文件 spring-webmvc-5.2.5.RELEASE.jar 的第一个包 org.springframework.web.servlet下可找到

1.1.3.2 <load-on-startup/>

<servlet/>中添加<load-on-startup/>的作用是,标记是否在Web服务器(这里是Tomcat)启动时会创建这个 Servlet 实例,即是否在 Web 服务器启动时

调用执行该 Servlet 的 init()方法,而不是在真正访问时才创建。它的值必须是一个整数。

1、当值大于等于 0 时,表示容器在启动时就加载并初始化这个 servlet,数值越小,该 Servlet的优先级就越高,其被创建的也就越早;

2、当值小于 0 或者没有指定时,则表示该 Servlet 在真正被使用时才会去创建。

3、当值相同时,容器会自己选择创建顺序

1.1.3.3 <url-pattern/>

对于<url-pattern/>,可以写为 / ,建议写为*.do 的形式

1.1.4 创建 SpringMVC 配置文件

在工程的类路径即 src/main/resources 目录下创建 SpringMVC 的配置文件 springmvc.xml。该文件名可以任意命名

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xsi:schemaLocation="://www.springframework/schema/beans/spring-beans.xsd  .xsd"><!--声明组件扫描器--><context:component-scan base-package="com.zwh.controller"/><!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径--><bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--前缀:视图文件的路径--><property name="prefix" value="/WEB-INF/view/" /><!--后缀:视图文件的扩展名--><property name="suffix" value=".jsp" /></bean>
</beans>
1.1.5 创建处理器
//@Controller:创建处理器对象,对象放在springmvc容器中。
@Controller
public class MyController {/*** 准备使用doSome方法处理some.do请求。** @RequestMapping: 请求映射,作用是把一个请求地址和一个方法绑定在一起,一个请求指定一个方法处理。* 属性: 1. value 是一个String,表示请求的uri地址的(some.do)。* value的值必须是唯一的, 不能重复。 在使用时,推荐地址以“/”* 位置:1.在方法的上面,常用的。 2.在类的上面* <p>* 说明: 使用RequestMapping修饰的方法叫做处理器方法或者控制器方法。* 使用@RequestMapping修饰的方法可以处理请求的,类似Servlet中的doGet, doPost* <p>* 返回值:ModelAndView 表示本次请求的处理结果* Model: 数据,请求处理完成后,要显示给用户的数据* View: 视图, 比如jsp等等。*/@RequestMapping(value = "/hello.do")public ModelAndView doSome() {System.out.println("处理hello请求中");// 调用service处理请求,把处理结果放入到返回值ModelAndViewModelAndView mv = new ModelAndView();//  addObject()方法用于向其 Model 中添加数据。Model 的底层为一个 HashMap。mv.addObject("msg", "使用注解的springMVC应用");mv.setViewName("hello");// Model 中的数据存储在 request 作用域中,SringMVC 默认采用转发的方式跳转到视图,本次请求结束,模型中的数据被销毁return mv;}
}
1.1.6 声明组件扫描器
    <!--声明组件扫描器--><context:component-scan base-package="com.zwh.controller"/>
1.1.7 自定义目标页面

这里我们将目标jsp页面都放在web-inf下的view包中,目的是让用户不能直接访问

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body><h1>msg数据:${msg}</h1></body>
</html>测试结果:msg数据:使用注解的springMVC应用

1.2 SpringMVC 执行 执行 流程 ( 理解)

流程图:

执行流程简单分析:

  1. 浏览器提交请求到中央调度器
  2. 中央调度器直接将请求转给处理器映射器。
  3. 处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器。
  4. 中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器
  5. 处理器适配器调用执行处理器。
  6. 处理器将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器
  7. 处理器适配器直接将结果返回给中央调度器。
  8. 中央调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象
  9. 视图解析器将封装了的视图对象返回给中央调度器
  10. 中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。
  11. 中央调度器响应浏览器。

2 SpringMVC注解式开发

2.1 @RequestMapping 定义请求规则

@RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。

用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

通俗讲就好比商品的增删改:都会有前缀,goods/add goods/delete goods/update

这时候就可以在类上添加@RequestMapping(value = “/goods”)

那么方法上就可以直接@RequestMapping(value = “/add”)@RequestMapping(value = “/update”),但是他们都同时具有了父路径/goods

对请求提交方式的定义:

对于@RequestMapping,其有一个属性 method,就是限制请求是采用post还是get方式

当然,若不指定 method 属性,则无论是 GET 还是 POST 提交方式,均可匹配。即对于请求的提交方式无要求。

  • 对请求中携带参数的定义

@RequestMapping 中 params 属性中定义了请求中必须携带的参数的要求。

@RequestMapping(value=”/xxx.do”, params={“name”,”age”}) :要求请求中必须携带请求参数 name 与 age

@RequestMapping(value=”/xxx.do”, params={“!name”,”age”}) :要求请求中必须携带请求参数 age,但必须不能携带参数 name

@RequestMapping(value=”/xxx.do”, params={“name=zs”,”ag=23”}) :要求请求中必须携带请求参数 name,且其值必须为 zs;必须携带参数 age,其其值必须为 23

@RequestMapping(value=”/xxx.do”, params=“name!=zs”) :要求请求中必须携带请求参数name,且其值必须不能为 zs

2.2 接收前端参数及post乱码问题

1、若表单的name属性值与方法参数一致直接取即可

2、若表单的name属性值与方法参数不一致,则在参数前添加@RequestParam(value = “aname”),进行指定name的属性值即可

post请求乱码问题(web.xml):

    <!--注册声明过滤器,解决post请求乱码的问题--><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><!--强制请求对象(HttpServletRequest)使用encoding编码的值--><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><!--强制应答对象(HttpServletResponse)使用encoding编码的值--><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><!--/*:表示强制所有的请求先通过过滤器处理。--><url-pattern>/*</url-pattern></filter-mapping>

2.3 处理器方法的返回值

1、 ModelAndView

若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好

2、String

返回内部资源逻辑视图名,这个字符串与视图解析器中的 prefix、suffix 相结合,即可形成要访问的 URI。

当然,也可以直接返回资源的物理视图名。不过,此时就不需要再在视图解析器中再配置前辍与后辍了。

3、 object

演示:返回学生对象到浏览器

  • 导入 jackson 依赖

           <!--Jackson应该是目前比较好的json解析工具了--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.10.0</version></dependency>
    
  • 引入 jQuery 库

    <script src="js/jquery-3.4.1.js"></script>
    
  • 定义 index 页面

    <html>
    <head><title>$Title$</title>
    </head>
    <script src="js/jquery-3.4.1.js"></script>
    <script type="text/javascript">$(function () {$("button").click(function () {$.ajax({url: "/json1.do",success: function (data) {// JSON.stringify将json数据转换成json字符串document.write(JSON.stringify(data));}})})})
    </script>
    <body>
    <button>提交ajax请求</button>
    </body>
    </html>
    
  • 定义对象 Student

    @Data
    public class Student {private String name;private Integer age;
    }
    
  • 修改处理器类 MyController

    //在类上直接使用 @RestController ,这样子,里面所有的方法都只会返回 json 字符串了,不用再每一个都添加@ResponseBody
    @RestController
    public class MyController {//produces:指定响应体返回类型和编码@RequestMapping(value = "/json1.do")public String json1() throws JsonProcessingException {//创建一个jackson的对象映射器,用来解析数据ObjectMapper mapper = new ObjectMapper();//创建一个对象Student student = new Student("张三", 10);//将我们的对象解析成为json格式String str = mapper.writeValueAsString(student);//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便return str;}
    }
    
  • springmvc配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns=""xmlns:xsi=""xmlns:context=""xmlns:mvc=""xsi:schemaLocation="://www.springframework/schema/beans/spring-beans.xsd://www.springframework/schema/context/spring-context.xsd://www.springframework/schema/mvc/spring-mvc.xsd"><!--注册mvc注解驱动以及处理JSON乱码问题配置--><mvc:annotation-driven><mvc:message-converters register-defaults="true"><bean class="org.springframework.http.converter.StringHttpMessageConverter"><constructor-arg value="UTF-8"/></bean><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"><property name="objectMapper"><bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"><property name="failOnEmptyBeans" value="false"/></bean></property></bean></mvc:message-converters></mvc:annotation-driven><!--声明组件扫描器--><context:component-scan base-package="com.zwh.controller"/><!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--前缀:视图文件的路径--><property name="prefix" value="/WEB-INF/view/"/><!--后缀:视图文件的扩展名--><property name="suffix" value=".jsp"/></bean></beans>
    
  • web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns=""xmlns:xsi=""xsi:schemaLocation=" .xsd"version="4.0"><servlet><servlet-name>myweb</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><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>myweb</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping><!--注册声明过滤器,解决post请求乱码的问题--><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><!--强制请求对象(HttpServletRequest)使用encoding编码的值--><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><!--强制应答对象(HttpServletResponse)使用encoding编码的值--><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><!--/*:表示强制所有的请求先通过过滤器处理。--><url-pattern>/*</url-pattern></filter-mapping>
</web-app>

4、 void

对于处理器方法返回 void 的应用场景,主要有两种。

  • 通过 ServletAPI 传递数据并完成跳转

通过在处理器方法的参数中放入的 ServletAPI 参数,来完成资源跳转时所要传递的数据及跳转。

可在方法参数中放入 HttpServletRequest 或 HttpSession,使方法中可以直接将数据放入到 request、session 的域中,也可通过 request.getServletContext()获取到 ServletContext,从而将数据放入到 application 的域中。

  • AJAX 响应

对若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。

以对象方式整体接收:

单个逐个接收:

jQuery.ajax:

jQuery.ajax(...)部分参数:url:请求地址type:请求方式,GET、POST(1.9.0之后用method)headers:请求头data:要发送的数据contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")async:是否异步timeout:设置请求超时时间(毫秒)beforeSend:发送请求前执行的函数(全局)complete:完成之后执行的回调函数(全局)success:成功之后执行的回调函数(全局)error:失败之后执行的回调函数(全局)accepts:通过请求头发送给服务器,告诉服务器当前客户端课接受的数据类型dataType:将服务器端返回的数据转换成指定类型"xml": 将服务器端返回的内容转换成xml格式"text": 将服务器端返回的内容转换成普通文本格式"html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。"script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式"json": 将服务器端返回的内容转换成相应的JavaScript对象"jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

这里就不做演示,和返回对象类型差不多,只是处理器方法返回值为void,不能表示数据,也没有视图。

所以可以通过httpServletResponse的输出对象,把数据输出到浏览器

5、json输出时间对象

  • 默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数!
  • Jackson 默认是会把时间转成timestamps形式

解决方法:封装工具类

public class JsonUtils {public static String getJson(Object object) {return getJson(object, "yyyy-MM-dd HH:mm:ss");}public static String getJson(Object object, String dateFormat) {ObjectMapper mapper = new ObjectMapper();//不使用时间差的方式mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);//自定义日期格式对象SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);//指定日期格式mapper.setDateFormat(sdf);try {return mapper.writeValueAsString(object);} catch (JsonProcessingException e) {e.printStackTrace();}return null;}
}

2.4 FastJson

fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是一样的。

fastjson 的 pom依赖:

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.60</version>
</dependency>

fastjson 三个主要的类:

  • JSONObject 代表 json 对象
  • JSONArray 代表 json 对象数组
  • JSON 代表 JSONObject和JSONArray的转化

代码测试,我们新建一个MyTest类

public class MyTest {public static void main(String[] args) {//创建一个对象Student Student1 = new Student("1号", 3);Student Student2 = new Student("2号", 3);Student Student3 = new Student("3号", 3);Student Student4 = new Student("4号", 3);List<Student> list = new ArrayList<Student>();list.add(Student1);list.add(Student2);list.add(Student3);list.add(Student4);System.out.println("*******Java对象 转 JSON字符串*******");String str1 = JSON.toJSONString(list);System.out.println("JSON.toJSONString(list)==>" + str1);String str2 = JSON.toJSONString(Student1);System.out.println("JSON.toJSONString(Student1)==>" + str2);System.out.println("\n****** JSON字符串 转 Java对象*******");Student jp_Student1 = JSON.parseObject(str2, Student.class);System.out.println("JSON.parseObject(str2,Student.class)==>" + jp_Student1);System.out.println("\n****** Java对象 转 JSON对象 ******");JSONObject jsonObject1 = (JSONObject) JSON.toJSON(Student2);System.out.println("(JSONObject) JSON.toJSON(Student2)==>" + jsonObject1.getString("name"));System.out.println("\n****** JSON对象 转 Java对象 ******");Student to_java_Student = JSON.toJavaObject(jsonObject1, Student.class);System.out.println("JSON.toJavaObject(jsonObject1, Student.class)==>" + to_java_Student);}
}

2.5 解读<url-pattern/>

1、配置详解

  • *.do

    在没有特殊要求的情况下,SpringMVC 的中央调度器 DispatcherServlet 的<url-pattern/>常使用后辍匹配方式,如写为*.do 或者 *.action, *.mvc 等

  • /

    可以写为/,因为 DispatcherServlet 将会向静态资源的获取请求,例如.css、.js、.jpg、.png等资源的获取请求,当作是一个普通的 Controller 请求。中央调度器会调用处理器映射器为其查找相应的处理器。当然也是找不到的,所以在这种情况下,所有的静态资源获取请求也均会报 404 错误.

*保持<url-pattern/>的值为 .do,扩展名方式,图片会正常显示,将<url-pattern/>的值修改为 / ,则图片将无法显示。

2、静态资源访问

<url-pattern/>的值并不是说写为/后,静态资源就无法访问了。经过一些配置后,该问题也是可以解决的。

方法一:

在web.xml中配置:

 <!--处理静态资源访问-->
<mvc:default-servlet-handler/>

方法二:

在web.xml中配置:

<mvc:resources mapping="/img/**" location="/img/"/>location	表示静态资源所在目录。当然,目录不要使用/WEB-INF/及其子目录
mapping		表示对该资源的请求

2.6 校正请求参数名@RequestParam

所谓校正请求参数名,是指若请求 URL 所携带的参数名称与处理方法中指定的参数名不相同时,则需在处理方法参数前,添加一个注解@RequestParam(“请求参数名”),指定请求 URL 所携带参数的名称。该注解是对处理器方法参数进行修饰的。

@RequestParam()有三个属性:

  • value:指定请求参数的名称。
  • required:指定该注解所修饰的参数是否是必须的,boolean 类型。若为 true,则表示请求中所携带的参数中必须包含当前参数。若为 false,则表示有没有均可。
  • defaultValue:指定当前参数的默认值。若请求 URI 中没有给出当前参数,则当前方法参数将取该默认值。即使 required 为 true,且 URI 中没有给出当前参数,该处理器方法参数会自动取该默认值,而不会报错。

2.7 路径变量@PathVariable

对于处理器方法中所接收的请求参数,可以来自于请求中所携带的参数,也可以来自于请求的 URI 中所携带的变量,即路径变量。

不过,此时,需要借助@PathVariable 注解。

@PathVariable 在不指定参数的情况下,默认其参数名,即路径变量名与用于接收其值的属性名相同。

若路径变量名与用于接收其值的属性名不同,则@PathVariable 可通过参数指出路径变量名称。

@RequestMapping("/{pname}/{age}/register.do")
public MOdelAndView register(@pathVariable("pname") String name,@pathVariable int age){}

3 springmvc核心技术

3.1 请求重定向和转发

3.1.1 返回 ModelAndView 时的请求转发
  • 请求转发到其它 Controller
mv.setViewName("forward:other.do")
  • 请求转发到页面
mv.setViewName("forward:/WEB-INF/jsp/hello.jsp")

重定向使用redirect

注意:

对于请求转发的页面,可以是WEB-INF中页面;

而重定向的页面,是不能为WEB-INF中的页面。

因为重定向相当于用户再次发出一次请求,而用户是不能直接访问 WEB-INF 中资源的。

3.2 异常处理

3.2.1 SimpleMappingExceptionResolver 异常处理器

该方式只需要在 SpringMVC 配置文件中注册该异常处理器 Bean 即可。该 Bean 比较特殊,没有 id 属性,无需显式调用或被注入给其它<bean/>,当异常发生时会自动执行该类。

当请求参数的值与接收该参数的处理器方法形参的类型不匹配时,会抛出类型匹配有误异常 TypeMismatchException。

  • 自定义异常类
// 其他异常类的父类
public class MyStudentException extends Exception {public MyStudentException() {super();}public MyStudentException(String message) {super(message);}
}
// 名字异常类
public class NameException extends MyStudentException {public NameException() {super();}public NameException(String message) {super(message);}
}
// 年龄异常类
public class AgeException extends MyStudentException {public AgeException() {super();}public AgeException(String message) {super(message);}
}
  • 修改 Controller
 @RequestMapping(value = "/exception.do")public ModelAndView doSome(String name, Integer age) throws MyStudentException {ModelAndView mv = new ModelAndView();//根据请求参数抛出异常if (!"张三".equals(name)) {throw new NameException("姓名不正确!!!");}if (age == null || age > 80) {throw new AgeException("年龄比较大!!!");}mv.addObject("myname", name);mv.addObject("myage", age);mv.setViewName("show");return mv;}
  • 注册异常处理器
	// 配置异常处理器<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><prop key="com.zwh.exception.NameException">nameError</prop><prop key="com.zwh.exception.AgeException">ageError</prop></props></property><property name="defaultErrorView" value="defaultErr"/><property name="exceptionAttribute" value="ex"/></bean>
  • 定义异常响应页面
3.2.2 自定义异常处理器

使用 SpringMVC 定义好的 SimpleMappingExceptionResolver 异常处理器,可以实现发生指定异常后的跳转。

但若要实现在捕获到指定异常时,执行一些操作的目的,它是完成不了的。此时,就需要自定义异常处理器。

自定义异常处理器,需要实现HandlerExceptionResolver接口,并且该类需要在SpringMVC配置文件中进行注册。

  • 定义异常处理器
public class MyExceptionResolver implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {ModelAndView mv = new ModelAndView();
//        将异常对象加入到数据模型中mv.addObject("ex", e);
//        设置默认错误响应页面mv.setViewName("defaultError");
//        设置name异常if (e instanceof NameException) {mv.setViewName("nameError");}
//        设置age异常if (e instanceof AgeException) {mv.setViewName("ageError");}return mv;}
}
  • 注册异常处理器
<!--注册异常处理器-->
<bean class="com.zwh.exception.MyExceptionResolver"/>
3.2.3 @ExceptionHandler 注解

使用注解@ExceptionHandler 可以将一个方法指定为异常处理方法。

该注解只有一个可选属性 value,为一个 Class<?>数组,用于指定该注解的方法所要处理的异常类,即所要匹配的异常。

而被注解的方法,其返回值可以是 ModelAndView、String,或 void,方法名随意参数可以是 Exception 及其子类对象、HttpServletRequest、HttpServletResponse 等。系统会自动为这些方法参数赋值。

  • 定义全局异常处理类
@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(value = NameException.class)public ModelAndView doNameException(Exception exception) {ModelAndView mv = new ModelAndView();mv.addObject("msg", "姓名必须是张三,其它用户不能访问");mv.addObject("ex", exception);mv.setViewName("nameError");return mv;}@ExceptionHandler(value = AgeException.class)public ModelAndView doAgeException(Exception exception) {ModelAndView mv = new ModelAndView();mv.addObject("msg", "你的年龄不能大于80");mv.addObject("ex", exception);mv.setViewName("ageError");return mv;}//处理其它异常, NameException, AgeException以外,不知类型的异常@ExceptionHandlerpublic ModelAndView doOtherException(Exception exception) {//处理其它异常ModelAndView mv = new ModelAndView();mv.addObject("msg", "others 异常");mv.addObject("ex", exception);mv.setViewName("defaultError");return mv;}
}
  • 定义 Spring 配置文件
// 注册组件扫描器    
<context:component-scan base-package="com.zwh.exception"/>
// 注册注解驱动
<mvc:annotation-driven />

3.2 拦截器

3.2.1 拦截器的介绍

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。

  • 过滤器

过滤器依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。

使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。

通常用的场景是:在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。

  • 拦截器

拦截器依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。

在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。

由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。

但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。

3.2.2 拦截器的实现
  • 自定义拦截器
public class MyInterceptor implements HandlerInterceptor {//在请求处理的方法之前执行//如果返回true执行下一个拦截器//如果返回false就不执行下一个拦截器@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {System.out.println("------------preHandle处理前------------");String loginName = "";// 从session中获取name值Object name = request.getSession().getAttribute("name");if (name != null) {loginName = (String) name;}// 判断登陆的账户是否符合要求if (!"zs".equals(loginName)) {// 不能够访问系统request.getRequestDispatcher("/fail.jsp").forward(request, response);return false;}return true;}//在请求处理方法执行之后执行@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {// 对原来的dosome执行结果进行二次调整
//        if (modelAndView != null) {
//            // 改变数据
//            modelAndView.addObject("madate", new Date());
//            // 改变视图
//            modelAndView.setViewName("other");
//        }System.out.println("------------postHandle处理后------------");}//在dispatcherServlet处理后执行,做清理工作.@Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {System.out.println("------------afterCompletion清理------------");}
}
  • 注册拦截器
  <!--关于拦截器的配置--><mvc:interceptors><mvc:interceptor><!--/** 包括路径及其子路径--><!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截--><!--/admin/** 拦截的是/admin/下的所有--><mvc:mapping path="/**"/><!--bean配置的就是拦截器--><bean class="com.zwh.interceptor.MyInterceptor"/></mvc:interceptor></mvc:interceptors>

3.3 文件上传

  • 导入文件上传的jar包
<!--文件上传-->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version>
</dependency>
  • 编写前端页面
<form action="upload.do" enctype="multipart/form-data" method="post">文件: <input type="file" name="file"/><input type="submit" value="上传">
</form><a href="download.do">点击下载</a>
  • 配置bean
    <!--文件上传配置--><!--这个bena的id必须为:multipartResolver , 否则上传文件会报400的错误--><bean id="multipartResolver" class="org.springframework.web.multipartmons.CommonsMultipartResolver"><!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以 便正确读取表单的内容,默认为ISO-8859-1 --><property name="defaultEncoding" value="utf-8"/><!-- 上传文件大小上限,单位为字节(10485760=10M) --><property name="maxUploadSize" value="10485760"/><property name="maxInMemorySize" value="40960"/></bean>
  • Controller
	/** 采用file.Transto 来保存上传的文件*/@RequestMapping("/upload.do")public String fileUpload2(@RequestParam("file") MultipartFile photo) throws IOException {if (!photo.isEmpty()) {photo.transferTo(new File("D:\\IDEA\\springmvc-code\\springmvc-05-file\\web\\img\\" + photo.getOriginalFilename()));return "success";}return "fail";}

3.4 Restful风格

3.4.1 Restful介绍
  • 传统方式操作资源

http://127.0.0.1/item/queryUser.action?id=1 查询,GET
http://127.0.0.1/item/saveUser.action 新增,POST
http://127.0.0.1/item/updateUser.action 更新,POST
http://127.0.0.1/item/deleteUser.action?id=1 删除,GET或POST

  • rest风格操作资源

【GET】 /users # 查询用户信息列表

【GET】 /users/1001 # 查看某个用户信息

【POST】 /users # 新建用户信息

【PUT】 /users/1001 # 更新用户信息(全部字段)

【PATCH】 /users/1001 # 更新用户信息(部分字段)

【DELETE】 /users/1001 # 删除用户信息

分析:

传统方式你每次请求的接口或者地址,都在做描述,例如查询的时候用了queryUser,新增的时候用了saveUser ,修改的时候用了updateUser,其实完全没有这个必要。

我使用了get请求,就是查询,使用post请求,就是新增的请求,PUT就是修改,delete就是删除,我的意图很明显,完全没有必要做描述,这就是为什么有了restful。

3.4.2 springmvc实现rest风格
  • 前端页面
<form action="user.do" method="get"><input type="submit" value="REST-GET 提交">
</form><form action="user.do" method="post"><input type="submit" value="REST-POST 提交">
</form><form action="user.do" method="post"><input type="hidden" name="_method" value="DELETE"><input type="submit" value="REST-DELETE 提交">
</form><form action="user.do" method="post"><input type="hidden" name="_method" value="PUT"><input type="submit" value="REST-PUT 提交">
</form>
  • web.xml
    <!--Restful:  HiddenHttpMethodFilter过滤器可以将POST请求转化为put请求和delete请求--><filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
  • controller
@Controller
public class RestFulController {@GetMapping("/user.do")@ResponseBodypublic String getUser() {return "GET-张三";}@PostMapping("/user.do")@ResponseBodypublic String saveUser() {return "POST-张三";}@PutMapping("/user.do")@ResponseBodypublic String putUser() {return "PUT-张三";}@DeleteMapping(value = "/user.do")@ResponseBodypublic String deleteUser() {return "DELETE-张三";}
}

更多推荐

springmvc学习笔记(超详细)

本文发布于:2024-03-06 21:44:51,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1716455.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学习笔记   详细   springmvc

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!