springMVC学习

概念

  1. 三层架构与MVC模型
    1. 三层:表现层、业务层、持久层
    2. MVC:model view controller

小案例

  1. 创建web项目的步骤:

    1. new -> maven -> √create from archetype -> 选archetype-webapp -> next -> 输入项目名 -> √俩Override ,选择D:\maven\apache-maven-3.6.1\conf\setting.xml ,下面一个选对应的repository -> properties里面+ archetypeCatalog internal -> next -> 选择文件保存路径 -> finish
    2. main里面新建两个文件夹 java和resourcesjava右键Mark Directory asSources Rootresources右键Mark Directory asResources Root
    3. pom.xml里面导入jar包
    4. web.xml里面写servlet的配置
    5. resources里面新建一个spring config xml,此项目中名称为springmvc.xml,作用同bean.xml
    6. 配置tomcat环境
      • EditConfiguration -> 在Template下面选择tomcat local 选择+
      • Deployment里面+,选择当前项目,Apply ,OK

        idea里面创建新的module时,取消父项目,则几个module就可以单独运行 jar包jstl,用来写EL表达式

  2. 项目案例的步骤:

    1. web.xml中配置:xml <servlet> <servlet-name>dispatcherServlet</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> <!-- 使用servlet加载配置文件 --> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> <!-- 拦截,发任何请求都会经过此servlet --> </servlet-mapping>

      • DispatcherServlet为前端控制器,拦截匹配的请求
    2. java文件夹下创建类,如com.mvc.controller.HelloController.java。```java @Controller public class HelloController {

      @RequestMapping(path=”/hello”) public String sayHello(){ System.out.println(“Hello World”); return “success”; } } ```

      • @Controller配置此为Bean对象
      • @RequestMapping配置请求的路径,该函数返回指定页面。其属性:
        1. pathvalue作用一样,用于指定请求的URL。若@RequestMapping放在类名前面,则该类下面的方法再使用@RequestMapping时,方法的路径前面会加上类前面指定的路径
          • 某页面里面超链接<a>href路径与此路径一致
          • 如果前端页面.jsp向后端方法传参,则在href路径后加?paraName1=value1& paraName2=value2,在对应的@RequestMapping配置的方法形参里面加上就可
        2. method,用于指定请求的方式,如GET POST
        3. params,用于指定限制请求参数的条件
    3. resources文件夹下创建beanspringmvc.xml

      1. <!-- 启用注解扫描器: 扫描被@Controller注解的类 -->
      2. <context:component-scan base-package="com.graduate.admin.controller, com.graduate.system.controller"/>
      3. <!-- 加载注解驱动 -->
      4. <mvc:annotation-driven/>
      5. <!-- 处理静态资源 -->
      6. <mvc:default-servlet-handler/>
      7. <!-- 过滤静态资源-->
      8. <mvc:resources location="/static/layui/" mapping="/static/layui/**"/>
      9. <mvc:resources location="/static/layui/css/" mapping="/static/layui/css/**"/>
      10. <mvc:resources location="/static/layui/lay/modules/" mapping="/static/layui/lay/modules/**"/>
      11. <!-- 配置文件上传解析器 -->
      12. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      13. <!-- 指定请求编码格式 -->
      14. <property name="defaultEncoding" value="UTF-8"/>
      15. <!-- 指定指定允许上传文件的最大值(20MB) -->
      16. <property name="maxUploadSize" value="20971520"/>
      17. </bean>
      18. <!-- 配置视图解析器 -->
      19. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      20. <property name="prefix" value="/WEB-INF/pages/"/>
      21. <property name="suffix" value=".jsp"/>
      22. </bean>
    4. WEB-INF文件夹下创建pages文件夹,并在此夹下建新的页面文件

tips

post中文乱码

web.xml里面配置过滤器:

  1. <filter>
  2. <filter-name>characterEncodingFilter</filter-name>
  3. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  4. <init-param> <!-- 初始化参数-->
  5. <param-name>encoding</param-name>
  6. <param-value>UTF-8</param-value>
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>characterEncodingFilter</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. </filter-mapping>

