SpringMVC学习笔记(1)

三层架构和MVC

三层架构

  1. 服务器端程序,一般基于两种形式,一种C/S架构程序,一种B/S架构程序
  2. 使用Java语言基本上都是开发B/S架构的程序,B/S架构又分成了三层架构
  3. 三层架构
    1. 表现层:WEB层,用来和客户端进行数据交互的。表现层一般会采用MVC的设计模型
    2. 业务层:处理公司具体的业务逻辑的
    3. 持久层:用来操作数据库的

MVC模型

  1. MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。
  2. Model:数据模型,JavaBean的类,用来进行数据封装。
  3. View:指JSP、HTML用来展示数据给用户
  4. Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等。

SpringMVC入门

  1. 导入jar包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <!-- 版本锁定 --> 
    <properties>
    <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>
  2. web.xml配置核心控制器

    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>
    <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
    <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-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!-- 拦截所有请求 -->
    <url-pattern>/</url-pattern>
    </servlet-mapping>
  3. 在springmvc.xml中导入约束

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?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">

    <!-- 配置spring创建容器时要扫描的包 -->
    <context:component-scan base-package="com.itheima"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 配置spring开启注解mvc的支持-->
    <mvc:annotation-driven></mvc:annotation-driven>
    </beans>
  4. 控制器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**
    * 控制器
    * @author
    */
    @Controller
    public class HelloController {
    /**
    * 接收请求 * @return
    */
    @RequestMapping(path="/hello")
    public String sayHello() {
    System.out.println("Hello SpringMVC!!");
    return "success";
    }
    }

@RequestMapping

  • 作用: 用于建立请求 URL 和处理请求方法之间的对应关系。
  • 功能: 可以在类上添加注解(表示一级目录),也可以在方法上添加(表示二级目录)
  • 属性:
    • value: 和path一样,用来指定请求的 URL
    • method: 用于指定请求的方式(POST, GET等)
      • 一般超链接使用的是GET请求方式
    • params: 用于指定限制请求参数的条件,支持简单的表达式,要求请求参数的key和value必须和配置的一模一样
    • header: 用于指定限制请求消息头的条件
    • 这些属性只要同时出现就是与的关系

请求参数绑定

HelloController

1
2
3
4
5
6
@RequestMapping(value = "/login", params = {"username","password"})
public String login(String username, String password) {
System.out.println("用户名为: " + username);
System.out.println("密码为: " + password);
return "success";
}

index.jsp

1
2
3
4
5
<form method="get" action="user/login">
<input type="text" id="username" name="username">
<input type="text" id="password" name="password">
<button type="submit" id="button">登录</button>
</form>

支持的数据类型

  • 基本类型参数:
    • 包括基本类型和 String 类型
  • POJO(JavaBean) 类型参数:
    • 包括实体类,以及关联的实体类
  • 数组和集合类型参数 :
    • 包括 List 结构和 Map 结构的集合(包括数组)

SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。

JavaBean类型请求参数绑定

AccountController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
@RequestMapping("/account")
public class AccountController {
/**
* 请求参数绑定把数据封装到JavaBean的类中
* @param account
* @return
*/
@RequestMapping(value = "/saveAccount", method = RequestMethod.POST, params = {"username", "password", "money"})
public String saveAccount(Account account){
System.out.println("保存了");
System.out.println(account);
return "success";
}
}

Account

1
2
3
4
5
6
7
8
public class Account implements Serializable {
private String username;
private String password;
private Double money;
//在一个实体类中的实体变量
private User user;
...
}

  • 注意
    1. 要注意的就是要保证name和你要封装的JavaBean的变量名一直,可以自动完成封装。
    2. 要给实体类中的引用类型赋值时,只用使用引用类型的变量名.变量名即可
      1
      2
      3
      4
      5
      6
      7
      8
      <form method="post" action="account/saveAccount">
      用户名:<input type="text" id="username" name="username"><br>
      密码:<input type="text" id="password" name="password"><br>
      金额:<input type="text" id="money" name="money"><br>
      用户姓名:<input type="text" id="uname" name="user.uname"><br>
      用户年龄:<input type="text" id="age" name="user.age"><br>
      <input type="submit" value="提交">
      </form>

