SpringMVC简介
- SpringMVC技术与Servlet技术功能等同,均属于web层开发技术
SpringMVC概述
-
SpringMVC是一种基于Java实现MVC模型的轻量级Web框架(表现层)
-
优点
-
使用简单,开发便捷(相比于Servlet)
//Servlet方式 @webServlet("/user/save") public class UserSaveServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException { String name = req.getParameter("name"); System.out.println("servlet save name ==>" + name); resp.setContentType("text/json;charset=utf-8"); Printwriter pw = resp.getwriter(); pw.write( "{'module':'servlet save'}"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOEXception { this.doGet(req,resp); } }
//SpringMVC方式 @Controller public class UserController{ @RequestMapping("/save") @ResponseBody public String save(String name){ System.out.println("springmvc save name ==>" + name); return "{'module':'springmvc save'}"; } }
-
灵活性强
-
入门案列
- 目录结构
-
使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标(在pom.xml中)
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.10.RELEASE</version> </dependency>
-
创建springMVC控制器类(等同于servlet功能)
//定义bean @Controller public class UserController { //定义访问路径 @RequestMapping("/save") //设置当前操作的返回值类型 @ResponseBody public String save() { return "{'module':'springmvc'}"; } }
-
初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
//创建SpringMvc的配置文件,加载controller对应的bean @Configuration @ComponentScan("com.jihua.controller") public class SpringMvcConfig { }
-
初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
//定义一个servlet容器启动的配置类,在里面加载spring的配置 @Configuration public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer { //记载SpringMvc容器配置 @Override protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; } //设置哪些请求归属SpringMvc处理 @Override protected String[] getServletMappings() { //设置所有请求 return new String[]{"/"}; } //加载Spring容器配置 @Override protected WebApplicationContext createRootApplicationContext() { return null; } }
快速入门用到的注解
-
名称:@Controller
-
类型:类注解
-
位置: SpringMVC控制器类定义上方
-
作用:设定SpringMVC的核心控制器bean
-
范例:
@Controller public class UserController { }
-
名称:@RequestMapping
-
类型:方法注解
-
位置: SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法请求访问路径
-
范例:
@RequestMapping("/save") public void save(){ System.out.println("user save ..."); }
-
相关属性
- value(默认)︰请求访问路径
-
名称:@ResponseBody
-
类型:方法注解
-
位置: SpringMNVC控制器方法定义上方
-
作用:设置当前控制器方法响应内容为当前返回值,无需解析
-
范例:
@RequestMapping("/save") @ResponseBody public string save(){ System.out.println("user save ..." ); return "{'info':'springmvc'}"; }
SpringMVC入门程序开发总结(1+N)
- 一次性工作
- 创建工程,设置服务器,加载工程
- 导入坐标
- 创建web容器启动类,加载SpringMVC配置,并设置SpringMVc请求拦截路径
- SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器bean)
- 多次工作
- 定义处理请求的控制器类
- 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
-
AbstractDispatcherServletInitializer类是SpringWVc提供的快速初始化web3.0容器的抽象类
-
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
-
createServletApplicationContext()方法,创建Servlet容器时,加载SpringWVC对应的bean并放入
WebApplicationContext对象范围中,而MebApplicationContext的作用范围为ServletContext范围,即整个web容器范围protected WebApplicationcontext createServletApplicationContext() { AnnotationconfigwebApplicationContext ctx = new AnnotationConfigwebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; }
-
getServletMappings()方法,设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理
protected string[] getservletMappings() { return new String[]{"/"}; }
-
createRootApplicationContext()方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationcontext()
protected webApplicationContext createRootApplicationContext() { return null; }
-
- 启动服务器初始化过程
- 服务器启动,执行ServletcontainersInitConfig类,初始化web容器
- 执行createServletApplicationcontext方法,创建了webApplicationContext对象
- 加载SpringMvcConfig
- 执行@Componentscan加载对应的bean
- 加载UserController,每个@RequestMapping的名称对应一个具体的方法
- 执行getServletMappings方法,定义所有的请求都通过SpringMVC
Controller加载控制与业务bean加载控制
- SpringMVC相关bean(表现层bean)
- Spring控制的bean
- 业务bean (service)
- 功能bean (DataSource等)
因为功能不同,要避免spring错误的加载到SpringMVC的bean
加载spring控制的bean的时候排除掉springMVC控制的bean
-
SpringMVC相关bean加载控制
- SpringMVc加载的bean对应的包均在com.jihua.controller包内
-
Spring相关bean加载控制
- 方式一: Spring加载的bean设定扫描范围为com.jihua,排除掉controller包内的bean
- 方式二:Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等
- 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中
-
名称: @ComponentScan
-
类型:类注解
-
范例:
@Configuration @ComponentScan(value ="com.jihua", excludeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = Controller.class ) ) public class SpringConfig { }
-
属性
- excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)与具体项(classes)
- includeFilters:加载指定的bean,需要指定类别(type)与具体项(classes)
-
bean的加载格式
public class ServletcontainersInitConfig extends AbstractDispatcherServletInitializer { protected webApplicationcontext createServletApplicationcontext() { AnnotationconfigwebApplicationContext ctx = new AnnotationConfigwebApplicationContext();ctx.register(SpringMvcConfig.class); return ctx; } protected webApplicationcontext createRootApplicationcontext(){ AnnotationConfigwebApplicationContext ctx = new AnnotationConfigwebApplicationContext();ctx.register(SpringConfig.class); return ctx; } protected string[] getServletMappings(){ return new String[]{"/"}; } }
-
简化形式
@Configuration public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvcConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }
PostMan
PostMan简介
- Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件
- 作用:常用于进行接口测试
- 特征
- 简单
- 实用
- 美观
- 大方
请求与响应
请求映射路径
-
名称:@RequestMapping
-
类型:方法注解 类注解
-
位置: SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
-
范例:
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/save") @ResponseBody public String save()i System.out.println("user save ..."); return "{'module':'user save'}"; } } //此时可以访问路径.../user/save
-
属性
- value(默认)︰请求访问路径,或访问路径前缀
请求方式
Get请求
-
Get请求传参
-
普通参数: url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
http://localhost/book/commonParam?name=jihua&age=20
@RequestMapping("/commonParam") @ResponseBody public String commonParam(String name, int age){ System.out.println("普通参数传递name ==> "+name ); System.out.println("普通参数传递age ==> "+age); return "{'module':'common param'}"; }
-
Post请求
-
Post请求参数
-
普通参数: form表单post请求传参,表单参数名与形参变量名相同,定义形参即可接收参数
http://localhost/book/commonParam
@RequestMapping("/commonParam") @ResponseBody public String commonParam(String name, int age){ System.out.println("普通参数传递name ==> "+name ); System.out.println("普通参数传递age ==> "+age); return "{'module':'common param'}"; }
-
解决中文乱码问题
-
在servlet容器启动的配置类中添加
//处理中文字符乱码 @Override protected Filter[] getServletFilters() { //方法一 //CharacterEncodingFilter filter = new CharacterEncodingFilter("UTF-8"); //方法二 CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("UTF-8"); return new Filter[]{filter}; }
-
这个写法只对post请求的中文有用
常见的几种请求参数
普通参数
-
普通参数: form表单post请求传参,表单参数名与形参变量名相同,定义形参即可接收参数
http://localhost/book/commonParam?name=jihua&age=20
@RequestMapping("/commonParam") @ResponseBody public String commonParam(String name, int age){ System.out.println("普通参数传递name ==> "+name ); System.out.println("普通参数传递age ==> "+age); return "{'module':'common param'}"; }
-
普通参数: form表单post请求传参,表单参数名与形参变量名不同,使用@RequestParam绑定参数关系
http://localhost/book/commonParam?name=jihua&age=20
@RequestMapping("/commonParam") @ResponseBody public String commonParam(@RequestParam("name")String userName, int age){ System.out.println("普通参数传递name ==> "+userName ); System.out.println("普通参数传递age ==> "+age); return "{'module':'common param'}"; }
-
名称:@RequestParam
-
类型:形参注解
-
位置: SpringMVC控制器方法形参定义前面
-
作用:绑定请求参数与处理器方法形参间的关系
-
范例:
@RequestMapping("/commonParamDifferentName") @ResponseBody public string commonParamDifferentName(@RequestParam("name" )String userName , int age){ System.out.println("普通参数传递userName ==> " + userName); System.out.println("普通参数传递age ==> " + age); return "{'module':'common param different name'}"; }
-
参数:
- required:是否为必传参数
- defaultValue:参数默认值
POJO参数
-
POJO参数:请求参数名与形参对象属性名相同,定义PO30类型形参即可接收参数
http://localhost/book/pojoParam?name=jihua&age=20
public class User { private String name; private int age; //此处省略get,set和toString方法 }
@RequestMapping("/pojoParam") @ResponseBody public string pojoParam(User user){ System.out.println( "pojo参数传递user ==> "+user); return "{'module':'pojo param'}"; }
-
嵌套POJO参数:POJO对象中包含POJO对象
public class User { private String name; private int age; private Address address; //此处省略get,set和toString方法 }
public class Address { private String province; private String city; //此处省略get,set和toString方法 }
-
嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
http://localhost/pojoContainPojoParam?name=jihua&age=15&address.province=sichuan&address.city=chengdu
数组参数
-
数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数
http://localhost/arrayParam?likes=sing&likes=dance&likes=rap&likes=basketball
@RequestMapping("/arrayParam") @ResponseBody public String arrayParam(String[] likes){ System.out.println("数组参数传递likes ==> " + Arrays.toString(likes)); return "{'module':'array param'}"; }
集合参数
-
集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
http://localhost/arrayParam?likes=sing&likes=dance&likes=rap&likes=basketball
@RequestMapping("/listParam") @ResponseBody public String listParam(@RequestParam List<String> likes){ System.out.println("集合参数传递likes ==> " + likes); return "{'module':'list param'}"; }
-
总结就是名称一样自动匹配
-
匹配不上的加
@RequestParam
json传参
-
添加json数据转换相关坐标
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency>
-
设置发送json数据(请求body中添加json数据)
-
开启自动转换json数据的支持
@Configuration @ComponentScan("com.jihua.controller") //开启json @EnableWebMvc public class SpringMvcConfig { }
- @EnablewebMvc注解功能强大,该注解整合了多个功能,对json数据进行自动类型转换只是其一
-
设置接收json数据
@RequestMapping("/listParamForJson") @ResponseBody public String listParam(@RequestBody List<String> likes){ System.out.println("集合参数传递likes ==> " + likes); return "{'module':'list param'}"; }
-
名称:@EnablewebMvc
-
类型:配置类注解
-
位置: SpringMVC配置类定义上方
-
作用:开启SpringMVC多项辅助功能
-
范例:
@Configuration @ComponentScan("com.jihua.controller") @EnablewebMvc public class SpringMvcConfig { }
-
名称:@RequestBody
-
类型:形参注解
-
位置:SpringMVC控制器方法形参定义前面
-
作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
-
范例:
@RequestMapping("/listParamForson") @ResponseBody public string listParamForJson(@RequestBody List<string> likes){ System.out.println("list common(json)参数传递list ==> "+likes); return "{'module':'list common for json param'}"; }
@RequestBody与@RequestParam区别
- 区别
- @RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
- @RequestBody用于接收json数据【application/json】
- 应用
- 发送json格式数据为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@RequestParam接收请求参数
日期类型参数传递
-
日期类型数据基于系统不同格式也不尽相同
- 2088-08-18
- 2088/08/18
- 08/18/2088
-
接收形参时,根据不同的日期格式设置不同的接收方式
@RequestMapping("/dataParam") @ResponseBody public String dataParam(Date date, @DateTimeFormat(pattern = "yyyy-MM-dd" ) Date date1, @DateTimeFormat(pattern = "yyyy/MM/ dd HH:mm: ss" )Date date2){ System.out.println("参数传递date ==> " + date); System.out.println("参数传递date(yyyy-MM-dd) ==> " + date1); System.out.println("参数传递date(yyyy/MM/dd HH :mm:ss) ==> " + date2); return "{'module':'data param'}"; }
http://localhost/dataParam?date=2088/08/08&date1=2088-08-18&date2=2088/08/28 8:08:08
-
名称: @DateTimeFormat
-
类型:形参注解
-
位置: SpringMVC控制器方法形参前面
-
作用:设定日期时间型数据格式
-
范例:
@RequestMapping("/dataParam") @ResponseBody public string dataParam(Date date){ System.out.println("参数传递date ==> "+date); return "{'module':'data param'}"; }
-
属性:
- pattern:日期时间格式字符串
类型转换器(了解)
-
Converter接口
public interface Converter<S, T> { @Nullable T convert(S var1); }
- 请求参数年龄数据(String-→Integer)
- 日期格式转换(String - Date)
-
@EnablewebMvc功能之一:根据类型匹配对应的类型转换器
响应
- 响应页面(了解)
@RequestMapping("/toPage")
public String toPage(){
return "page.jsp";
}
- 响应文本数据(了解)
@RequestMapping("/toText")
@ResponseBody
public String toText(){
return "response text";
}
- 响应json数据(对象转json)
@RequestMapping( "/toJsonPOJ0")
@ResponseBody
public User toJsonPOJO(){
User user = new User();
user.setName("赵云");
user.setAge(41);
return user;
}
- 响应json数据(对象集合转json数组)
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
User user1 = new User();
user1.setName("赵云");
user1.setAge(41);
User user2 = new User();
user2.setName( "master赵云");
user2.setAge(40);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
return userList;
}
-
名称:@ResponseBody
-
类型:方法注解
-
位置: SpringMVC控制器方法定义上方
-
作用:设置当前控制器返回值作为响应体,若返回POJO对象,会自动转为JSON(调用HttpMessageConverter接口)
-
范例:
@RequestMapping("/save") @ResponseBody public String save(){ system.out.println("save.. . "); return "{'info':'springmvc'}"; }
-
HttpMessageConverter类型转换器接口(了解)
public interface HttpMessageConverter<T> { boolean canRead(class<?> clazz, @Nullable MediaType mediaType); boolean canMrite(class<?> clazz. @Nullable MediaType mediaType); List<MediaType> getsupportedMediaTypes(); T read(class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException,HttpMessageNotReadableException; void write(T t, @Nullable MediaType contentType, HttpoutputMessage outputNessage) throws IOException,HttpMessageNotwritableException; }
REST风格
REST简介
-
REST (Representational State Transfer),表现形式状态转换
-
传统风格资源描述形式
http://localhost/user/getById?id=1
http://localhost/user/saveUser
-
REST风格描述形式
http://localhost/user/1
http://localhost/user
-
-
优点:
- 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
- 书写简化
-
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
-
查询全部用户信息 GET(查询)
http://localhost/users
-
查询指定用户信息 GET(查询)
http://localhost/users/1
-
添加用户信息 POST(新增/保存)
http://localhost/users
-
修改用户信息 PUT(修改/更新)
http://localhost/users
-
删除用户信息 DELETE(删除)
http://localhost/users/1
-
-
根据REST风格对资源进行访问称为RESTful
-
上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
-
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、account…
入门案例
-
设定http请求动作(动词)
@RequestMapping(value ="/users", method = RequestMethod.POST) @ResponseBody public String save(@RequestBody User user) { System.out.println("user save... " + user); return "{'module':'user save'}"; } @RequestMapping(value ="/users", method = RequestMethod.PUT) @ResponseBody public String update(@RequestBody User user){ system.out.println( "user update... " + user); return "{'module':'user update'}"; }
-
设定请求参数((路径变量)
@RequestMapping(value ="/users/{id}", method = RequestMethod.DELETE) @ResponseBody public String delete(@PathVariable Integer id){ System.out.println("user delete... " + id); return "{'module':'user delete'}"; }
-
名称:@RequestMapping
-
类型:方法注解
-
位置: SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法请求访问路径
-
范例:
@RequestMapping(value = "/users", method = RequestMethod.POST) @ResponseBody public String save(@RequestBody User user){ system.out.print1n( "user save..." + user); return "{'module':'user save'}"; }
-
属性
- value(默认)︰请求访问路径
- method: http请求动作,标准动作(GET /POST/PUT/DELETE)
@RequestBody @RequestParam @PathVariable
-
区别
-
@RequestParam用于接收url地址传参或表单传参
-
@RequestBody用于接收json数据
-
@PathVariable用于接收路径参数,使用{参数名称}描述路径参数
-
-
应用
- 后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@RequestParam接收请求参数
- 采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值
RESTful快速开发
-
名称:@RestController
-
类型:类注解
-
位置:基于SpringMVC的RESTful开发控制器类定义上方
-
作用:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
-
范例:
@RestController public class BookController { }
-
名称: @GetMapping@PostMapping@PutMapping@DeleteMapping
-
类型:方法注解
-
位置:基于SpringMVC的RESTful开发控制器方法定义上方
-
作用:设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping对应GET请求
-
范例:
@GetMapping("/{id}") public string getById(@PathVariable Integer id){ System.out.println("book getById ... " + id); return "{'module':'book getById'}"; }
-
属性
- value(默认)︰请求访问路径
制作具体页面
-
设置对静态资源的访问放行,否则当访问/pages/xxx时,会提示没有/pages/xxx请求路径
@Configuration public class SpringMvcSupport extends webMvcConfigurationSupport { @Override protected void addResourceHandlers(ResourceHandlerRegistry registry){ //当访问/pages/????时候,走/pages目录下的内容 registry.addResourceHandler("/pages/*").addResourceLocations("/pages/"); registry.addResourceHandler("/js/**") .addResourceLocdtions("/js/"); registry.addResourceHandler("/css/**") .addResourceLocations("/css/"); registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/"); } }
-
前端页面通过异步提交访问后台控制器
//添加 saveBook () { axios.post("/books" ,this.formData).then((res)=>{ ... }); }, //主页列表查询 getAll(){ axios.get("/books").then((res)=>{ this.dataList = res.data; }); },