SpringMVC—学习笔记#day02

目录

第一章:响应数据和结果视图

1.1返回值分类

1.1.1 字符串

1.1.2 void

1.1.3 ModelAndView对象

1.2 SpringMVC框架提供的转发和重定向

1.2.1 forward请求转发

1.2.2 redirect重定向

1.3 ResponseBody响应json数据

1. DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置

2. 使用@RequestBody获取请求体数据

3. 使用@RequestBody注解把json的字符串转换成JavaBean的对象

4. 使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应

5. json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包

第二章:SpringMVC实现文件上传

前提条件

上传原理

2.1 文件上传的回顾(弃用)

1. 导入文件上传的jar包

2. 编写文件上传的JSP页面

3. 编写文件上传的Controller控制器

2.2 SpringMVC传统方式文件上传

0.原理

1. 导入文件上传的jar包

2. 编写文件上传的JSP页面

3. 编写文件上传的Controller控制器

4.spingmvc.xml

2.3springmvc跨服务器方式的文件上传

1. 搭建图片服务器

2.导入开发需要的jar包

3. 编写文件上传的JSP页面

4.编写控制器

编写处理文件的工具类

第三章 SpringMVC 中的异常处理

3.1 异常处理的思路

3.2  实现步骤

3.2.1编写异常类和错误页面

3.2.2 自定义异常处理器

3.2.3  配置异常处理器

3.2.3测试结果

3.3流程

第4章 SpringMVC 中的拦截器

4.1  拦截器的作用

4.2 自定义拦截器的步骤

4.2.1 第一步:编写一个普通类实现 HandlerInterceptor 

4.2.2 第二步:配置拦截器

4.2.3 测试运行结果:

4.3  拦截器的细节

4.3.1 拦截器的放行

4.3.2  拦截器中方法的说明

4.4  拦截器的简单案例(验证用户是否登录)

4.4.1  实现思路

4.4.2 拦截器代码


第一章:响应数据和结果视图

1.1返回值分类

1.1.1 字符串

Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。


    
    
@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/testString")
    public String testString(Model model) {
		// 执行方法体...向隐式对象添加属性attribute_user,可以在jsp中通过 ${attribute_user} 获取到
		model.addAttribute("attribute_user", new User("张三", "123"));
        
        // 经过视图解析器的处理,SpringMVC会将请求转发到/WEB-INF/pages/succeess.jsp,但浏览器地址栏显示的一直是 项目域名/user/testString
        return "success";
    }
}

1.1.2 void

1. 如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。

 默认会跳转到@RequestMapping(value="/initUpdate") initUpdate的页面。

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/testVoid")
    public void testVoid(Model model) {
		// 执行方法体...向隐式对象添加属性attribute_user,可以在jsp中通过 ${attribute_user} 获取到
		model.addAttribute("attribute_user", new User("张三", "123"));
        
        // 处理器没有返回值,则会将请求转发到当前 项目域名/user/testVoid 路径
        // 若在web.xml中没有配置 项目域名/user/testVoid 对应的url-pattern,则会返回404错误
        return;
    }
}

2. 可以使用请求转发或者重定向跳转到指定的页面

@Controller
@RequestMapping("/user")
public class UserController {

	@RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 执行方法体...向隐式对象添加属性attribute_user,可以在jsp中通过 ${attribute_user} 获取到
		model.addAttribute("attribute_user", new User("张三", "123"));
        
        // 通过下面三个方法之一,可以指定访问的视图
        // 指定视图的方式1: 请求转发
        request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);

        // 指定视图的方式2: 重定向
        response.sendRedirect(request.getContextPath() + "/index.jsp");

        // 指定视图的方式3: 通过Writer对象写入内容
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().print("你好");

        return;
    }
}

1.1.3 ModelAndView对象

ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图

ModelAndView为我们提供了一种更灵活地为页面添加属性和指定返回视图的方法,其主要方法如下:

  1. public ModelMap getModelMap(): 返回当前页面的ModelMap对象.
  2. public ModelAndView addObject(Object attributeValue): 向当前页面的ModelMap对象中添加属性
  3. public void setViewName(@Nullable String viewName): 指定返回视图,viewName会先被视图解析器处理解析成对应视图.
@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView() {
        
        // 创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        
        // 向model中存入属性attribute_user
	mv.addObject("attribute_user", new User("张三", "123"));

        // 指定返回视图,视图解析器将"success"解析为视图URL /WEB-INF/pages/succeess.jsp
        mv.setViewName("success");

        return mv;
    }
}

1.2 SpringMVC框架提供的转发和重定向

1.2.1 forward请求转发

