SpringMVC Controller控制器详解
Controller控制器作用
- 收集、验证请求参数并绑定到命令对象;
- 将命令对象交给业务对象,由业务对象处理并返回模型数据;
- 返回ModelAndView(Model部分是业务对象返回的模型数据,视图部分为逻辑视图名)。
核心注解
@Controller : 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。
/** * @Controller,类级别上的注解。我们定义的类可以只是一个 javabean,不需要实现任何接口。标注了 * @Controller,借助 <context:component-scan>,框架能自动识别到这就是一个 Controller */ @Controller public class MyController { // ...... }
@RequestMapping : @RequestMapping 来映射URL 到控制器类,或者是到Controller 控制器的处理方法上。当@RequestMapping 标记在Controller 类上的时候,里面使用@RequestMapping 标记的方法的请求地址都是相对于类上的@RequestMapping 而言的;当Controller 类上没有标记@RequestMapping 注解时,方法上的@RequestMapping 都是绝对路径。这种绝对路径和相对路径所组合成的最终路径都是相对于根路径“/ ”而言的。
- value: 路径地址
- method:请求方法的规则,比如:如果设置了RequestMethod.POST,那么你的表单提交就必须使用POST提交,否则将报405错误
- params: 提交中的数据中一定要有配置的参数(如id),否则将报400的错误
/** * @RequestMapping 可以出现在类级别上,也可以出现在方法上。如果出现在类级别上,那请求的 url 为 类级别 * 上的 @RequestMapping + 方法级别上的 @RequestMapping,否则直接取方法级上的 @RequestMapping。 * 类级别的 @RequestMapping 不是必需的。 */ @Controller @RequestMapping("/my") public class MyController { /** * 由于类级别上定义了 @RequestMapping,那么想匹配到这个方法来处理请求,url 必须为 /my/somelist。 * 如果没有定义类级别上的 @RequestMapping,url 为 /somelist 即可。同时,请求方法必须为 POST */ @RequestMapping(value="/somelist", method=RequestMethod.POST); public String getSomeList() {...} /** * 在方法级别使用 @RequestMapping 来限定请求处理的时候,可以指定两个属性。除了我们在上面刚使用过的 * method 属性,还有一个 params 属性。使用 params 属性,可以达到与使用 * ParameterMethodNameResolver 作为 MethodResolver的 MultiActionController 类似的功能。 * * params 有两种表达形式,这里先说第一种:"parameterName=parameterValue" * * 请求方法为 GET 或 POST,且具有 hello 参数,且值为 world 的请求才能匹配到该方法,如: * /my?hello=world */ @RequestMapping(params="hello=world", method={RequestMethod.GET, RequestMethod.POST}) public String helloworld() {...} /** * 请求方法为 GET 或 POST,且具有 hello 参数,且值为 java 的请求才能匹配到该方法,如: * /my?hello=java */ @RequestMapping(params="hello=java", method={RequestMethod.GET, RequestMethod.POST}) public String hellojava() {...} /** * params 属性的另外一种表达形式为:"parameter" * * 请求方法为 GET,且具有请求参数 java 即匹配此方法,而不管 java 参数的值是什么,如: * /my?java=anything */ @RequestMapping(params="java", method={RequestMethod.GET}) public String java() {...} /** * 请求方法为 GET,且具有请求参数 cplusplus 即匹配此方法,而不管 cplusplus 参数的值是什么,如: * /my?cplusplus=anything */ @RequestMapping(params="cplusplus", method={RequestMethod.GET}) public String cplusplus() {...} /** * @RequestMapping 还有一个参数化 headers,它和 params 非常相似,也有两种表达式,只不过它是对 * 请求头做限制罢了。大家可以通过 telnet 或 http-client 来发类似的请求以检验。以 telnet 为例: * * telnet localhost 8080 * POST /contextPath/my HTTP/1.1 * Host: localhost * hello: world # 这个就是自定义请求头,和标准的请求头的写法别无二致 */ @RequestMapping(headers="hello=world", method={RequestMethod.POST}) public String cplusplus() {...} }
@RequestBody : 将请求正文绑定到方法参数
@Controller @RequestMapping("/my") public class MyController { /** * 我们定义的 body 的数据类型是 String,请求体嘛,肯定是 String。实际上,@RequestBody 是用于将请 * 求体的内容绑定到方法参数上,数据类型不一定是 String。Spring MVC 是通过 HttpMessageConverter * 来完成这种转换的。AnnotationMethodHandlerAdapter 默认注册了一些 HttpMessageConverters: * ByteArrayHttpMessageConverter - converts byte arrays * StringHttpMessageConverter - converts strings * FormHttpMessageConverter - converts form data to/from MultiValueMap< String,String> * SourceHttpMessageConverter - convert to/from a javax.xml.transform.Source * MappingJacksonHttpMessageConverter - converts json * MarshallingHttpMessageConverter - convert to/from an object using the * 正如上所述,HttpMessageConverter 用于从请求正文绑定到对象和把对象序列化成 String 予客户端响应。 * 即 HttpMessageConverter is responsible for converting from the HTTP request message to * an object and converting from an object to the HTTP response body * * 我们可以在 AnnotationMethodHandlerAdapter 定义任意多的 HttpMessageConverters。 * * 既然 HttpMessageConverter 可以用于双向 convert,这里讨论的是 @RequestBody,那这部分我们只讲 * converting from the HTTP request message to an object。 * * 假设我们只向 AnnotationMethodHandlerAdapter 注入了 MappingJacksonHttpMessageConverter 和 * MarshallingHttpMessageConverter。处理请求的方法有如下签名: * public String test(@RequestBody User user) { ... } * * 不管请求正文的内容是什么,对于客户端和服务器而言,它们只是用文本来互相通信。把字符串转为 User 对 * 象,该用哪个 HttpMessageConverter 来完成此项工作呢? * * 在定义 HttpMessageConverters 时,我们可以为其指定 supportedMediaTypes。对于将请求正文转为对象 * 这个方向的操作,HttpMessageConverters 会从请求头得到 Content-Type 头信息,看其是否隶属于其定义 * 的 supportedMediaTypes。若没有匹配上,则会使用下一个 HttpMessageConverter 做同样的判断。只要 * 某个 HttpMessageConverter 支持请求头中的 Content-Type,那么就会应用此 HttpMessageConverter * 来将 String 转为 Object。当然,若请求正文并没有按照 Content-Type 所规定的格式来编写,必然要收到 * 500 的响应。同时请注意,请求头中还必须提供 Content-Length,否则拿不到请求正文。 * * 如果所有的 HttpMessageConverters 中定义的 supportedMediaTypes 均不能匹配上 Content-Type 请 * 求头中的类型,那么就会收到 415 Unsupported Media Type 响应。 */ @RequestMapping("/user/body"); public String getBody(@RequestBody String body) { // 这里的 body 的内容就是 hello System.out.println(body); return null; } }
@ResponseBody : 将返回的数据改为json格式。
@Controller @RequestMapping("/my") public class MyController { /** * 该方法的返回类型是 User,并不符合含有 @RequestMapping 的注解所需的签名方式。但它仍然是合法的,因 * 为在返回类型前有 @ResponseBody 注解,此注解将告知框架,将 User 对象作为影响正文返回?什么?对象 * 作为响应正文!所以,HttpMessageConverter 在这里就起到作用了。这里讨论的是 @ResponseBody,所以 * 这里我们只讲 converting from an object to the HTTP response body。 * * User 对象要转成什么样的 String,或者说要转成什么格式的 String?这个时候需要从请求头中获得此信息 * 了,这里,就是请求头的 Accept 头。Accept 头可以使用逗号分隔定义多个类型,用以告知服务器我只接受 * 哪些类型的响应。AnnotationMethodHandlerAdapter 中同样注入了多个 HttpMessageConverter,每个 * HttpMessageConverter 都可以定义各自的 supportedMediaTypes。这个时候该用哪个 * HttpMessageConverter 来完成对象到文本的序列化操作呢? * * 遍历 Accept 头中的每种媒体类型,在定义的多个 HttpMessageConverters 中依次去匹配,若匹配上,就使 * 用该 HttpMessageConverter 来完成序列化操作,并且响应头的 Content-Type 并不是请求头 Accept 头 * 的诸多类型中第一个被匹配的类型,而是匹配到的 HttpMessageConverter 定义的 supportedMediaTypes * 中的第一个类型。 * * 如果所有的 HttpMessageConverters 中定义的 supportedMediaTypes 均不能匹配上 Accept 请求头中 * 的诸多的类型,那么就会收到 406 Not Acceptable 响应。 */ @RequestMapping("/user") public @ResponseBody User getUser() { return new User(18, "Jack", "计算机"); } }
@RequestParam : 绑定 HttpServletRequest 请求参数到控制器方法参数。
@Controller @RequestMapping("/my") public class MyController { /** * 注意,这里的方法有一个参数。若请求 url 为 /my/test,会匹配此方法。这里的方法的参数名为 userId, * 那么请求参数中一定有名为 userId 的参数,且值为整数。这也是默认的绑定行为,它是根据名称匹配原则进行 * 的数据绑定。当请求中的参数名与方法名一致的时候,相应的参数值将被绑定到相应的方法参数上。 * * 如果没有传递 userId 参数,框架会传入 null。可是这里我们定义的是 primitive type,异常伺候!若 * 要解决此问题,需要将 primitive type 定义成相应的 wrapper type 即可,这里使用 Integer 就行了。 * * 如果传递了 userId 参数,但值不是整数,你叫 test 怎么办呢?这种情况下,框架借助 PropertyEditor * 数据类型转换失败,ExceptionResolver 会接手处理,请求是不会进入 test 方法的。 * * 这种方式下,默认的绑定行为需要我们严格遵守命名一致性原则。如果我们对此不满,想自定义绑定关系,可以求 * 助于 @RequestParam。 */ @RequestMapping("/test") public String test(int userId) { ... } /** * 当我们不想使用 userId 作为方法的参数名,即不想使用默认的数据绑定方式。如果我们要使用 id 作为方法 * 的参数,为了保证名称为 userId 的请求参数可以绑定到新的名称为 id 的方法参数上,我们就可以使用 * @RequestParam 对这一参数进行标注。@RequestParam 只可以标注于方法参数上。 * 如果请求参数中有 age,和方法的参数名称一致,故 age 参数不需要 @RequestParam 标注。如果没有传递 * age,我们又不想定义成 Integer,很显然框架会注入 null 值,报错是必然的。这是由于 @RequestParam * 的 required 属性决定的,默认就是 true。如果我们定义成 false, * 即 @RequestParam(required=false) int age * 这个时候定义成 int 型的 age,即便请求参数没有 age 参数,也是没问题的。 * 同时,这里还能绑定 Date 类型,User 对象类型等等。如 date=2011-01-01&userName=Tom&userAge=18 * 这里,User 类的属性需要为 userName 和 userAge,以免和 age,name 混淆。所以,Spring MVC 对对象 * 的数据绑定就没有 Struts2 做的那么好了,Strtus2 可以这样:user.age=18&user.name=Tom */ @RequestMapping("/test2") public String test2(@RequestParam("userId") int id, int age, Date date, User user) { ... } }
@PathVariable : 将 url template 里的参数绑定到方法参数
@Controller @RequestMapping("/my") public class MyController { /** * @PathVariable 是 url 模板,需要和 @RequestMapping 配合起来使用,这是 Spring 3.0 之后引入的。 * * 在这个例子中,请求的 url 必须满足类似 /my/user/zhangsan/18 这样的格式才能匹配方法。url 模板里 * 的参数名和方法参数名的绑定规则和 @RequestParam 类似,这里就不再赘述了。 * * @PathVariable 和 @RequestParam 的区别在于: * @PathVariable 的 url:/my//user/zhangsan/18 * @RequestParam 的 url:/my//user?nickname=zhangsan&age=18 */ @RequestMapping("/user/{nickname}/{age}"); public String getUserInfo(@PathVariable("nickname") String name, @PathVariable int age) {...} }
ModelAttribute :
/** * @ModelAttribute 可以为视图渲染提供更多的模型数据,而不需要在处理请求的方法里添加 ModelMap 或 * Model 类型的参数。 * * @ModelAttribute 可以标注在方法(存数据)上,也可以标注在方法参数(取数据)上。 */ @Controller @RequestMapping("/my") public class MyController { /** * 在处理该请求时,方法的返回类型是 User,貌似不符合返回类型的规范。由于这里使用了 @ModelAttribute * 注解,表示将返回的对象以 "user" 为 key 放入模型数据里。这里的 key 值默认值是返回的数据类型首字母 * 小写的结果。如果想自定义 key,可以写成 @ModelAttribute("myAttribute"),那么模型数据将会将 * User 对象绑定到 key 为 "myAttribute" 上。 * * jsp 里可以这样访问模型里的数据: * age: ${user.age} * name: ${user.name} * job: ${user.job} * * 当然,这里只是提到了 @ModelAttribute 存数据的操作。 */ @RequestMapping("/user") @ModelAttribute public User getUser() { return new User(18, "Jack", "计算机"); } /** * 这里将 @ModelAttribute 标注在方法参数上,表示要从模型数据里取 key 为 "user" 的对象,绑定在方法 * 参数上。如果这样做的话,其实你是得不到上面的那个请求放入的 User 对象,得到的是另外一个对象。其实 * 也好理解,这是两个互相独立的请求,作用域不一样。要想达到我们的目的,即能够从模型数据里取数据,需要 * 求助于 @SessionAttributes */ @RequestMapping("/user2") public String showUser(@ModelAttribute User user) { System.out.println(user); return null; } }
@SessionAttributes
/** * @SessionAttributes 和 @ModelAttribute 类似,只不过 @SessionAttributes 是将数据存放于 session * 中或从 session 中取数据。 * * @SessionAttributes 只能应用在类型声明上。比如下面的类的声明中,只有属性名为 "the-attribute" 的数 * 据才会纳入到 session 的管理。 * * @SessionAttributes 允许以属性名名称或者类型两种方法,来表明将哪些数据通过 session 进行管理。这里 * 我们使用的是指定属性名称的方式,但通过类型来指定也是可行的,如: * @SessionAttributes(types=User.class) */ @Controller @RequestMapping("/my") @SessionAttributes("the-attribute") public class MyController { @RequestMapping("/getUser") public String getUser(int userId, Model model) { /** * 注意,这里将 User 对象添加到属性名为 "the-attribute" 上,所以 User 对象将纳入到 session 的 * 管理。如果这里添加的对象的属性名不是 "the-attribute",那么它只会作用于当前请求,而不会纳入到 * session 的管理中。 */ User user = userService.getUserById(userId); model.addAtrribute("the-attribute", user); return "userinfo"; } /** * 将模型里的 "the-attribute" 为 key 的对象绑定到 User 类上。由于在类级别上声明了只有 "the- * attribute" 的属性名才会纳入到 session 的管理,所以就解决了在 @ModelAttribute 注解中讲解中最 * 后提到的问题。 * * 另外,这个方法还有两个参数,BindingResult 和 SessionStatus。由于这里有绑定数据的动作,我们可以 * 根据 BindingResult 对象获得数据绑定结果以决定后继流程该如何处理。SessionStatus 在这里用于处理 * 完请求后,清空 session 里的数据。 */ @RequestMapping("/updateUser") public String updateUser(@ModelAttribute("the-attribute") User user, BindingResult result, SessionStatus status) { if (result.hasErrors) { return "error"; } userService.updateUser(user); // 我们通过调用 status.setComplete() 方法,该 Controller 所有放在 session 级别的模型属性数据 // 将从 session 中清空 status.setComplete(); return "redirect:getUser?userId=" + user.getId(); } }
@CookieValue : 绑定 cookie 的值到 Controller 方法参数。
@RequestHeader :注解绑定 HttpServletRequest 头信息到 Controller 方法参数。
使用示例
自动匹配参数
@RequestMapping("/person") public String toPerson(String name,double age){ System.out.println(name+" "+age); return "hello"; }
使用InitBinder来处理Date类型的参数
@RequestMapping("/date") public String date(Date date){ System.out.println(date); return "hello"; } //At the time of initialization,convert the type "String" to type "date" @InitBinder public void initBinder(ServletRequestDataBinder binder){ binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); }
自动装箱
package test.SpringMVC.model; public class Person { public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } private String name; private int age; }
@RequestMapping("/person1") public String toPerson(Person p){ System.out.println(p.getName()+" "+p.getAge()); return "hello"; }
向前台传递参数
@RequestMapping("/show") public String showPerson(Map<String,Object> map){ Person p =new Person(); map.put("p", p); p.setAge(20); p.setName("jayjay"); return "show"; }
在Controller中使用redirect方式处理请求
@RequestMapping("/redirect") public String redirect(){ return "redirect:hello"; }
文件上传
@RequestMapping(value="/upload",method=RequestMethod.POST) public String upload(HttpServletRequest req) throws Exception{ MultipartHttpServletRequest mreq = (MultipartHttpServletRequest)req; MultipartFile file = mreq.getFile("file"); String fileName = file.getOriginalFilename(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); FileOutputStream fos = new FileOutputStream(req.getSession().getServletContext().getRealPath("/")+ "upload/"+sdf.format(new Date())+fileName.substring(fileName.lastIndexOf('.'))); fos.write(file.getBytes()); fos.flush(); fos.close(); return "hello"; }
使用@RequestParam注解指定参数的name
@Controller @RequestMapping("/test") public class mvcController1 { @RequestMapping(value="/param") public String testRequestParam(@RequestParam(value="id") Integer id, @RequestParam(value="name")String name){ System.out.println(id+" "+name); return "/hello"; } }
RESTFul风格的SringMVC
@Controller @RequestMapping("/rest") public class RestController { @RequestMapping(value="/user/{id}",method=RequestMethod.GET) public String get(@PathVariable("id") Integer id){ System.out.println("get"+id); return "/hello"; } @RequestMapping(value="/user/{id}",method=RequestMethod.POST) public String post(@PathVariable("id") Integer id){ System.out.println("post"+id); return "/hello"; } @RequestMapping(value="/user/{id}",method=RequestMethod.PUT) public String put(@PathVariable("id") Integer id){ System.out.println("put"+id); return "/hello"; } @RequestMapping(value="/user/{id}",method=RequestMethod.DELETE) public String delete(@PathVariable("id") Integer id){ System.out.println("delete"+id); return "/hello"; } }
返回json格式的字符串
@Controller @RequestMapping("/json") public class jsonController { @ResponseBody @RequestMapping("/user") public User get(){ User u = new User(); u.setId(1); u.setName("jayjay"); u.setBirth(new Date()); return u; } }
异常的处理
处理局部异常(Controller内)
@ExceptionHandler public ModelAndView exceptionHandler(Exception ex){ ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex); System.out.println("in testExceptionHandler"); return mv; } @RequestMapping("/error") public String error(){ int i = 5/0; return "hello"; }
处理全局异常(所有Controller)
@ControllerAdvice public class testControllerAdvice { @ExceptionHandler public ModelAndView exceptionHandler(Exception ex){ ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex); System.out.println("in testControllerAdvice"); return mv; } }
在SpringMVC配置文件中配置全局异常
<!-- configure SimpleMappingExceptionResolver --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.lang.ArithmeticException">error</prop> </props> </property> </bean>
整体示例
实体类
package com.heqing.ssm.entity; public class Test { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "test = {id:"+id+",name:"+name+"}"; } }
控制层
package com.heqing.ssm.controller; @Controller @RequestMapping("/springMVC") public class TestController { @ModelAttribute public void modelAttribute() { System.out.println("===Controller.before==="); } @ExceptionHandler public void exceptionHandler(Exception e) { System.out.println("===Controller.@ExceptionHandler==="+e.getMessage()); } @InitBinder public void initBinder(ServletRequestDataBinder binder){ binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); } @RequestMapping("/index") public String index(Map<String,Object> map) { System.out.println("===Controller.springMVC==="); map.put("message", "Hello World!"); return "springMVC.html"; } @RequestMapping("/view") public ModelAndView view(HttpServletRequest req, HttpServletResponse resp) throws Exception { //1、收集参数、验证参数 //2、绑定参数到命令对象 //3、将命令对象传入业务对象进行业务处理 //4、选择下一个页面 ModelAndView mv = new ModelAndView(); //添加模型数据 可以是任意的POJO对象 mv.addObject("message", "Hello World!"); //设置逻辑视图名,视图解析器会根据该名字解析到具体的视图页面 mv.setViewName("springMVC"); return mv; } @RequestMapping("/jsonUtil") public void jsonUtil(HttpServletResponse response,HttpServletRequest request, int id, String name) { Test test = new Test(); test.setId(id); test.setName(name); List<String> list = new ArrayList<>(); list.add("test1"); list.add("test2"); Map<String,Object> paramsMap=new LinkedHashMap<String,Object>(); paramsMap.put("id", 1); paramsMap.put("message", "Hello World!"); paramsMap.put("test", test); paramsMap.put("list", list); JsonUtil.outPutJsonMessage(log, "test", response, paramsMap); } @RequestMapping(value = "/requestBody", method = {RequestMethod.POST }) @ResponseBody public void requestBody(@RequestBody List<Test> tests) { System.out.println("===Controller.requestBody==="); System.out.println("size="+tests.size()+" name1="+tests.get(0).getName()); } @RequestMapping("/responseBody") @ResponseBody public Map<String, Object> responseBody() throws IOException { System.out.println("===Controller.responseBody==="); Map<String,Object> paramsMap = new LinkedHashMap<String,Object>(); paramsMap.put("id", 1); paramsMap.put("name", "name1"); return paramsMap; } /** * value: 路径地址 * method:请求方法的规则,比如:如果设置了RequestMethod.POST,那么你的表单提交就必须使用POST提交,否则将报405错误 * params: 提交中的数据中一定要有配置的参数(如id),否则将报400的错误 * */ @RequestMapping(value = "/requestParam", method = {RequestMethod.POST }, params="id") @ResponseBody public void requestParam(@RequestParam int id, @RequestParam String name) { System.out.println("===Controller.requestParam==="); System.out.println("id="+id+", name="+name); } @RequestMapping("/requestParamAuto") @ResponseBody public void toPerson(String id, String name){ System.out.println("===Controller.requestParamAuto==="); System.out.println("id="+id+", name="+name); } @RequestMapping("/requestBeanAuto") @ResponseBody public void requestBeanAuto(Test test){ System.out.println("===Controller.requestBeanAuto==="); System.out.println("id="+test.getId()+", name="+test.getName()); } @RequestMapping("/pathVariable/{id}") @ResponseBody public void pathVariable(@PathVariable("id") String id) { System.out.println("===Controller.pathVariable==="); System.out.println("id="+id); } @RequestMapping("/initBinder") @ResponseBody public void initBinder(Date date) { System.out.println("===Controller.initBinder==="); System.out.println("date="+date); } @RequestMapping("/upload") @ResponseBody public void upload(HttpServletRequest request) throws IllegalStateException, IOException { System.out.println("===upload==="); //创建一个通用的多部分解析器 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); //判断 request 是否有文件上传,即多部分请求 if(multipartResolver.isMultipart(request)){ //转换成多部分request MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request; //取得request中的所有文件名 Iterator<String> iter = multiRequest.getFileNames(); while(iter.hasNext()){ //记录上传过程起始时的时间,用来计算上传时间 int pre = (int) System.currentTimeMillis(); //取得上传文件 MultipartFile file = multiRequest.getFile(iter.next()); if(file != null){ //取得当前上传文件的文件名称 String myFileName = file.getOriginalFilename(); //如果名称不为“”,说明该文件存在,否则说明该文件不存在 if(myFileName.trim() !=""){ //重命名上传后的文件名 String fileName = file.getOriginalFilename(); //定义上传路径 String path = "D:/test/" + fileName; File localFile = new File(path); file.transferTo(localFile); } } //记录上传该文件后的时间 int finaltime = (int) System.currentTimeMillis(); System.out.println("上传用时:"+(finaltime - pre)+"秒"); } } } }
显示层
< !DOCTYPE html> < html> < head> < base href="<%=basePath%>"> < title>springMVC< /title> < meta http-equiv="pragma" content="no-cache"> < meta http-equiv="cache-control" content="no-cache"> < meta http-equiv="expires" content="0"> < meta http-equiv="keywords" content="springMVC"> < meta http-equiv="description" content="This is my test page"> < script src="../js/jquery-3.1.1.min.js"></script> < script src="../js/ajaxfileupload.js"></script> < /head> < body> 后台传递过来的消息:${message} <br/> < spring:message code="start"/><br/> < button id="RequestBody" type="button">测试 @RequestBody< /button> < button id="ResponseBody" type="button">测试 @ResponseBody< /button> < button id="RequestParam" type="button">测试 @RequestParam< /button> < button id="RequestParamAuto" type="button">测试 自动匹配参数< /button> < button id="RequestBeanAuto" type="button">测试 自动装箱< /button> < button id="PathVariable" type="button">测试 @PathVariable< /button> < button id="InitBinder" type="button">测试 @InitBinder< /button> < button id="JsonUtil" type="button">测试 JsonUtil< /button> < input type="file" id="uFile" name="uFile" multiple="multiple"/> < button id="uploadAll" type="button">上传文件< /button> < /body> < script> $("#RequestBody").click(function(){ var testAry=[]; var test1={"id":1,"name":"name1"}; var test2={"id":2,"name":"name2"}; testAry.push(test1); testAry.push(test2); $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/requestBody", data:JSON.stringify(testAry), dataType: "json", contentType: "application/json;", success: function(data){ console.info(data); } }); }); $("#JsonUtil").click(function(){ $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/jsonUtil", data: { "id" : 1, "name" : "name" }, success: function(data){ console.info(data); } }); }); $("#ResponseBody").click(function(){ $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/responseBody", success: function(data){ console.info(data); } }); }); $("#RequestParam").click(function(){ $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/requestParam", data: { "id" : 3, "name" : "name3" }, success: function(data){ console.info(data); } }); }); $("#RequestParamAuto").click(function(){ $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/requestParamAuto", data: { "id" : 3, "name" : "name3" }, success: function(data){ console.info(data); } }); }); $("#RequestBeanAuto").click(function(){ $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/requestBeanAuto", data: { "id" : 3, "name" : "name3" }, success: function(data){ console.info(data); } }); }); $("#PathVariable").click(function(){ $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/pathVariable/4", success: function(data){ console.info(data); } }); }); $("#InitBinder").click(function(){ $.ajax({ type: "POST", url: "/Demo_SSM/springMVC/initBinder", data: { "date" : "2017-01-16" }, success: function(data){ console.info(data); } }); }); $("#uploadAll").click(function(){ $.ajaxFileUpload({ url:"/Demo_SSM/springMVC/upload", fileElementId:"uFile", success: function (data, status){ alert("上传成功"); }, }); }); </script> </html>