为封装数据传参

  1. 普通传参
  2. 封装数据传参,为实体对象传参,使用form,且里面的name属性必须与实体的对应参数名一样。在接收方法的形式参数直接用Account account接收参数
  3. 有引用类型的封装,就是在一个实体里面有引用其他实体,为这个实体封装数据时。比如Account里面引用了User对象,在form的各个user对应的nameuser.name等,其余不变
  4. 有集合类型的封装

获取原生的ServletAPI对象

  1. 只需要在控制器的方法参数定义HttpServletRequestHttpServletResponse对象

常用注解

  1. @RequestParam,当url中传入的参数名与方法形式参数的名字不一样时,在形参前加这个注释
  2. @RequestBody,用于获取请求体内容,直接使用得到 key=value&key=value...结构的数据。
    1. get请求不适用,即超链接方式
    2. 使用post方式,如用表单。接收方法的形参:@RequestBody String body
  3. @PathVariable,用于绑定url中的占位符。例如,请求url中/delete/{id}
    1. 属性:value 用于指定url中占位符名称;required 是否需要占位符
    2. Restful编写风格
  4. @ModelAttribute,用于修饰方法和参数
  5. @SessionAttributes,用于多次执行控制器方法间的参数共享
    1. 属性:value 指定存入的属性名称
    2. 该注解放在类的前面,@SessionAttributes(value = {"msg"})表示把msg存到session中
    3. 存储共享参数:用Model model做某一方法的形参,用model.addAttribute("msg","中半");存储
    4. 使用:用ModelMap modelMap做另一方法的形参,用String msg = (String)modelMap.get("msg");取出
    5. 删除:用SessionStatus status做一方法形参,用status.setComplete();清除

响应数据和结果视图

1. 返回值分类

  1. 返回字符串

    • 从后端返回字符串数据到页面显示,使用注解@SessionAttributes,在显示数据的页面头部加上isELIgnored="false",使用${msg}${user.name}方式使用
    • 控制器里的方法返回字符串类型,如return "success";,则跳转到success.jsp页面
    • :在 springmvc-config.xml 文件中配置的视图解析器指定了视图查找的页面的头和尾部分,则在controller中返回的字符串就是去掉该头和尾的中间完整部分,比如视图控制器中是这样设置的:

      1. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      2. <property name="prefix" value="/WEB-INF/pages/"/>
      3. <property name="suffix" value=".jsp"/>
      4. </bean>
    • 而页面的文件结构若为:

WEB-INF
|———-pages
|———-admin
| └——-main.jsp
|———-student
└——-index.jsp
则要访问admin下面的main.jsp时,系统会从WEB-INF去找/WEB-INF/pages/admin/main.jsp,则controller返回的则是去掉配置器里面头和尾部分的 admin/main

  1. 返回viod,即控制器里面的方法返回void,则执行完该方法后 会去找该方法前面的@RequestMapping所指定的字符串同名的jsp文件,若想让它跳转到其他名字的页面,则需要写request和response 或重定向手动设置。麻烦,还不如直接返回String

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

  1. forword转发,return "forword:/WEB-INF/pages/success.jsp";,相当于request. getRequesDispatcher("url").forword(request,response),使用请求转发,既可以转发到jsp,也可以转发到其他的控制器方法。
  2. redirect重定向,return "redirect:/index.jsp",重定向不能到WEB-INF下面的页面

3. ResponseBody相应json数据

  1. 当项目中使用外部js、css、images等静态文件,需要在bean.xml中配置,告诉前端控制器,哪些静态文件不需要拦截```xml ```

2.1 页面发送AJAX请求,

  1. $.ajax({
  2. url:"testAjax",
  3. contentType:"application/json;charset=UTF-8",
  4. data:'{"name":"毕设","address":"巴黎"}',
  5. dataType:"json",
  6. type:"post",
  7. success:function (data) {
  8. // data 服务器端响应的json数据,进行解析
  9. alert(data.name);
  10. }
  11. });