此时forward:后的地址不能直接被视图解析器解析,因此要写完整的相对路径

@Controller
@RequestMapping("/user")
public class UserController {
	@RequestMapping("/testForward")
    public String testForward() {
        // 在forward:要写完整的相对路径
        // return "forward:success"	// 错误,会将请求转发到 /项目名/user/success
        return "forward:/WEB-INF/pages/success.jsp";
    }
}

1.2.2 redirect重定向

此时redirect:后的地址要写相对于ContextPath的地址

@Controller
@RequestMapping("/user")
public class UserController {
	@RequestMapping("/testRedirct")
    public String testRedirct() {
        // 在forward:要写完整的相对路径
        // return "redirect:" + request.getContextPath() + "/index.jsp";	// 错误,会将请求转发到 /项目名/项目名/index.jsp
		return "redirect:/index.jsp";
    }
}

1.3 ResponseBody响应json数据

1. DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置

1. mvc:resources标签配置不过滤

1. location元素表示webapp目录下的包下的所有文件

2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b





2. 使用@RequestBody获取请求体数据

3. 使用@RequestBody注解把json的字符串转换成JavaBean的对象

使用@ResponseBody注解表示将该方法的返回值直接写回到HTTP响应中,而不是存入Model或解析为视图名

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testAjax")
    @ResponseBody
    public User testAjax(@RequestBody User user) {

        System.out.println(user);
        
        // 将user对象返回给前端页面
        return user;
    }
}

4. 使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应

要求方法需要返回JavaBean的对象

@RequestMapping("/testAjax")  
//@ResponseBody 注在返回值类型Address前,自动将Address类型转换为json格式数据响应给客户端
public @ResponseBody User testAjax(@RequestBody User user) {
	//客户端发送ajax请求,传入的是json字符串(请求体内)由SpringMVC框架自动转换封装到JavaBean中        
	System.out.println(user);        
	user.setUserName("111");        
	return user;    
}

5. json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包


    com.fasterxml.jackson.core
    jackson-databind
    2.9.0


    com.fasterxml.jackson.core
    jackson-core
    2.9.0


    com.fasterxml.jackson.core
    jackson-annotations
    2.9.0

第二章:SpringMVC实现文件上传

前提条件

    A form 表单的 enctype(表单请求正文的类型) 取值必须是:multipart/form-data      
                                    (默认值是:application/x-www-form-urlencoded)
    B method 属性取值必须是 Post (get方法是将请求体写在URL里的。有大小限制) 
    C 提供一个文件选择域 

上传原理

不论是传输字符串,还是传输文件,都是通过form表单,其实文件只是长度很长的字符串罢了。

当 form 表单的 enctype=”application/x-www-form-urlencoded”时,
form 表单的正文内容是键值对+&:    key=value&key=value&key=value 

当 form 表单的 enctype 取值为 Mutilpart/form-data 不是默认值时,request.getParameter()将失效。 
请求正文内容就变成: 每一部分都是 MIME 类型描述的正文 
-----------------------------7de1a433602ac   分界符 
Content-Disposition: form-data; name="userName"  协议头
aaa              协议的正文(文件内容)
-----------------------------7de1a433602ac 

那么我们的工作就是,解析Post请求方法的请求体,将文件内容、文件名拆分出来,然后在服务器指定路径下建立同名文件

2.1 文件上传的回顾(弃用)

1. 导入文件上传的jar包


    commons-fileupload
    commons-fileupload
    1.3.1


    commons-io
    commons-io
    2.4

2. 编写文件上传的JSP页面

选择文件:

3. 编写文件上传的Controller控制器

/**
 * 文件上传(弃用)
 *
 * @return
 */
@RequestMapping("/fileupload1")
public String fileuoload1(HttpServletRequest request) throws Exception {
    System.out.println("文件上传...");

    // 使用fileupload组件完成文件上传
    // 上传的位置
    //String path = request.getSession().getServletContext().getRealPath("/uploads/");
    String path = request.getSession().getServletContext().getContextPath() + "/uploads/";///springmvc_day02_02_fileupload_war/uploads/
    //System.out.println(request.getSession());//org.apache.catalina.session.StandardSessionFacade@4c2048cc
    //System.out.println(request.getSession().getServletContext().getContextPath() + "/uploads/");///springmvc_day02_02_fileupload_war
    // 判断,该路径是否存在
    File file = new File(path);
    if (!file.exists()) {
        // 创建该文件夹
        file.mkdirs();
    }

    // 解析request对象,获取上传文件项
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    // 解析request
    List items = upload.parseRequest(request);
    System.out.println(items);
    // 遍历
    for (FileItem item : items) {
        System.out.println(item);
        // 进行判断,当前item对象是否是上传文件项
        if (item.isFormField()) {
            // 说明普通表单项
            System.out.println("普通表单向");
        } else {
            // 说明上传文件项
            // 获取上传文件的名称
            String filename = item.getName();
            System.out.println(filename);
            // 把文件的名称设置唯一值,uuid
            String uuid = UUID.randomUUID().toString().replace("-", "");
            filename = uuid + "_" + filename;
            // 完成文件上传
            item.write(new File(path, filename));
            // 删除临时文件
            item.delete();
        }
    }

    return "success";
}

