三层架构和MVC
三层架构
- 服务器端程序,一般基于两种形式,一种C/S架构程序,一种B/S架构程序
- 使用Java语言基本上都是开发B/S架构的程序,B/S架构又分成了三层架构
- 三层架构
MVC模型
- MVC全名是Model View Controller 模型视图控制器,每个部分各司其职。
- Model:数据模型,JavaBean的类,用来进行数据封装。
- View:指JSP、HTML用来展示数据给用户
- Controller:用来接收用户的请求,整个流程的控制器。用来进行数据校验等。
SpringMVC入门
导入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>在
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>在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>控制器
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
: 用于指定限制请求消息头的条件- 这些属性只要同时出现就是与的关系
请求参数绑定
HelloController1
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.jsp1
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类型请求参数绑定
AccountController1
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";
}
}
Account1
2
3
4
5
6
7
8public class Account implements Serializable {
private String username;
private String password;
private Double money;
//在一个实体类中的实体变量
private User user;
...
}
- 注意
- 要注意的就是要保证name和你要封装的JavaBean的变量名一直,可以自动完成封装。
- 要给实体类中的引用类型赋值时,只用使用
引用类型的变量名.变量名
即可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 | public class User implements Serializable { |
因此我们需要自己定义一个类,实现Converter<S,T>接口,将特定格式的String类型的日期转换为Date类型1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public 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 | @RequestMapping("testRequestParam") |
使用此注解后,传入参数名称一定要与value
中的相同
@RequestBody
- 作用位置: 参数上
- 作用: 用于获取请求体的内容。直接使用的到
key=value&key=value..
结构的数据 (get
请求方式不适用) - 属性:
required
: 是否必须有请求体。默认是true
,此时get
请求方式会报错。如果为false
,get
请求得到的是null
1 | /** |
@PathVaribale
- 作用位置: 参数上
- 作用: 用于绑定
URL
中的占位符,获取占位符中的数据 - 属性:
value
: 用于指定URL
中占位符名称required
: 是否必须提供占位符
1 | /** |
@RequestHeader(不常用)
- 作用位置: 参数上
- 作用: 用于获取请求消息头
- 属性:
value
: 提供消息头名称required
: 是否必须有此消息头
1 | /** |
@CookieValue
- 作用位置: 参数上
- 作用: 用于把指定cookie名称的值传入控制器方法参数
- 属性:
value
: 提供cookie的名称required
: 是否必须有此cookie
1 | /** |
@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
: 用于获取数据的key
。key
可以是POJO
的属性名称,也可以是map
结构的key
。
@SessionAttributes
- 作用位置: 类上
- 作用: 用于多次执行控制器方法间的参数共享(将参数存到session域中)
- 属性:
value
: 用于指定存入的属性名称type
: 用于指定存入的数据类型
1 | @Controller |