学习笔记--Spring MVC

1、SpringMVC开发步骤

1)导入MVC相关坐标

2)配置SpringMVC核心控制器DispatcherServlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 配置SpringMVC前端控制器-->
    <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:spring-mvc.xml</param-value>
        </init-param>
    <!--   不配置说明是访问时启动服务,配置时就是一直启动服务 数字越小优先级越高    -->
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
    <!--   如果配置的是缺省的,那么说明访问所有的网址都要启动这个服务servlet     -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

  这里的

1
2
3
4
<init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
  </init-param>

  一开始不明白,后来查阅资料后发现:

  SpringMVC配置文件的默认路径是WEB-INF下面,如果你的配置文件不想放在WEB-INF目录下,则可以通过

contextConfigLocation这个初始化参数进行指定。classpath:xxx就是去resource目录下找。

3)创建Controller类和视图页面

4)使用注解配置Controller类中业务方法的映射地址

5)配置SpringMVC核心文件spring-mvc.xml(组件扫描之类的)

组件扫描必须在context命名空间下,需要自己添加设置。

1
2
3
xmlns:context="http://www.springframework.org/schema/context"
//在xsi:schemaLocation中添加
http://www.springframework.org/schema/context <br>http://www.springframework.org/schema/context/spring-context.xsd

6)客户端发起请求测试

 

2、SpringMVC注解解析

2.1 @RequestMapping

RequestMapping用于建立请求URL和处理请求方法之间的对应关系。

简单来说就是跳转到某地址时会执行的方法。

有两种可以使用该方法的位置:

1、类上,说明请求URL的第一级访问目录。此处可以不写,就相当于应用的根目录。

2、方法上,说明请求URL的第二级访问目录,与类上使用@RequestMapping标注的一级目录一起组成访问的虚拟路径。

 另外,该注解还附有3个参数:

value:用于指定请求的URL,如果只有这个参数,可以不写value

1
@RequestMapping("quick") = @RequestMapping(value = "quick")

method:用于指定请求的方式,如果将值设为RequestMethod.GET说明只有Get请求可以通过。

params:用于指定限制请求参数的条件。如果params = {"accountName"} 表示请求参数必须有accountName

2.2 配置内部资源视图解析器

作用:在配置跳转视图的时候,能够简化地址

1
2
3
4
5
6
<!-- 配置内部资源视图解析器 -->
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <!--   用这个配置的,都是/jsp/xxx.jsp     -->
      <property name="prefix" value="/jsp/"/>
      <property name="suffix" value=".jsp"/>
  </bean>

  

用bean注入mvc包里的视图解析器类。这个类有prefix和suffix的set方法,可以自定义属性的值。

prefix:地址的共同前缀。

suffix:地址的共同后缀。

2.3 SpringMVC的数据响应方式

1)页面跳转

  • 直接返回字符串

  具体做法见2.2配置内部资源解析器

  • 通过ModelAndView对象返回

  ModelAndView对象返回方式的好处在于:Model是用于封装数据的,View是展示视图的。可以分离开。

  有以下几种使用方式:

  一、在方法内创建一个ModelAndView类

  

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping("/quick2")
  public ModelAndView save2(){
      /*
          Model: 模型 用于封装数据
          View: 视图 用于展示视图
       */
      ModelAndView modelAndView = new ModelAndView();
      modelAndView.addObject("username","xcc");
      modelAndView.setViewName("success");
      return modelAndView;
  }

  addObject方法是添加数据,参数是一个键值对,前面是名称,后面的是值,不仅仅是字符串,别的数据类型都行。

  setViewName方法是命名视图地址,这个地址也受内置视图解析器的影响。

  二、在请求方法中写ModelAndView形参。

  

1
2
3
4
5
6
7
8
9
/*
      当springMVC收到这个跳转函数的时候,发现有modelandview实参,会自己创建一个注入。
   */
  @RequestMapping("/quick3")
  public ModelAndView save3(ModelAndView modelAndView){
      modelAndView.addObject("username","xcnb");
      modelAndView.setViewName("success");
      return modelAndView;
  }

  MVC识别到请求方法中有形参的时候,会自动帮你注入一个实参。

  优点是避免每次手动创建一个ModelAndView对象。其余的同一。

  三、model和view进行分离

  