解决Post请求中文乱码问题

在web.xml中配置一个过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--配置解决中文乱码问题的过滤器-->
<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>

集合类型请求参数绑定

  • List形式只要直接用集合名[索引].变量名即可
  • Map形式只要直接用集合名[key].变量名即可
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <form method="post" action="account/saveAccount">
    用户名:<input type="text" id="username" name="username"><br>
    密码:<input type="text" id="password" name="password"><br>
    金额:<input type="text" id="money" name="money"><br>

    用户姓名:<input type="text" name="list[0].uname"><br>
    用户年龄:<input type="text" name="list[0].age"><br>

    用户姓名:<input type="text" name="map['one'].uname"><br>
    用户年龄:<input type="text"name="map['one'].age"><br>
    <input type="submit" value="提交">
    </form>

自定义类型转换器

Spring框架自带的类型转换器无法将2018-08-08格式的日期封装到Date中

1
2
3
4
5
6
<form method="post" action="account/saveUser">
用户姓名:<input type="text" name="uname"><br>
用户年龄:<input type="text"name="age"><br>
用户生日:<input type="text"name="birthday"><br>
<input type="submit" value="提交">
</form>

1
2
3
4
5
6
public class User implements Serializable {
private String uname;
private Integer age;
private Date birthday;
...
}

因此我们需要自己定义一个类,实现Converter<S,T>接口,将特定格式的String类型的日期转换为Date类型

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 source) {
try {
if (source == null){
throw new RuntimeException("请传入日期数据");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date date = df.parse(source);
return date;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}

完成后我们需要在Spring配置文件中配置类型转换器,在mvc:annotation-driven标签中,conversion-service标签中引入自定义类型转换器

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 配置类型转换器工厂 -->
<bean id="conversionService1" class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 给工厂注入一个新的类型转换器 -->
<property name="converters">
<set>
<!-- 添加自定义类型转换器 -->
<bean id="dateConverter" class="com.xushui.utils.DateConverter"></bean>
</set>
</property>
</bean>
<!--开启Spring注解支持 引用自定义类型转换器-->
<mvc:annotation-driven conversion-service="conversionService1"></mvc:annotation-driven>

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

获取Servlet原生API

你想获取Servlet的request或者response,你就在参数上加上他们,Spring框架会自动帮你获取

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("testRequest")
public String testRequest(HttpServletRequest request, HttpServletResponse response) {
System.out.println(request);

HttpSession session = request.getSession();
System.out.println(session);

ServletContext servletContext = session.getServletContext();
System.out.println(servletContext);

System.out.println(response);
return "success";
}


常用注解

@RequestParam

  • 作用位置: 参数上
  • 作用: 把请求中指定名称的参数给控制器中的形参赋值
  • 属性:
    • value: 请求参数中的名称(可以和参数列表的名字不同)
    • required: 请求参数中是否必须提供次参数。默认值true,表示必须提供,不提供就报错。
1
2
3
4
5
6
@RequestMapping("testRequestParam")
public String testRequestParam(@RequestParam("name") String username){
System.out.println("用户名: " + username);
System.out.println("testRequestParam执行了...");
return "success";
}

使用此注解后,传入参数名称一定要与value中的相同

@RequestBody

  • 作用位置: 参数上
  • 作用: 用于获取请求体的内容。直接使用的到key=value&key=value..结构的数据 (get请求方式不适用)
  • 属性:
    • required: 是否必须有请求体。默认是true,此时get请求方式会报错。如果为falseget请求得到的是null
1
2
3
4
5
6
7
8
9
10
/**
* 获取请求体内容
* @return
*/
@RequestMapping("testRequestBody")
public String testRequestBody(@RequestBody String body){
System.out.println("testRequestBody执行了...");
System.out.println(body);
return "success";
}

@PathVaribale

  • 作用位置: 参数上
  • 作用: 用于绑定 URL 中的占位符,获取占位符中的数据
  • 属性:
    • value: 用于指定 URL 中占位符名称
    • required: 是否必须提供占位符
1
2
3
4
5
6
7
8
9
10
/**
* PathVariable注解
* @return
*/
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") String id){
System.out.println("testPathVariable执行了...");
System.out.println("id为" + id);
return "success";
}

@RequestHeader(不常用)

  • 作用位置: 参数上
  • 作用: 用于获取请求消息头
  • 属性:
    • value: 提供消息头名称
    • required: 是否必须有此消息头
1
2
3
4
5
6
7
8
9
10
/**
* RequestHeader注解
* @return
*/
@RequestMapping("/testRequestHeader")
public String testRequestHeader(@RequestHeader("Accept") String accept){
System.out.println("RequestHeader执行了...");
System.out.println("accept为" + accept);
return "success";
}

@CookieValue

  • 作用位置: 参数上
  • 作用: 用于把指定cookie名称的值传入控制器方法参数
  • 属性:
    • value: 提供cookie的名称
    • required: 是否必须有此cookie
1
2
3
4
5
6
7
8
9
10
/**
* CookieValue注解
* @return
*/
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String cookie){
System.out.println("RequestHeader执行了...");
System.out.println("cookie为" + cookie);
return "success";
}

