Spring MVC知识点复习一

一、SpringMVC环境搭建

既然学到了SpringMVC了,那么我们就把前面的MyBatis、Spring都联系起来,在一整个web项目中他们三个是各司其职,分别负责服务器端的表现层、业务层、持久层。

1.首先还是导入jar包依赖

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

 值得注意的是,这次我们把spring的版本给固定了,不再需要我们没配置一个就指定一个version。

2.配置前端控制器,实质上就是一个servlet,配置在WEB-INF中去,取名web.xml

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!-- 配置前端控制器 -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <!--发任何请求都要经过配置的这个servlet-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

3.建立springMVC的配置文件,在resources目录下叫springmvc.xml,这里先提前说明,这个是要开启注解扫描的,所以名称空间中需要有context,所以我们先把名称空间卸载这里,接下来再添其他的。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
</beans>

4.把该建的一些包给建好,比如com.itheima.controller

二、springMVC入门程序的编写

在这里我们写一个入门程序,他的需求很简单,就是通过点击一个页面上的超链接,然后跳转到入门成功的页面。

1.把该写的前端页面给写好,这里就是直接在index.jsp上写超链接的页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="hello">入门程序</a>
</body>
</html>

跳转页面在WEB-INF下新建一个pages文件夹,然后在里面写要跳转的页面即success.jsp,这里就不success.jsp了

2.在com.heima.controller包下新建一个HelloController类在里面进行主要的代码编写

@Controller
public class HelloController {
    @RequestMapping(path = "/hello")
    public String sayHello(){
        System.out.println("Hello SpringMVC");
        return "success";
    }
}

 这个程序主要就是实现了从前端的映射和页面的跳转,页面的跳转是通过RequestMapping这个注解实现的,但是前提是这个类前面要有Controller注解,让springMVC知道这是一个控制类。

3.springMVC配置文件的编写。

所以我们需要在springmvc.xml中创建一个注解扫描器和视图解析器,分别对应于这两项任务,前者负责扫描包下有SpringMVC相关的注解,后者为了实现页面的跳转。还有一个现在入门程序配不配都无所谓,那就是开启springMVC的注解支持,

<!-- 开启注解扫描器 -->
    <context:component-scan base-package="cn.itcast"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <mvc:annotation-driven/>

 写到这里我发现现在包也可以扫描了,基本上springMVC的这一部分算是完成了,但是有一个问题就是我们的springmvc.xml这个配置文件从始至终都没有被加载过,所以我们需要在前端控制器的配置文件中实现对springmvc.xml这个配置文件的加载。配置完之后前端控制器变成了这样:

<!-- 配置前端控制器 -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置初始化参数,就是让他去加载springmvc的配置文件 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!-- 如下这样配置,以后启动服务器就可以创建这个servlet对象 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!--发任何请求都要经过配置的这个servlet-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

到现在为止入门程序编写完成。我们回顾一下整个入门程序,其大致流程可以用下面的这个框图来表示:

 事实上我们可以看到前端控制器在整个处理过程中始终处于一个核心的地位,然后是通过组件来实现一系列的操作的,真实的情况远比上图要麻烦,请看下图:

其中这个处理适配器、处理映射器、视图解析器被称为SpringMVC的三大组件,前两样都自动帮我们加载了,不需要我们手工去配置,只需要配最后一样就可以了。 

 三、请求参数绑定

这种参数绑定比较简单,主要分绑定一般的参数,绑定自定义参数,绑定集合参数,下面就直接放一个表单和他对应的实体类,涉及了各种参数绑定的样例:

<form action="param/saveAccount" method="post">
        姓名:<input type="text" name="name"/><br/>
        密码:<input type="text" name="password"/><br/>
        金额:<input type="text" name="money"/><br/>
        用户名:<input type="text" name="user.username"/><br/>
        年龄:<input type="text" name="user.age"><br/>
        用户名:<input type="text" name="list[0].username"/><br/>
        年龄:<input type="text" name="list[0].age"><br/>
        用户名:<input type="text" name="map['one'].username"/><br/>
        年龄:<input type="text" name="map['one'].age"><br/>
        生日:<input type="text" name="birthday">
        <input type="submit" value="提交"/>
    </form>

Account类

package cn.itcast.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class Account implements Serializable {
    private String name;
    private String password;
    private Double money;
    private List<User> list;
    private Map<String,User> map;
    private User user;
    private Date birthday;

    @Override
    public String toString() {
        return "Account{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", money=" + money +
                ", list=" + list +
                ", map=" + map +
                ", user=" + user +
                ", birthday=" + birthday +
                '}';
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public List<User> getList() {
        return list;
    }

    public void setList(List<User> list) {
        this.list = list;
    }

    public Map<String, User> getMap() {
        return map;
    }

    public void setMap(Map<String, User> map) {
        this.map = map;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

}

 四、配置中解决中文乱码的问题

有关中文乱码的问题我们只需要配置一个过滤器就行,在每次我们请求的时候都帮助我们转码,配置如下:

<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>

五、自定义类型转换器

当我们在前端的表单提交日期相关数据时,提交的肯定是String类型的变量,但是在我们后台需要的是Date类型的变量,所以我们需要一个类型转换器,来帮助我们将String转成Date。首先我们需要自己定义一个用于转换的工具类,在com.itheima包下新建一个utils的文件夹,在下面新建一个StringToDateConvertor,具体写法如下:

public class StringToDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        if(source == null){
            throw new RuntimeException("请传回正确的数据");
        }else {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            try {
                return df.parse(source);
            } catch (Exception e) {
                throw new RuntimeException("数据异常");
            }
        }
    }
}