1
2
3
4
5
6
7
8
/*
      这里将modelandview分开,model以参数的形式交给stringmvc处理,string以逻辑视图的方式返回。作用是一样的
   */
  @RequestMapping("/quick4")
  public String save4(Model model){
      model.addAttribute("username","小超和你");
      return "success";
  }

  视图以字符串格式回传,model以参数形式创建。

2)回写数据

  • 直接返回字符串
  • 返回对象或集合

  基础用法(直接返回字符串)
  

1
2
3
4
5
6
7
8
9
/*
      responsebody是告知函数返回的字符串不是跳转而是直接在http响应体中返回
   */
  @RequestMapping("/quick5")
  @ResponseBody
  public String save5(){
      //回写字符串
      return "hello xcc";
  }

  与返回跳转类似,如果不需要跳转而是回写数据的话,需要在方法上加注释@ResoponseBody

  ResponseBody意思是响应体,因为方法与res.writer.print相同,是通过响应数据回传的。

  更好的用法

  因为一般回传的数据都是以对象的JSon格式为主,所以,可以用第三方对象转json格式的工具。

  将需要回传的数据转换成json格式后再回传。

  

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping("/quick6")
  @ResponseBody
  public String save6() throws JsonProcessingException {
      User user = new User();
      user.setAge(10);
      user.setUsername("xcc");
      //使用json的转换工具将对象转换成json格式字符串在返回
      ObjectMapper objectMapper = new ObjectMapper();
      String json = objectMapper.writeValueAsString(user);
      return json;
  }

  json转换工具需要导 jackson-databind 依赖包

  最好的用法(返回对象和集合):

  刚才使用的方法是用第三方的工具包来给我们将对象转换成Json格式的字符串。

  但每次都要创建一个Mapper类显得有些麻烦,MVC帮我们底层完成了这个功能。

  在配置文件中,加入mvc命名空间:

  

1
2
3
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"

  再加入以下配置:

  

1
<mvc:annotation-driven/>

  这样之后,以后要取得返回的Json格式的字符串,就不必使用转换工具,直接返回该对象,处理器适配器

  会自动将该对象转换成Json格式的字符串。

  例子:

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
      如果想要让返回的对象是一个已经处理好的json字符串。
      在spring-mvc中注入RequestMappingHandlerAdapter
      向messageConverters注入MappingJackson2HttpMessageConverter
      前提必须是@responsebody响应体返回
 
      替换这个配置可以在xml中<mvc:annotation-driven/>这句注解替代
   */
  @RequestMapping("/quick7")
  @ResponseBody
  public User save7() {
      User user = new User();
      user.setAge(12);
      user.setUsername("xcc");
      return user;
  }

  

2.4 SpringMVC获得请求数据(服务器端)

1)普通数据类型

  例子:

  

1
2
3
4
5
6
7
8
9
10
/*
      controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动匹配
   */
  @RequestMapping("/quick8")
  @ResponseBody
  public void save8(String username,int age) {
      //当网址是localhost:8080/user/quick8?username=xxxx&age=xx时,会将username和age自动匹配
      System.out.println(username);
      System.out.println(age);
  }

  当方法是响应体方法、且业务方法的参数名称与请求参数的名称一致时,

  MVC会自动匹配参数,将值传给该参数。

2)获得POJO类型数据

  例子:

1
2
3
4
5
6
7
8
/*
    获得pojo类的数据,请求参数恰好都是pojo类中的属性,会自动适配填补
 */
@RequestMapping("/quick9")
@ResponseBody
public void save9(User user) {
    System.out.println(user);
}

  当请求参数的名称与POJO类的属性名称一致时,MVC会自动适配填补。

3)获得数组类型数据

  例子:

1
2
3
4
5
6
7
8
@RequestMapping("/quick10")
  @ResponseBody
  public void save10(String[] strs) {
      System.out.println(Arrays.asList(strs));
      //Arrays.asList() 是将数组转化成list集合的方法
      //但不支持add,remove,clear方法
      //遍历数组十分方便,但是如果要添加或者删除元素还是new一个list遍历添加。
  }

  当请求参数的名称与数组名称一致时,MVC会自动适配填补。

4)获得集合类型参数

  获得集合类型参数与别的数据略有不同,需要将集合放入一个VO对象,通过对VO对象的注入来获得集合类型参数。

  例子:

1
2
3
4
5
6
7
8
/*
      获得集合类型的数据,是将集合放在pojo类中实现,然后传入pojo类,名称对应
   */
  @RequestMapping("/quick11")
  @ResponseBody
  public void save11(VO vo) {
      System.out.println(vo);
  }

  在方法中,和获得POJO类型的数据类似。

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class VO {
 
    private List<User> userList;
 
    public List<User> getUserList() {
        return userList;
    }
 
    public void setUserList(List<User> userList) {
        this.userList = userList;
    }
 
    @Override
    public String toString() {
        return "VO{" +
                "userList=" + userList +
                '}';
    }
}

  VO对象中,将需要注入的集合加入成员属性中。

1
2
3
4
5
6
7
8
9
<body>
    <form action="${pageContext.request.contextPath}/user/quick11" method="post">
        <input type="text" name="userList[0].username"><br/>
        <input type="text" name="userList[0].age"><br/>
        <input type="text" name="userList[1].username"><br/>
        <input type="text" name="userList[1].age"><br/>
        <input type="submit" value="提交">
    </form>
</body>

  在页面中,将要注入的集合中的某一对象的什么元素对应,MVC就会自动填充属性。

 5)获得集合类型参数Ⅱ

  当使用ajax提交数据时,可以指定contextT为json格式,那么在方法参数位置使用@RequestBody可以直接接收集合数据而无需使用POJO进行包装。

  

1
2
3
4
5
6
7
8
9
10
11
12
<script src="${pageContext.request.contextPath}/js/jquery-3.6.0.js"></script>  <script>
    let userList = [];
    userList.push({username:"zhansan",age:18});
    userList.push({username:"lisi",age:20});
 
    $.ajax({
        type:"Post",
        url:"${pageContext.request.contextPath}/user/quick12",
        data:JSON.stringify(userList),
        contentType:"application/json;charset=utf-8"
    })
</script>

  

1
2
3
4
5
@RequestMapping("/quick12")
  @ResponseBody
  public void save12(@RequestBody List<User> userList) {
      System.out.println(userList);
  }

  光是这样并不能找到jquery-3.6.0.js,因为之前在MVC配置中,DispatcherServlet的映射配置是缺省的,这意味着所有的地址请求

  都要走这个Servlet,而在ajax请求前,先申请导入了jquery的资源文件,但这个并不能被RequestMapping映射找到,所以就略过不处理,这就导致了

  其实jquery根本没有被导入。

  解决方法1:

  在Spring-mvc.xml中开放资源的访问。

  

1
2
<!-- 开放资源的访问 mapping是访问的地址格式、后面的是具体所在的目录-->
<mvc:resources mapping="/js/**" location="/js/"/>

  解决方法2:

  在Spring-mvc.xml中使用默认的处理器

1
2
<!-- 功能是当mvc找不到对应的servlet时用原始的处理器(tomcat)处理    -->
<mvc:default-servlet-handler/>

 

2.5 Post请求中如果出现乱码该如何解决

  可以配置一个filter过滤器,将所有代码格式全部变为UTF-8

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 配置全局过滤的filter  -->
  <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>
  </filter>
 
  <!--  对所有的资源都进行过滤  -->
  <filter-mapping>
      <filter-name>CharacterEncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>

  同样的<init-param>起到一个设置过滤器编码格式的作用。

 

2.6 参数绑定注解@requestParam

作用:当请求参数与需要的参数名称不一致,但仍想对应起来时,可以使用该注解配置value参数进行映射。

1
2
3
4
5
6
@RequestMapping("/quick13")
 @ResponseBody
  public void save13(@RequestParam("name") String username ,@RequestParam("age") String nianling) {
      System.out.println(username);
      System.out.println(nianling);
  }

  即:将请求地址为“http://localhost:8080/user/quick13?name=zhangsan&age=18” 依然可以对应注入参数。

补充:

@RequestParam有其他几个参数

  required:默认为true,说明请求地址时必须包含此参数。

  defaultValue: 当没有指定请求参数时,则使用指定的默认值赋值。

2.7 获得Restful风格的参数

Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件。

基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。

 

Restful风格的请求是使用“url+请求方式”表示一次请求目的的,HTTP协议里面四个表示操作方式的动词如下:

GET:获取资源

POST:新建资源

PUT:更新资源

DELETE:删除资源

 

示例:

1
2
3
4
5
6
//访问localhost:8080/user/quick14/zhangsan 最后不同的 username 回传的参数也不同
  @RequestMapping("/quick14/{username}")
  @ResponseBody
  public void save14(@PathVariable(value = "username") String username) {
      System.out.println(username);
  }

  用 @PathVariable 注解来将占位符和参数绑定,value和{}中的属性要保持一致。

 