2.2 SpringMVC传统方式文件上传

0.原理

SpringMVC—学习笔记#day02_第1张图片

SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件
注意:形参变量名称必须和前端表单的 name属性名称相同。
与上面的第三方工具比较的优势:
1.不需要引入jar包,减少依赖
2.不需要再解析request,springMVC封装好了,在前端控制器中调用文件解析器对象来帮助解析。
3.代码简洁,干净。

1. 导入文件上传的jar包


    commons-fileupload
    commons-fileupload
    1.3.1


    commons-io
    commons-io
    2.4

2. 编写文件上传的JSP页面

选择文件:

3. 编写文件上传的Controller控制器

/**
 * SpringMVC文件上传
 *
 * @return
 */
@RequestMapping("/fileupload2")
public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception {
    System.out.println("springmvc文件上传...");

    // 使用fileupload组件完成文件上传
    // 上传的位置
    String path = request.getSession().getServletContext().getRealPath("/uploads/");

    // 判断,该路径是否存在
    File file = new File(path);
    if (!file.exists()) {
        // 创建该文件夹
        file.mkdirs();
        System.out.println(1);
    }
    System.out.println(path);
    // 说明上传文件项
    // 获取上传文件的名称
    String filename = upload.getOriginalFilename();
    System.out.println(filename);
    // 把文件的名称设置唯一值,uuid
    String uuid = UUID.randomUUID().toString().replace("-", "");
    filename = uuid + "_" + filename;
    // 完成文件上传
    upload.transferTo(new File(path, filename));

    return "success";
}

4.spingmvc.xml

    
        
	    

2.3springmvc跨服务器方式的文件上传

1. 搭建图片服务器

SpringMVC—学习笔记#day02_第2张图片

SpringMVC—学习笔记#day02_第3张图片

2.导入开发需要的jar包


    com.sun.jersey
    jersey-core
    1.18.1


    com.sun.jersey
    jersey-client
    1.18.1

3. 编写文件上传的JSP页面

跨服务器的文件上传

选择文件:

4.编写控制器

/**
 * 跨服务器文件上传
 *
 * @return
 */
@RequestMapping("/fileupload3")
public String fileuoload3(MultipartFile upload) throws Exception {
    System.out.println("跨服务器文件上传...");

    // 定义上传文件服务器路径
    String path = "http://localhost:9090/uploads/";

    // 说明上传文件项
    // 获取上传文件的名称
    String filename = upload.getOriginalFilename();
    System.out.println(filename);
    // 把文件的名称设置唯一值,uuid
    String uuid = UUID.randomUUID().toString().replace("-", "");
    filename = uuid + "_" + filename;

    // 创建客户端的对象
    Client client = Client.create();

    // 和图片服务器进行连接
    WebResource webResource = client.resource(path + filename);

    // 上传文件
    webResource.post(upload.getBytes());

    return "success";
}

编写处理文件的工具类

我们将上述程序中对文件的处理封装成抽象类FileUtil:

public class FileUtil {

    // 上传文件
    public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {
        File targetFile = new File(filePath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        FileOutputStream out = new FileOutputStream(filePath + fileName);
        out.write(file);
        out.flush();
        out.close();
    }

    // 删除文件,返回值表示是否删除成功
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    // 重命名文件
    public static String renameToUUID(String fileName) {
        return UUID.randomUUID() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
    }
}

保存文件的操作可简化为如下三句:

String fileName = FileUtil.renameToUUID(uploadFile.getOriginalFilename());
String filePath = request.getSession().getServletContext().getRealPath("/uploads/");
FileUtil.uploadFile(uploadFile.getBytes(), filePath, fileName);

第三章 SpringMVC 中的异常处理

3.1 异常处理的思路

系统中异常包括两类:预期异常运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息, 后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。 系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端 控制器交由异常处理器进行异常处理

SpringMVC—学习笔记#day02_第4张图片

3.2  实现步骤

3.2.1编写异常类和错误页面

/**
 * 自定义异常类
 */
public class SysException extends Exception{