@ModelAttribute

  • 作用位置:

    • 方法上

      • 作用: 方法会在控制器的方法执行之前,先执行。有返回值或者无返回值都可以修饰。
      • 应用场景: 我们在编辑一个用户时, 用户有一些该字段的值是不允许被修改的。在提交表 单数据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        /**
        * ModelAttribute注解
        * @return
        */
        @RequestMapping("/testModelAttribute")
        public String testModelAttribute(User user){
        System.out.println("testModelAttribute执行了...");
        System.out.println(user);
        return "success";
        }

        @ModelAttribute
        public User showUser(String uname, String age) {
        // 模拟数据库查询
        User user = new User();
        user.setUname("赵四");
        user.setAge(18);
        user.setBirthday(new Date());

        user.setUname(uname);
        user.setAge(Integer.parseInt(age));

        return user;
        }
    • 参数上

      • 作用: 用于获取指定的数据给参数赋值
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        /**
        * ModelAttribute注解
        * @return
        */
        @RequestMapping("/testModelAttribute")
        public String testModelAttribute(@ModelAttribute("abc") User user){
        System.out.println("testModelAttribute执行了...");
        System.out.println(user);
        return "success";
        }

        @ModelAttribute
        public void showUser(String uname, String age, Map<String, User> map) {
        // 模拟数据库查询
        User user = new User();
        user.setUname("赵四");
        user.setAge(18);
        user.setBirthday(new Date());

        user.setUname(uname);
        user.setAge(Integer.parseInt(age));

        map.put("abc", user);
        }
  • 属性:

    • value: 用于获取数据的keykey可以是POJO的属性名称,也可以是map结构的key

@SessionAttributes

  • 作用位置: 类上
  • 作用: 用于多次执行控制器方法间的参数共享(将参数存到session域中)
  • 属性:
    • value: 用于指定存入的属性名称
    • type: 用于指定存入的数据类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Controller
@RequestMapping("/anno")
@SessionAttributes("msg")//将msg存入到session域中
public class AnnoController {
/**
* SessionAttributes注解
* @return
*/
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Model model){
System.out.println("testSessionAttributes执行了...");
// 底层会存储到request域对象中
model.addAttribute("msg","佩佩");
return "success";
}

/**
* 取出Session中的值
* @return
*/
@RequestMapping("/getSessionAttributes")
public String getSessionAttribute(ModelMap modelMap){
System.out.println("getSessionAttribute执行了...");
String msg = (String) modelMap.get("msg");
System.out.println(msg);
return "success";
}

/**
* 清除Session域中的值
* @return
*/
@RequestMapping("/delSessionAttributes")
public String delSessionAttributes(SessionStatus status){
System.out.println("delSessionAttributes执行了...");
status.setComplete();
return "success";
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×