2.2 后端接收,并返回一个对象

  1. @RequestMapping("/testAjax")
  2. public @ResponseBody User testAjax(@RequestBody User user){
  3. System.out.println("testAjax worked...");
  4. // 客户端发送ajax请求,传的是json字符串,后端把json字符串封装到user对象中
  5. System.out.println(user);
  6. // 做响应,模拟从数据库中得到数据
  7. user.setName("菊次郎");
  8. return user;
  9. }

文件上传

  1. 文件上传的前提
    1. form表单的enctype取值必须是: multipart/form-data,表单请求正文的类型 表单分块
    2. method属性取值必须是post
    3. 提供一个文件选择域<input type="file" />

使用fileupload组件上传文件

  1. 传统方式
  1. // 上传的位置
  2. String path = request.getSession().getServletContext().getRealPath("/loads/");
  3. // 判断该路径知否存在
  4. File file = new File(path);
  5. if(!file.exists()){
  6. // 则创建
  7. file.mkdirs();
  8. }
  9. // 解析request对象,获取上传文件项
  10. DiskFileItemFactory factory = new DiskFileItemFactory();
  11. ServletFileUpload upload = new ServletFileUpload(factory);
  12. // 解析request
  13. List<FileItem> items = upload.parseRequest(request);
  14. // 遍历
  15. for(FileItem item : items){
  16. // 进行判断,当前item对象是否是上传文件项
  17. if(item.isFormField()){
  18. // 普通表单项
  19. }else{
  20. // 上传文件项
  21. // 获取上传文件的名称
  22. String filename = item.getName();
  23. // 完成上传
  24. item.write(new File(path, filename));
  25. // 删除临时文件
  26. item.delete();
  27. }
  28. }
  1. 使用SpringMVC方式上传文件

    1. bean.xml文件中配置springMVC的文件解析器对象,注意id名必须是这个xml <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxInMemorySize" value="10485760"></property> </bean>

    2. 在某jsp中写文件上传按钮html <form action="fileUpload2" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="upload" /><br/> <input type="submit" value="上传"/> </form>

    3. 在控制器中写代码,注意上面的input的name值必须要和下面的形式参数的第二个名称一致```java public String fileUpload2(HttpServletRequest request, MultipartFile upload) throws Exception{ System.out.println(“fileUpload worked…”);

      // 使用fileupload组件上传文件 // 上传的位置 String path = request.getSession().getServletContext().getRealPath(“/loads/“); // 判断该路径知否存在 File file = new File(path); if(!file.exists()){

      1. // 则创建
      2. file.mkdirs();

      } String filename = upload.getOriginalFilename(); // 把文件的名称设成唯一值 String uuid = UUID.randomUUID().toString().replace(“-“,””); filename=uuid+”_”+uuid; upload.transferTo(new File(path, filename));

      return “success”; } ```

异常处理

  1. springMVC异常处理
    1. 编写自定义异常类(做提示信息)
    2. 编写异常处理器,实现HandlerExceptionResolver接口
    3. 配置异常处理器,在bean.xml文件中配置

拦截器

  1. Srping MVC 中的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。可以自定义拦截器
  2. 拦截器只会拦截访问的控制器方法,如果访问的是jsp, html, css, image, js,不会进行拦截
  3. 自定义拦截器:
    1. 编写拦截器,必须实现HandlerInterceptor接口。
      • preHandle方法,预处理,在controller方法前执行
      • postHandle方法,后处理,在controller方法执行后,success.jsp执行前 执行
      • afterCompletion方法,最后执行 在success.jsp之后执行
    2. 配置拦截器,在bean.xml中配置

整理的小事

  1. 从controller返回一个单值给jsp,不跳转,仅判断提交结果是否成功
    1. 在controller中方法返回值为 void ,使用 HttpServletResponse response ,返回一个数字1给前端的ajax的success接收
      1. PrintWriter out = response.getWriter();
      2. out.print(1); // 只返回数据,不跳转
      3. out.close();
      1. success: function (res) { // 这个res就是print过来的值
      2. console.log(res);
      3. if (res) {
      4. layer.msg('已提交申请');
      5. } else {
      6. layer.msg("提交失败")
      7. }
      8. }
      b. 然后若需要弹出 比如layui的弹出提示框,则需要在ajax函数的后面( }) 后面)接上 return false