    // 存储提示信息的
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public SysException(String message) {
        this.message = message;
    }

}

jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>


    执行失败



    ${errorMsg}


3.2.2 自定义异常处理器

/**
 * 异常处理器
 */
public class SysExceptionResolver implements HandlerExceptionResolver {

    /**
     * 处理异常业务逻辑
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 获取到异常对象
        SysException e = null;
        //如果抛出的是系统自定义异常则直接转换
        if (ex instanceof SysException) {
            e = (SysException) ex;
        } else {
            //如果抛出的不是系统自定义异常则重新构造一个系统错误异常
            e = new SysException("系统正在维护....");
        }
        // 创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg", e.getMessage());
        mv.setViewName("error");
        return mv;
    }
}

3.2.3  配置异常处理器

3.2.3测试结果

SpringMVC—学习笔记#day02_第5张图片

SpringMVC—学习笔记#day02_第6张图片

SpringMVC—学习笔记#day02_第7张图片

3.3流程

原理:所有的异常都会经过前端控制器,所以前端控制器可以自定义拦截(处理)识别的异常e,响应自己写的异常e处理结果(友好界面),这样就不会给用户看到tomcat的报错结果了SpringMVC—学习笔记#day02_第8张图片

SpringMVC—学习笔记#day02_第9张图片

SpringMVC—学习笔记#day02_第10张图片

第4章 SpringMVC 中的拦截器

4.1  拦截器的作用

Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
用户可以自己定义一些拦截器来实现特定的功能。
谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但
是也有区别,接下来我们就来说说他们的区别:
过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。

它也是 AOP 思想的具体应用。
我们要想自定义拦截器, 要求必须实现:HandlerInterceptor  接口。

4.2 自定义拦截器的步骤

SpringMVC—学习笔记#day02_第11张图片

4.2.1 第一步:编写一个普通类实现 HandlerInterceptor 

实现了两个类(两个拦截器)

/**
 * 自定义拦截器
 */
public class MyInterceptor1 implements HandlerInterceptor {

    /**
     * 预处理,controller方法执行前
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false不放行
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),
     * 不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle执行了...前1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }

    /**
     * 后处理方法,controller方法执行后,success.jsp执行之前
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)
     * 对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle执行了...后1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }

    /**
     * success.jsp页面执行后,该方法会执行
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,
     * 还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了...最后1111");
    }
}
/**
 * 自定义拦截器
 */
public class MyInterceptor2 implements HandlerInterceptor{

    /**
     * 预处理,controller方法执行前
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false不放行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle2执行了...前2222");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }

    /**
     * 后处理方法,controller方法执行后,success.jsp执行之前
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2执行了...后2222");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }

    /**
     * success.jsp页面执行后,该方法会执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion2执行了...最后2222");
    }

}

4.2.2 第二步:配置拦截器



    
    
        
        
        
        
        
    

    
    
        
        
        
        
        
    

4.2.3 测试运行结果:

SpringMVC—学习笔记#day02_第12张图片

SpringMVC—学习笔记#day02_第13张图片

SpringMVC—学习笔记#day02_第14张图片

4.3  拦截器的细节

4.3.1 拦截器的放行

放行的含义是指,如果有下一个拦截器就执行下一个,如果该拦截器处于拦截器链的最后一个,则执行控制器中的方法。

4.3.2  拦截器中方法的说明

看4.2.1 第一步:编写一个普通类实现 HandlerInterceptor 的代码

4.3.3 拦截器的作用路径

看4.2.2 第二步:配置拦截器的代码

4.4  拦截器的简单案例(验证用户是否登录)

4.4.1  实现思路

1、有一个登录页面,需要写一个 controller 访问页面
2、登录页面有一提交表单的动作。需要在 controller 中处理。
 2.1、判断用户名密码是否正确
 2.2、如果正确 向 session 中写入用户信息
 2.3、返回登录成功。
3、拦截用户请求,判断用户是否登录
 3.1、如果用户已经登录。放行
 3.2、如果用户未登录,跳转到登录页面

4.4.2 拦截器代码

public class LoginInterceptor implements HandlerInterceptor{
    @Override
    Public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
    //如果是登录页面则放行
        if(request.getRequestURI().indexOf("login.action")>=0){
            return true;
        }
        HttpSession session = request.getSession();
    //如果用户已登录也放行
        if(session.getAttribute("user")!=null){
            return true;
        }
    //用户没有登录跳转到登录页面
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,
                response);
        return false;
    }
}

你可能感兴趣的:(SpringMVC)