1 Spring MVC一些概念
2 SpringMVC 入门(项目)
步骤
是固定的.
解决 maven 加载慢问题
archetypeCatalog
internal 添加一个键值对
创建完是缺少 java,和 resources 两个目录的,自己创建并右键,java 设置为 Sources Root 目录, resources 设为Resources Root 目录.
pom.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yydcyy</groupId>
<artifactId>SpringMVC_v1.1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMVC_v1.1 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<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>
<build>
<finalName>SpringMVC_v1.1</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
resources 目录下新建 xml 配置文件 (复制我这个,全!)
<?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>
环境部署完毕,长这样.
配置 Tomcat (不明白的位置,百度关键字搜得到)
添加 tomcat 并将当前项目添加进去. OK
删了这个 index.jsp. 新建 (默认的不带处理 utf8 编码, 中文会出现乱码)
步骤:
web.xml - > spring…xml -> success.jsp -> 视图解析器 -> 测试 Demo
web.xml
java.class
@Controller
public class HelloController {
@RequestMapping(path="/hello")
public String sayHello(){
System.out.println("Hello StringMVC");
return "sayHello ok";
}
}
spring.xml
<?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">
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.yydcyy"></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>
</beans>
执行步骤示意图:
基于组件开发. 适配器是个好东西.
tomcat 默认启动打开 index.jsp 路径若不正确,可以更改配置
记住是选 Artifact (达成 war 包发布)
run 测试即可
RequestMapping注解
@RequestMapping(value=“xxx”) @RequestMapping(path=“xxxx”) 是一样的. 而 value 可以省略,故
@RequestMapping("") 也是对的.
@Controller
@RequestMapping(path="/user")
public class HelloController {
@RequestMapping(path="/hello")
public String sayHello(){
System.out.println("Hello StringMVC");
return "success";
}
}
添加 @RequestMapping() 注解后默认目录变成/hello 了, 比如需要访问 hello,应该跳转 /user/hello
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
你好啊, 羽扬
<a href="user/hello">入门配置成功</a>
</body>
</html>
正确了吧!
不知道为啥,这个都是 404 (应该是 400, 提示我传参数呐)
[params 和 headers 属性用得比较少]]
[ 试了下之前项目(目录层级好像被我玩坏了), 还是打不开.放弃了, 继续 ]
3 请求参数绑定
请求参数绑定入门
domain account bean (setter() getter() toString() )))) - > param.jsp 表单 (往类里封装). bean 属性与 表单 name相同)
User.java -> 引用类型 封装 : user.uname
domain (User , Account)
private String username;
private String password;
private Double money;
private User user;
....setter() getter() toString()
private String uname;
private Integer age;
param.jsp
<br/><H3>把数据封装Account类中</H3>
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
用户姓名:<input type="text" name="user.uname" /><br/>
用户年龄:<input type="text" name="user.age" /><br/>
<input type="submit" value="提交" />
</form>
ParamController.java
@RequestMapping(value = "/saveAccount")
public String saveAccount(Account account){
System.out.println("执行了...");
System.out.println(account);
return "success";
}
输出结果:
org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/Users/yuyang/Downloads/Surrounddings/apache-tomcat-8.5.45/webapps/manager] has finished in [24] ms
执行了...
Account{username='yy', password='1231a', money=100.0}User{uname='yy', age=19}
解决 POST 请求 中文乱码问题
(GET 请求没有乱码问题)
使用 Spring 提供的过滤器, 在 web.xml 中添加 :
<!--配置解决中文乱码的过滤器-->
<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>
修改步骤 : param.jsp -> domain ( Account.java ) -> paramController.java -> 运行
请求参数绑定集合类型(List, Map 等)
param.jsp
<%--把数据封装Account类中,类中存在list和map的集合 --%>
<br/><H3> <form action="param/saveAccount" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" 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>
domain ( Account.java )
private String username;
private String password;
private Double money;
//private User user;
private List<User> list;
private Map<String,User> map;
... //注释掉 User类及其 setter() getter() 修改 toString()
paramController.java
@RequestMapping(value = "/saveAccount")
public String saveAccount(Account account){
System.out.println("执行了...");
System.out.println(account);
return "success";
}
运行
自定义类型转换器
converter 类型转换总接口.
步骤 :
User 类添加 date 属性 -> param.jsp 表单增加 date 属性 -> ParamController.java 添加 saveUser 方法. -> 结果测试.
问题:表格中日期格式固定, 若不符合报错"HTTP Status 400 – Bad Request " 实现后固定格式是yyyy-MM-dd
解决方法 : 写类 implement Converter - > 配置 springmvc.xml 配置开启自转换.
User 类添加 date 属性
private String uname;
private Integer age;
private Date date;
... setter() getter() toString ...
param.jsp 表单增加 date 属性
<br/><H3>自定义类型转换器</H3>
<form action="param/saveUser" method="post">
用户姓名:<input type="text" name="uname" /><br/>
用户年龄:<input type="text" name="age" /><br/>
用户生日:<input type="text" name="date" /><br/>
<input type="submit" value="提交" />
</form>
ParamController.java 添加 saveUser 方法
/**
* 自定义类型转换器
* @param user
* @return
*/
@RequestMapping("/saveUser")
public String saveUser(User user){
System.out.println("执行了...");
System.out.println(user);
return "success";
}
实现 Converter 类
package com.yydcyy.utils;
import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 把字符串转换日期
*/
public class StringToDateConverter implements Converter<String,Date>{
/**
* String source 传入进来字符串
* @param source
* @return
*/
public Date convert(String source) {
// 判断
if(source == null){
throw new RuntimeException("请您传入数据");
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
// 把字符串转换日期
return df.parse(source);
} catch (Exception e) {
throw new RuntimeException("数据类型转换出现错误");
}
}
}
千奇百怪的错误
复制一遍就好了. 网上说空格, 字符集(gbk , utf-8 原因啥的)
结果测试:
获取原生 Servlet 的 API
步骤 :
param.jsp -> ParamController.java -> 运行
param.jsp
<br/><H3>Servlet原生的API</H3>
<a href="param/testServlet">Servlet原生的API</a>
ParamController.java
/**
* 原生的API
* @return
*/
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response){
System.out.println("执行了...");
System.out.println(request);
HttpSession session = request.getSession();
System.out.println(session); //打印 Session ,证明获取了 session. 可以随便用
ServletContext servletContext = session.getServletContext(); //作用域最大
System.out.println(servletContext);
System.out.println(response);
return "success";
}
运行
3 常用注解
1 RequestParam 注解
步骤
anno.jsp ->( com.yydcyy.controller ) AnnoController.java
anno.jsp
<a href="anno/testRequestParam?name=哈哈">RequestParam</a>
AnnoController.java
@Controller
@RequestMapping(value="anno")
public class AnnoController {
@RequestMapping("/testRequestParam")
public String testRequestParam(@RequestParam(name="name") String username){
System.out.println("执行了...");
System.out.println(username);
return "success";
}
}
@Controller 注解别忘了, 否则 404 (注解配置,页面找不到目录)
@RequestParam 作用 : 之前学过, jsp 中?后的参数"name"必须和testRequestParam方法参数 String name 命名一样, 不一样就出错. 通过起别名, 解决这个名字不一样问题
2 RequestBody 注解
GET 方式提交的Body 方法体. (POST 方法没有方法体)
Demo步骤 :
anno.jsp -> AnnoController.java
anno.jsp
<br/><h3>@RequestBody Demo</h3>
<form action="anno/testRequestBody" method="post">
用户姓名:<input type="text" name="username" /><br/>
用户年龄:<input type="text" name="age" /><br/>
<input type="submit" value="提交" />
</form>
AnnoController.java
/**
* 获取到请求体的内容
* @return
*/
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String body){
System.out.println("执行了...");
System.out.println(body);
return "success";
}
结果 :
这是目前最好的存储方式,转为%E5%存储中文
3 PathVariable 注解
Demo步骤 :
anno.jsp -> AnnoController.java
anno.jsp
<a href="anno/testPathVariable/10">testPathVariable</a>
AnnoController.java
/**
* PathVariable注解
* @return
*/
@RequestMapping(value="/testPathVariable/{sid}")
public String testPathVariable(@PathVariable(name="sid") String id){
System.out.println("执行了...");
System.out.println(id);
return "success";
}
这个 sid 相当于占位符.
结果 :
这里有个注解传参 restful 风格. (风格就是用了好, 不用没强制性)
4 HiddentHttpMethodFilter过滤器
通过过滤器,模拟提交方式, put / get / …
WebClient 使用静态方法发送请求, 模拟各种请求方式. 见文档说明
5 RequestHeader注解Demo
步骤 anno.jsp -> AnnoController.java 增加对应内容
<br/><h3>@RequestHeader Demo</h3>
<a href="anno/testRequestHeader">RequestHeader</a>
/**
* 获取请求头的值
* @param header
* @return
*/
@RequestMapping(value="/testRequestHeader")
public String testRequestHeader(@RequestHeader(value="Accept") String header) throws IOException {
System.out.println("执行了...");
System.out.println(header);
return "success";
}
结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-efVeohbq-1570196845209)(https://tva1.sinaimg.cn/large/006y8mN6ly1g7mi6b65oej30r00osach.jpg)]
6 CookieValue注解
B - S 对应 cookie (JSECOOKIE) - Session
步骤 :
anno.jsp -> AnnoController.java 增加对应内容
<br/><h3> CookieValue注解 Demo</h3>
<a href="anno/testCookieValue">CookieValue</a>
/**
* 获取Cookie的值
* @return
*/
@RequestMapping(value="/testCookieValue")
public String testCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
System.out.println("执行了...");
System.out.println(cookieValue);
return "success";
}
结果 Demo
7 ModelAttribute注解
数据不完整时, 优先执行(从库中查数据补全.) 两种实现方式 ①通过 return 返回值方式. ② 通过存储 Map 中, 然后取出
①步骤 :
anno.jsp -> AnnoController.java 增加对应内容
<br/><h3> ModelAttribute Demo</h3>
<form action="anno/testModelAttribute" method="post">
用户姓名:<input type="text" name="uname" /><br/>
用户年龄:<input type="text" name="age" /><br/>
<input type="submit" value="提交" />
</form>
/**
* ModelAttribute注解
* @return
*/
@RequestMapping(value="/testModelAttribute")
public String testModelAttribute( User user){
System.out.println("testModelAttribute执行了...");
System.out.println(user);
return "success";
}
@ModelAttribute
public User showUser(String uname,Integer age){
System.out.println("showUser执行了...");
// 通过用户查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(20);
user.setDate(new Date());
return user;
}
结果 Demo
②无返回值 , 存 Map 方式步骤 :
anno.jsp -> AnnoController.java 增加对应内容
同上
/**
* ModelAttribute注解
* @return
*/
@RequestMapping(value="/testModelAttribute")
public String testModelAttribute(@ModelAttribute("我是token") User user){
System.out.println("testModelAttribute执行了...");
System.out.println(user);
return "success";
}
@ModelAttribute
public void showUser(String uname, Map<String, User> map){
//Map<别名 String, 对象 User>
System.out.println("showUser执行了...return void, 存入 Map 方式");
// 通过用户查询数据库(模拟)
User user = new User();
user.setUname(uname);
user.setAge(20);
user.setDate(new Date());
map.put("我是token",user);
}
结果 Demo
sout 输出说明执行方法没错. 但设的 age=20 没用? 自动只注如 null 数据?奇怪, 一会补充说明
8 SessionAttributes注解
通过 interface Model 降低获取Request 的耦合
步骤
anno.jsp -> AnnoController.java 增加对应内容结果Demo
<br/><h3>testSessionAttributes</h3>
<a href="anno/testSessionAttributes">testSessionAttributes</a>
<br/><h3>getSessionAttributes</h3>
<a href="anno/getSessionAttributes">getSessionAttributes</a>
<br/><h3>delSessionAttributes</h3>
<a href="anno/delSessionAttributes">delSessionAttributes</a>
/**
* SessionAttributes的注解
* @return
*/
@RequestMapping(value="/testSessionAttributes")
public String testSessionAttributes(Model model){
System.out.println("testSessionAttributes...");
// 底层会存储到request域对象中
model.addAttribute("msgFlag","狭路相逢勇者胜");
return "success";
}
/**
* 获取值
* @param modelMap
* @return
*/
@RequestMapping(value="/getSessionAttributes")
public String getSessionAttributes(ModelMap modelMap){
System.out.println("getSessionAttributes...");
String msg = (String) modelMap.get("msgFlag");
System.out.println(msg);
return "success";
}
/**
* 清除
* @param status
* @return
*/
@RequestMapping(value="/delSessionAttributes")
public String delSessionAttributes(SessionStatus status){
System.out.println("delSessionAttributes...");
status.setComplete();
return "success";
}
三个方法 分别对应1 set Attribute /2 获取 / 3 删除
结果 Demo
点击步骤 : 1 -> 2 (返回) ->3(返回) -> 2
1
-> 2 (返回)
->3(返回)
delete 后更不用说了, 肯定没有.
-> 2
哪里出问题了呐. ===> 少了注解!
@Controller
@RequestMapping(value="anno")
@SessionAttributes(value={"msgFlag"}) // 把 msgFlag 存入到session域对中
public class AnnoController {
重启 Tomcat , 再来
出来了
ok, 又学了一个存 RequestScope 方法. 是不是很酷. 大家加油!