随后去springmvc.xml中去把这个自定义类型转换器给配置起来:

<bean id="conversionServiceFactory" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="cn.itcast.utils.StringToDateConverter"/>
            </set>
        </property>
    </bean>

配完之后,注意这是一个新的组件,框架不会自动给我们启动加载这个组件,所以需要我们自己手动写上打开,就在前面定义过的开启SpringMVC的注解支持那里开启。

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

 这样就完成了类型转换器的定义。

六、其他的一些注解

1.RequestParam

解决的是方法中的局部变量名和前端传来的数据变量名不同的问题,比如前端传来的是:

<a href="param/annoTest1?name=哈哈">requestParameter</a>

那么我们后端这样使用RequestParam注解:

@RequestMapping("/annoTest1")
    public String annoTest1(@RequestParam(name="name")String username){
        System.out.println(username);
        return "success";
    }

 2.RequestServlet

用于产生原生的servlet

@RequestMapping(path = "/servletTest")
    public String servletTest(HttpServletRequest hrq, HttpServletResponse hrp){
        System.out.println(hrq);
        HttpSession session = hrq.getSession();
        System.out.println(session);
        ServletContext servletContext = session.getServletContext();
        System.out.println(servletContext);
        System.out.println(hrp);
        return "success";
    }

 3.REST编程风格---PathVariable

简单说一下这个编程风格,比如原先对一个资源进行请求的时候,比如对一个用户的表进行操作,我们会有更新、删除、等操作,所以我们会每一个操作都会对应一个独立的访问路径:

这样就有些繁琐了,其实我们可以只采用一个相同的路径,也就是/user/,通过区分访问方式如:GET、PUT、POST来对不同的操作进行访问,假如我们如果在同一路径有两个不同的方法,其访问方式是相同的,我们只需要在路径后面加上一个id就行了,如:/user/9。这样写路径会更加简洁,当然REST只是一种风格并不是规范,没有必要硬要遵循。

 前端我们是这样写的:

<a href="param/annoTest3/10">pathVariable</a>

后端我们这样来获取id:

@RequestMapping("/annoTest3/{uid}")
    public String annoTest3(@PathVariable(name="uid") String id){
        System.out.println(id);
        return "success";
    }

 4.ModelAttribute

这个注解还是比较重要的,分两种,一种是方法上的注释,一种是成员变量上的注释。当这个注解出现在方法上的时候,这个方法会优先于控制器中的其他方法执行。而且这种带ModelAttribute的注解方法有两种写法,一种有返回值,一种没有返回值。我们先说有返回值的。

前端是这样写的:

<form action="param/annoTest4" method="post">
        用户名:<input type="text" name="uname"/>
        <input type="submit" value="提交">
    </form>

我们要实现什么的是,这个输入只能输入一个用户名,我们需要提交之后在后端我们从数据库把用户名对应的年龄给拿出来,然后和这个用户名一起疯转成一个对象。这里我们就暂时不写数据库的相关程序了,就假设这个年龄我们已经查询得到了。

@ModelAttribute
    public User showUser(String uname){
        User user = new User();
        user.setUsername(uname);
        user.setAge(13);
        return user;
    }

就这样得到了一个user对象,然后我们再将其打印下来

@RequestMapping("/annoTest4")
    public String annoTest4(@ModelAttribute("aaa") User user){
        System.out.println("annoTest4执行了...");
        System.out.println(user);
        return "success";
    }

这样就实现了从数据库中查询相关所需要的数据,然后封装成一个对象。

除此之外还有一种没有返回值的写法,它的思想就是封装对象之后放在一个map中存起来,然后要用就直接通过键值对进行获取,其写法如下:

@ModelAttribute
    public void showUser(String uname, Map<String,User> map){
        User user = new User();
        user.setAge(13);
        user.setUsername(uname);
        map.put("aaa",user);
    }
@RequestMapping("/annoTest4")
    public String annoTest4(@ModelAttribute("aaa") User user){
        System.out.println("annoTest4执行了...");
        System.out.println(user);
        return "success";
    }

 5.SessionAttributes--对象的存储、取出、删除

首先我们考虑如何将信息存储进request域对象,我们可以采用原生servlet的方式,但是那样耦合度太高,于是SpringMVC中给我们提供了一个类Model,这样我们就能够将其存进request域对象了,如下:

@RequestMapping("/annoTest5")
    public String annoTest5(Model model){
        //将信息存储进request域对象
        model.addAttribute("msg","美美");
        return "success";
    }

 至于如何存进Session域对象中,我们采用的就是SessionAttributes注解,但是请注意,这个注解只能加在类前面,所以我们在整个控制类前面加上注解:@SessionAttributes(value={"msg"})

这样当你执行上面那串代码的时候就将数据存进了Session域对象中。下面就展示如何取数据和删除数据了:

@RequestMapping("/annoTest6")
    public String annoTest6(ModelMap modelMap){
        String msg = (String)modelMap.get("msg");
        System.out.println(msg);
        return "success";
    }
@RequestMapping("/annoTest7")
    public String annoTest7(SessionStatus status){
        status.setComplete();
        return "success";
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值