SpringMVC常见功能

📅 2026/6/26 13:32:19
SpringMVC常见功能
使用注解编写在实际开发中我们会创建很多Controller来满足业务方面的需求这样就会导致一个问题需要在springmvc.xml配置文件中配置大量的bean标签这样就导致该配置文件变的臃肿起来为了解决这个问题spring MVC提供了一系列的注解通过设置注解可以使springmvc.xml配置文件变的简洁。注册扫描器在配置文件中我们只需要注册一个组件扫描器即可其中base-package写上你的包名即可下面这种写法表示会扫描com.wrj.controller下的所有类该组件扫描器是spring中的内容具体咱在spring中再讲解。!-- 控制器扫描 -- context:component-scan base-packagecom.wrj.controller / !-- 资源映射 -- mvc:resources mapping/images/** location/images/ / !-- 开启注解驱动 特别注意的是如果开启了资源映射那么必须开启驱动注解不然控制器扫描404-- mvc:annotation-driven validatormyValidator /注意如果在你的springmvc.xml文件中配置了静态资源即使用了!-- 资源映射 -- mvc:resources mapping/images/** location/images/ /的话那么需要在你的配置文件中配置注解驱动添加下面内容!-- 开启注解驱动 特别注意的是如果开启了资源映射那么必须开启驱动注解不然控制器扫描404-- mvc:annotation-driven validatormyValidator /如果没有添加注解驱动的话你访问controller的时候会出现404错误。处理器中的注解Controller表示当前类为一个ControllerRequestMapping表示当前方法为Controller中的方法该方法会处理请求被注解的方法的名称是可以随意命名的。当有多个请求可以匹配该方法时可以写上一个String类型的数组如下示例中的test2方法。RequestMapping注解还可以定义在类上面在上面的示例中test1方法和test2方法中的url路径中都包含了/test此时我们把这些相同的url抽取出来放到类上的注解RequestMapping中此时可以称之为命名空间。package com.wrj.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; Controller RequestMapping(/test)//类名上的注解命名空间namespace public class TestController02 { RequestMapping(/test1) public ModelAndView test1(HttpServletRequest request, HttpServletResponse response) throws Exception{ ModelAndView mv new ModelAndView(); mv.addObject(hello, hello annotation); mv.setViewName(annotation1); return mv; } RequestMapping({/test2, /test3}) public ModelAndView test2(HttpServletRequest request, HttpServletResponse response) throws Exception{ ModelAndView mv new ModelAndView(); mv.addObject(name, monkey1024); mv.setViewName(annotation2); return mv; } }通配符在RequestMapping中我们可以使用*号表示通配符从而匹配一系列的请求RequestMapping(/test*)表示请求的url中只要是以test开头就可以被当前方法处理。RequestMapping(/*test)表示请求的url中只要是以test结尾就可以被当前方法处理。RequestMapping(wrj/*/test)表示在/test的前面只能有两级路径第一级必须是wrj而第二级随意例如wrj/1024/test。这种称为路径级数的精确匹配。RequestMapping(wrj/**/test)表示在test的资源名称前面必须以wrj路径开头而其它级的路径包含几级各级又叫什么名称均随意例如wrj/1/0/2/4/test。 这种称为路径级数的可变匹配。请求的提交方式在RequestMapping中有一个method属性改属性可以设置接收请求的提交方式如果不写method属性的话无论你是使用get或者post或者其他方式它都会进行处理。请求中携带的参数在RequestMapping中还有一个属性是params通过这个属性我们可以指定请求中必须携带的参数。RequestMapping(value/test , params{name , age})要求请求中必须携带请求参数 name 与 ageRequestMapping(value/test , params{!name , age})要求请求中必须携带请求参数 age但必须不能携带参数 nameRequestMapping(value/test , params{namejack , age23})要求请求中必须携带请求参数 name且其值必须为jack必须携带参数 age其值必须为 23RequestMapping(value/test , paramsname!jack)要求请求中必须携带请求参数name且其值必须不能为jackcontroller中的方法参数列表也就是说在controller的方法里面我们可以写多个参数也可以一个都不写spring mvc会自动为以下参数进行赋值HttpServletRequestHttpServletResponseHttpSession请求携带的参数用于承载数据的Model获取请求参数中文乱码倘若你的表单请求内容输入了中文那很有可能出现乱码问题我们可以使用spring MVC为开发者提供的CharacterEncodingFilter来解决乱码问题这个其实就是一个过滤器。我们需要在web.xml文件中进行配置最好将其设置在其他过滤器之前因为过滤器是按照web.xml中的顺序执行的!--字符编码过滤器-- filter filter-namecharacterEncodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class !--指定字符编码-- init-param param-nameencoding/param-name param-valueutf-8/param-value /init-param !--强制指定字符编码即如果在request中指定了字符编码那么也会为其强制指定当前设置的字符编码-- init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-namecharacterEncodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping这里可以通过springmvc的源码中看到forceEncoding如果设置为true的话那么不论你是否在request中设置了字符编码spring mvc都会强制将其字符编码设置为我们在web.xml文件中写的字符编码。*特别注意的是过滤器里面的url-pattern是/*如果是/不生效*参数名不一致的情况在实际开发中有可能会有这样的问题就是表单中input的name和spring mvc方法中的参数名不一致这时可以使用RequestParam()注解来解决这个问题这个注解中有三个属性value指定请求参数的名称即表单中input的name值。name同value两者只能使用一个required指定该参数是否是必须传入的boolean类型。若为 true则表示请求中所携带的参数中必须包含当前参数。若为 false则表示有没有均可。defaultValue指定当前参数的默认值。如果请求中没有该参数则当前方法参数将取该默认值。简单总结value和name用一个属性即可表单提交没有赋值defaultValue属性会对其默认赋值设置requiredtrue请求参数必须包含属性。使用对象来接收表单参数倘若表单中的参数较多的话需要在controller的方法里面把这些参数都写上这样就不太方便了我们可以定义一个javabean将表单中的参数都写到javabean的属性里面然后将这个bean作为参数写到controller的方法中。对象属性参数的接收当请求中的参数是一个对象属性中的属性时我们可以在表单中的name中写上对象属性.属性的方式进行处理。form action/regist methodpost 姓名input typetext namenamebr 年龄input typetext nameagebr 学校名称input typetext nameschool.schoolNamebr 学校地址input typetext nameschool.addressbr input typesubmit value提交 /form路径变量Controller除了可以接收表单提交的数据之外还可以获取url中携带的变量即路径变量此时需要使用PathVariable注解来设置其中包含属性value指定请求参数的名称即url中的值当url中的名称和方法参数名称不一致时可以使用该属性解决。name同value两者只能使用一个required指定该参数是否是必须传入的boolean类型。若为 true则表示请求中所携带的参数中必须包含当前参数。若为 false则表示有没有均可。controller中方法的返回值在我们之前写的Controller的方法中返回值都写的是ModelAndView其实还可以返回其他类型的对象在实际应用中需要根据不同的情况来使用不同的返回值ModelAndView既要跳转到前台页面或其他资源又要传递数据String内部或者外部资源voidajax响应或者原始的servlet跳转Object添加jackson的jar依赖在Spring mvc中使用了jackson来进行json数据格式的转换需要在方法上添加一个注解ResponseBody方法返回的对象转为json之后会放入响应体中返回外部资源返回外部资源这里指的是跳转到其他域名的页面上。如果你需要在controller的方法中跳转到外部资源比如跳转到http://www.baidu.com/此时需要在springmvc.xml文件中配置一个BeanNameViewResolver类这个类被称作是视图解析器。在springmvc.xml文件中添加下面内容bean classorg.springframework.web.servlet.view.BeanNameViewResolver / bean idbaidu classorg.springframework.web.servlet.view.RedirectView property nameurl valuehttps://www.baidu.com / /bean其中id是controller中的方法返回值value是要跳转的外部资源的地址。之后修改controller中的方法返回值RequestMapping(/welcome) public String welcome() throws Exception{ //直接填写要跳转的页面的名称 return baidu; }此时在浏览器中输入localhost:8080/welcome页面会跳转到http://www.baidu.com/这个就是跳转到外部资源的方式。转发与重定向区别重定向相当于用户再次发出一次请求并且不能直接访问WEB-INF目录下的资源。需要注意的是重定向的方式在request域中的数据会失效此时可以通过ModelAndView来传递数据但是只能传递基本数据类型和String类型因为spring mvc会将传递的数据以请求参数的方式放到url的后面此时任何数据类型都会被转换为普通的字符串建议将数据放到HttpSession域中。自定义异常处理器倘若我们要在项目中捕获特定的异常然后再根据捕获的异常做一些操作的时候按照以前的写法我们需要在每次捕获异常之后再抛出之前进行操作这段代码就会重复的出现在很多类里面导致代码冗余此时我们可以通过自定义异常处理器来解决。自定义异常处理器需要实现org.springframework.web.servlet.HandlerExceptionResolver接口并且该类!-- 凡是实现了SpringMVC的接口都要注册 -- bean classcom.wrj.custom.MyExceptionResolver/需要在Springmvc.xml配置文件中进行注册。package com.wrj.custom; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyExceptionResolver implements HandlerExceptionResolver{ public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { ModelAndView mv new ModelAndView(); mv.setViewName(error); mv.addObject(ex, e.getMessage()); if(e instanceof MyException){ mv.addObject(ex, 自定义异常); mv.addObject(ex2, e.getMessage()); mv.setViewName(error2); } return mv; } }以后只要系统发生了异常就会执行resolveException方法。跳转至自定义错误页面将异常信息传递给用户。% page contentTypetext/html;charsetUTF-8 languagejava % html head title错误/title /head body ${ex.message} /body /html类型转换器从前台提交到controller中方法的表单数据会根据我们在方法参数中定义的类型来自动转换不用再强制的去转换了这个是通过spring mvc中的默认类型转换器converter来实现的不过这些默认转换器不是万能的有些类型就不能转换比如日期类型此时我们可以自定义一个类型转换器来进行日期类型的转换。spring中新增了DateTimeFormat注解通过该注解可以进行日期类型的转换这样子我们就不用单独编写日期类型的转换器了。DateTimeFormat注解支持joda-time当然如果是的jdk8含之后的版本就不用在引入joda相关的jar包了。package com.wrj.model; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; public class User { private String name; private int age; DateTimeFormat(pattern yyyy-MM-dd) private LocalDate birthday; /* 省略setter和getter */ }数据校验前台校验通常由javascript来完成后台校验主要由java来负责这里我们可以通过spring mvchibernate-validator。dependency groupIdorg.hibernate/groupId artifactIdhibernate-validator/artifactId version6.0.9.Final/version /dependencypackage com.wrj.model; import javax.validation.constraints.*; public class User { NotEmpty(message 姓名不能为空) Size(min 4, max 20, message 姓名长度必须在{min}-{max}之间) private String name; Min(value 0, message 年龄不能小于{value}) Max(value 120,message 年龄不能大于{value}) private Integer age; Pattern(regexp ^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$, message 手机号码不正确) private String phone; public String getName() { return name; } public void setName(String name) { this.name name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone phone; } }!--验证器-- bean idmyValidator classorg.springframework.validation.beanvalidation.LocalValidatorFactoryBean property nameproviderClass valueorg.hibernate.validator.HibernateValidator/ /bean !-- 开启注解驱动 特别注意的是如果开启了资源映射那么必须开启驱动注解不然控制器扫描404-- mvc:annotation-driven validatormyValidator /Controller public class UserController { RequestMapping(register) //不能将Validated 注解在String类型和基本类型的形参前。 //BindingResult参数可以获取到所有验证异常的信息 public ModelAndView register(Validated User user, BindingResult br) { ModelAndView mv new ModelAndView(); ListObjectError allErrors br.getAllErrors(); System.out.println(allErrors.size()); if (allErrors ! null allErrors.size() 0) { FieldError nameError br.getFieldError(name); FieldError ageError br.getFieldError(age); FieldError phoneError br.getFieldError(phone); if (nameError ! null) { mv.addObject(nameError, nameError.getDefaultMessage()); } if (ageError ! null) { mv.addObject(ageError, ageError.getDefaultMessage()); } if (phoneError ! null) { mv.addObject(phoneError, phoneError.getDefaultMessage()); } mv.setViewName(/register); return mv; } mv.addObject(name, user.getName()); mv.setViewName(/user); return mv; } }获取校验信息form action/register methodget 姓名:input typetext namename${nameError}br 年龄:input typetext nameage${ageError}br 手机:input typetext namephone${phoneError}br input typesubmit value提交 /form文件上传form enctypemultipart/form-data methodpost action/upload1 图片:input typefile namephotobr input typesubmit value上传 /form编写处理文件上传的controller在处理文件上传的方法中需要添加MultipartFile类型的参数MultipartFile本身是一个接口里面提供了一些文件上传的操作的方法getOriginalFilename()获得文件名isEmpty()判断是否上传了文件如果没有选择文件上传的话此时结果为truegetContentType()获得上传文件的文件类型transferTo(File file)将文件上传至指定目录中getName()获取表单中input的name值getBytes()获取上传文件的byte数组getInputStream()获取上传文件的InputStream对象方法中的另外一个参数HttpSession的主要作用就是获取服务器中用来存放上传文件的路径。package com.wrj.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpSession; import java.io.File; /** * 文件上传 */ Controller public class UploadController { RequestMapping(/upload1) public void upload1(MultipartFile photo, HttpSession session) throws Exception { if (!photo.isEmpty()) { //获取服务器上传的文件路径 String path session.getServletContext().getRealPath(/upload); //获取文件名称 String filename photo.getOriginalFilename(); //限制文件上传的类型 if (image/png.equals(photo.getContentType())) { File file new File(path, filename); //完成文件上传 photo.transferTo(file); }else { System.out.println(请选择png格式文件上传); } } } }在spring mvc中支持两种上传文件的方式使用apache的commons-io和commons-fileupload实现文件上传使用servlet3.0实现文件上传使用commons组件实现文件上传导入相关jar包dependency groupIdcommons-io/groupId artifactIdcommons-io/artifactId version2.6/version /dependency dependency groupIdcommons-fileupload/groupId artifactIdcommons-fileupload/artifactId version1.3.3/version /dependency在springmvc.xml配置文件中添加multipartResolver这里的id必须要写成multipartResolver会有DispatcherServlet来调用我们可以在这里设置上传文件大小、字符编码等内容!--注册multipartResolver,由DispatcherServlet来负责调用-- bean idmultipartResolver classorg.springframework.web.multipart.commons.CommonsMultipartResolver !--设置字符编码防止文件名乱码-- property namedefaultEncoding valueutf-8/ !--设置上传文件的总大小单位是字节b-- property namemaxUploadSize value1048576/ !--设置单个上传文件的大小单位是字节b-- property namemaxUploadSizePerFile value1048576/ !--设置内存缓冲区的大小当超过该值的时候会写入到临时目录-- property namemaxInMemorySize value1048576/ !--设置临时目录-- property nameuploadTempDir valuetempupload/ !--默认是false如果设置为true的话不会将文件路径去除在IE浏览器下上传时会将路径名也作为文件名上传D:\image\monkey.png-- property namepreserveFilename valuefalse/ !--是否使用懒加载默认是false设置为true的时候当我们操作文件时系统才会对文件进行解析-- property nameresolveLazily valuetrue/ /bean设置临时上传文件目录的作用提高安全性客户端上传的文件直接传到临时目录这样子对于客户端来说隐藏了真实的文件存放目录便于管理当用户取消上传或上传失败的话直接操作临时目录即可无需再去修改真实目录中的文件。将上面内容设置完毕之后就可以实现文件上传了。使用servlet3.0实现文件上传在web.xml中的中央控制器的servlet配置里面添加下面内容location的标签需要写在multipart-config中的第一行!--使用servlet3.0实现文件上传-- multipart-config !--临时文件路径-- location/tempupload/location !--单个上传文件的最大值单位是byte-- max-file-size100/max-file-size !--总上传文件的最大值-- max-request-size52428800/max-request-size !--内存缓冲区的大小,当超过该值时会写入到临时文件中单位是byte-- file-size-threshold1024/file-size-threshold /multipart-config然后需要在springmvc.xml文件中配置multipartResolverbean idmultipartResolver classorg.springframework.web.multipart.support.StandardServletMultipartResolver/配置完成后spring mvc就会使用servlet3.0来实现文件上传了。上传多个文件修改表单多个input的name相同form enctypemultipart/form-data methodpost action/upload2 图片1:input typefile namephotosbr 图片2:input typefile namephotosbr 图片3:input typefile namephotosbr input typesubmit value上传 /form在controller中添加方法方法参数中需要添加MultipartFile[]并且要在其前面加上RequestParam注解RequestMapping(/upload2) public void upload2(RequestParam MultipartFile[] photos, HttpSession session) throws Exception { //获取服务器上传的文件路径 String path session.getServletContext().getRealPath(/upload); for (MultipartFile photo : photos) { if (!photo.isEmpty()) { //获取文件名称 String filename photo.getOriginalFilename(); System.out.println(filename); //限制文件上传的类型 if (image/png.equals(photo.getContentType())) { File file new File(path, filename); //完成文件上传 photo.transferTo(file); } else { System.out.println(请选择png格式的文件上传); } } } }拦截器拦截器interceptor是spring mvc中提供的一种类似filter过滤器的技术只不过拦截器只能拦截controller的请求而filter可以过滤所有请求其他内容大体上两者是近似的。定一个类实现HandlerInterceptor接口这样就创建了一个拦截器该接口中有三个方法preHandle(request, response, Object handler)该方法在controller中的方法执行之前执行。其返回值为 boolean若为 true则紧接着会执行controller方法且会将afterCompletion()方法压栈进入入到一个专门的方法栈中等待执行。postHandle(request, response, Object handler, modelAndView)该方法在controller方法执行之后执行。controller方法若最终未被执行则该方法不会执行。由于该方法是在controller方法执行完后执行且该方法参数中包含 ModelAndView所以该方法可以修改controller方法的处理结果数据且可以修改跳转方向。afterCompletion(request, response, Object handler, Exception ex)当 preHandle()方法返回 true 时会将该方法放到专门的方法栈中等到对请求进行响应的所有工作完成之后才执行该方法。即该方法是在中央调度器渲染数据填充了响应页面之后执行的此时对 ModelAndView 再操作也对响应无济于事。 有点像java里面的finally语句块。