2.8 自定义类型转换器

客户端请求的任何数据到达服务端之后都会变成字符串。

但客户端发送的关于数字的请求依然可以正常的访问,说明MVC内部有将数字(int)转换成字符串的方法。

但不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自定义转换器。

 

自定义类型转换器的开发步骤:

1)定义转换器类实现Converter接口(复写接口的方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DateConverter implements Converter<String,Date> {
 
    @Override
    public Date convert(String s) {
        // new 里面是样式
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = format.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

  

2)在配置文件中声明转换器。

1
2
3
4
5
6
7
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
      <property name="converters">
          <list>
              <bean class="com.xc.converter.DateConverter"/>
          </list>
      </property>
  </bean>

  

3)在<annotation-driven>中引用转换器

1
<mvc:annotation-driven conversion-service="conversionService"/>

 当遇到指定格式的时候,就会自动使用转换器。

 

2.9获得Servlet相关API

SpringMVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入,常用的对象如下:

 

HttpServletRequest

HttpServletResponse

HttpSession

 

1
2
3
4
5
6
7
@RequestMapping("/quick16")
  @ResponseBody
  public void save16(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
      System.out.println(request);
      System.out.println(response);
      System.out.println(session);
  }

  

2.10 获得请求头

1)@RequestHeader

使用@RequestHeader可以获得请求头信息。

注解属性如下:

value:请求头的名称

required:是否必须携带此请求头

1
2
3
4
5
@RequestMapping("/quick17")
  @ResponseBody
  public void save17(@RequestHeader(value = "User-Agent", required = false) String user_agent) {
      System.out.println(user_agent);
  }

  

2)@CookieValue

使用@CookieValue可以获得指定Cookie的值

注解属性如下:

value:指定Cookie的名称

required:是否必须携带此Cookie

1
2
3
4
5
@RequestMapping("/quick18")
  @ResponseBody
  public void save18(@CookieValue(value = "JSESSIONID") String jsessionId) {
      System.out.println(jsessionId);
  }

  

2.11 文件上传

1)文件上传客户端三要素

表单项type=“file”

表单的提交方式是post

表单的enctype属性是多部分表单形式,即enctype="multipart/form-data"

1
2
3
4
5
<form action="${pageContext.request.contextPath}/user/quick19" enctype="multipart/form-data">
      名称<input type="text" name="username"><br/>
      文件<input type="file" name="upload"><br/>
      <input type="button" value="上传">
  </form>

  

2) 用MVC实现单文件上传

导入fileupload和io坐标

1
2
3
4
5
6
7
8
9
10
11
<dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
  </dependency>
 
  <dependency>
     <groupId>commons-io</groupId>
     <artifactId>commons-io</artifactId>
     <version>2.6</version>
  </dependency>

  

配置文件上传解析器

 

1
2
3
4
5
<!--  配置文件上传解析器  -->
  <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <property name="defaultEncoding" value="UTF-8"/>
      <property name="maxUploadSize" value="500000"/>
  </bean>

  

单文件上传的业务方法

1
2
3
4
5
6
7
8
9
@RequestMapping("/quick19")
  @ResponseBody
  public void save19(String username, MultipartFile uploadFile) throws IOException {
      System.out.println(username);
      //System.out.println(uploadFile);
      //获得上传文件的名称
      String originalFilename = uploadFile.getOriginalFilename();
      uploadFile.transferTo(new File("D:\\upload\\"+originalFilename));
  }

  

transferTo方法将接受到的上传文件以相同文件的格式保存在服务器端。

2.12 多文件上传

大致与单文件一致,但是业务方法接收时改用数组

1
2
3
4
5
6
7
8
9
@RequestMapping("/quick20")
@ResponseBody
public void save20(String username, MultipartFile[] uploadFile) throws IOException {
    System.out.println(username);
    for (MultipartFile multipartFile : uploadFile) {
        String originalFilename = multipartFile.getOriginalFilename();
        multipartFile.transferTo(new File("D:\\upload\\"+originalFilename));
    }
}

  

1
2
3
4
5
6
<form action="${pageContext.request.contextPath}/user/quick20" method="post" enctype="multipart/form-data">
      名称<input type="text" name="username"><br/>
      文件<input type="file" name="uploadFile"><br/>
      文件<input type="file" name="uploadFile"><br/>
      <input type="submit" value="上传">
  </form>

  

posted @   小超和你  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?
点击右上角即可分享
微信分享提示