前言:请先观看SpringMVC——快速入门之后再看此篇文章,方便理解。SpringMVC——快速入门_热爱编程的申同学的博客-CSDN博客SpringMVC的概述及工作原理,开发快速入门https://blog.csdn.net/select_myname/article/details/127542903?spm=1001.2014.3001.5501
目录
3.3、springmvc-servlet.xml配置文件(三种解决方式之一)
3.4、springmvc-servlet.xml配置文件简化方式(三种解决方式之一)
可以在controller控制类方法中获取request和response对象,以及session对象
- @Controller
- @RequestMapping("user")
- //@RestController //相当于@Controller 和 @ResponseBody
- public class UserController {
- @RequestMapping("test1")
- @ResponseStatus(HttpStatus.OK)
- public void test1(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
- System.out.println(request);
- System.out.println(response);
- System.out.println(session);
- }
- }
请求localhost:8080/user/test1.do路径
- @Controller
- @RequestMapping("user")
- //@RestController //相当于@Controller 和 @ResponseBody
- public class UserController {
- @RequestMapping("test2/{id}/{name}")
- public String test2(@PathVariable int id, @PathVariable String name) {
- ModelAndView mv = new ModelAndView();
- mv.addObject("id", id);
- mv.addObject("name", name);
- return "user";
- }
- }
将user页面存放在webapp包下,后缀为jsp文件
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <h1>我是user页面h1>
- ${id}
- ${user}
- body>
- html>
请求路径:localhost:8080/user/test2/12002/zhangsan.do
属性名 | 属性值 |
---|---|
value | 参数名 |
required | true(默认) false |
defultValue | 默认值,如果不给参数值,就走默认值 |
- @Controller
- @RequestMapping("user")
- //@RestController //相当于@Controller 和 @ResponseBody
- public class UserController {
- @RequestMapping("test3")
- @ResponseStatus(HttpStatus.OK)
- public void test3(@RequestParam(value = "id", required = false, defaultValue = "222") int id, @RequestParam("name") String name) {
- System.out.println(id);
- System.out.println(name);
- }
- }
请求路径localhost:8080/user/test3.do?name=itssl,因为id给定了默认值且为不必要参数,所以没有写id参数
- /**
- * 通过后台跳转到cookie视图
- *
- * @return
- */
- @RequestMapping("toCookie")
- public String toCookie() {
- return "cookie";
- }
-
- /**
- * 获取cookie的值
- *
- * @param
- */
- @RequestMapping("test5")
- @ResponseStatus(HttpStatus.OK)
- public void test5(@CookieValue(value = "name", required = false) String name) {
- System.out.println("cookie的值为:" + name);
- }
cookie.jsp页面,首先先请求toCookie到此页面,然后通过页面点击a标签请求test5接口
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <a href="/user/test5.do">测试cookiea>
- body>
- <script>
- document.cookie = "name=jack";
- script>
- html>
点击测试cookie ,idea控制台输出
创建实体类,这里使用lombok依赖进行set/get。
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <version>1.16.18version>
- dependency>
user实体类
- @Data //set/get方法
- @AllArgsConstructor //有参构造
- @NoArgsConstructor //无参构造
- public class User {
- private int id;
- private String name;
- private int age;
- private String address;
- }
书写一个控制类,填写user对象参数,以及request对象用来把user对象放到request域中,让jsp页面进行获取数据。
- @RequestMapping("test6")
- public String test6(User user, HttpServletRequest request) {
- request.setAttribute("user", user);
- return "user";
- }
user.jsp页面
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <h1>我是user页面h1>
- ${user}
- body>
- html>
注意:如果请求路径中没有填写相应的实体类属性,会以各个属性类型的默认值呈现。如:int类型为0,boolean类型为false...
- //跳转到login页面
- @RequestMapping("toUser")
- public String toUser() {
- return "login";
- }
-
- @PostMapping("test8")
- @ResponseStatus(HttpStatus.OK)
- public void test8(@RequestParam("name") String name,
- @RequestParam("age") Integer age,
- @RequestParam("income") Integer income,
- @RequestParam("isMarried") Boolean isMarried,
- @RequestParam("interests") String interests) {
- System.out.println(name);
- System.out.println(age);
- System.out.println(income);
- System.out.println(isMarried);
- System.out.println(interests);
- }
login.jsp页面
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <form action="/user/test8.do" method="post">
- <div>姓名:div>
- <div><input name="name" value="张三"/>div>
- <div class="clear">div>
- <div>年龄:div>
- <div><input name="age" value="20"/>div>
- <div class="clear">div>
- <div>收入:div>
- <div><input name="income" value="100000"/>div>
- <div class="clear">div>
- <div>结婚:div>
- <div>
- <input type="radio" name="isMarried" value="true" checked="checked"/>是
- <input type="radio" name="isMarried" value="false"/>否div>
- <div class="clear">div>
- <div>兴趣:div>
- <div>
- <input type="checkbox" name="interests" value="听歌" checked="checked"/>听歌
- <input type="checkbox" name="interests" value="书法" checked="checked"/>书法
- <input type="checkbox" name="interests" value="看电影" checked="checked"/>看电影
- div>
- <div class="clear">div>
- <div><input type="submit" value="提交表单"/>div>
- form>
- body>
- html>
请求toUser接口跳转到login页面
提交表单,ieda控制台输出
如果上面返回的数据存在乱码的话,那就是post请求乱码,在以往servlet学习中,直接对request对象进行设置utf-8就能解决,那么现在springMVC中如何解决这个问题呢?
需要在web.xml中通过过滤器来进行解决
-
- <filter>
-
- <filter-name>encodingFilterfilter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
- <init-param>
- <param-name>encodingparam-name>
- <param-value>utf-8param-value>
- init-param>
- filter>
-
- <filter-mapping>
- <filter-name>encodingFilterfilter-name>
- <url-pattern>/*url-pattern>
- filter-mapping>
我们发现上面我们写了很多次页面跳转的方法,其实我们可以抽取统一
- @Controller
- @RequestMapping("toPage")
- public class ToPage {
- @RequestMapping("{page}")
- public String toPage1(@PathVariable("page") String page){
- return page;
- }
- }
- @RequestMapping("test9")
- @ResponseStatus(HttpStatus.OK)
- public void test9(String[] addr) {
- for (String s : addr) {
- System.out.println(s);
- }
- }
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>数组title>
- head>
- <body>
- <form action="/user/test9.do" method="post">
- <input type="checkbox" name="addr" value="郑州"> 郑州 <br>
- <input type="checkbox" name="addr" value="上海"> 上海 <br>
- <input type="checkbox" name="addr" value="杭州"> 杭州 <br>
- <input type="checkbox" name="addr" value="北京"> 北京 <br>
- <input type="checkbox" name="addr" value="曹县"> 曹县 <br>
- <input type="submit" value="数组类型">
- form>
- body>
- html>
先通过通用页面跳转接口跳转到address.jsp页面
选择上海和北京提交
实体类中拥有很多类型,数组、包装类、Map、List等这种复杂实体类如何接收呢?
- @Data
- public class UserVO {
- private String name;
- private Integer age;
- private User user;
- private List
list; - private Map
map; - private String[] addr;
- }
控制类代码
- @RequestMapping("test10")
- @ResponseStatus(HttpStatus.OK)
- public void test10(UserVO userVO) {
- System.out.println(userVO);
- }
list.jsp页面
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <form action="/user/test10.do" method="post">
- 姓名: <input type="text" name="name">
- 年龄: <input type="text" name="age"> <br/>
- user属性中的姓名:<input type="text" name="user.name"><br/>
- user属性中的年龄:<input type="text" name="user.age"> <br/>
- list中第一个user对象的年龄:<input type="text" name="list[0].age"> <br/>
- list中第一个user对象的姓名:<input type="text" name="list[0].name"> <br/>
- list中第二个user对象的年龄: <input type="text" name="list[1].age"> <br/>
- list中第二个user对象的姓名: <input type="text" name="list[1].name"> <br/>
- map中第一个键值对中值user对象的年龄: <input type="text" name="map['one'].age"> <br/>
- map中第一个键值对中值user对象的姓名: <input type="text" name="map['one'].name"> <br/>
- map中第二个键值对中值user对象的年龄: <input type="text" name="map['two'].age"> <br/>
- map中第二个键值对中值user对象的姓名: <input type="text" name="map['two'].name"><br/>
-
- 请选择喜欢的城市:
- <input type="checkbox" name="addr" value="郑州"> 郑州 <br>
- <input type="checkbox" name="addr" value="上海"> 上海 <br>
- <input type="checkbox" name="addr" value="杭州"> 杭州 <br>
- <input type="checkbox" name="addr" value="北京"> 北京 <br>
- <input type="checkbox" name="addr" value="曹县"> 曹县 <br>
-
- <input type="submit" value="复杂类型">
- form>
- body>
- html>
使用jstl核心标签库需要导入依赖坐标
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>jstlartifactId>
- <version>1.2version>
- dependency>
- @GetMapping("test11")
- public ModelAndView test11(ModelAndView mv) {
- List
list=new ArrayList<>(); - User user = new User();
- user.setId(1);
- user.setName("张三");
- user.setAge(23);
- user.setAddress("郑州");
-
- User user1 = new User();
- user1.setId(2);
- user1.setName("李四");
- user1.setAge(22);
- user1.setAddress("上海");
-
- User user2=new User();
- user2.setId(3);
- user2.setName("王五");
- user2.setAge(24);
- user2.setAddress("杭州");
-
- list.add(user);
- list.add(user1);
- list.add(user2);
- mv.addObject("list",list);
- mv.setViewName("list2");
- return mv;
- }
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
-
- <table border="1px" cellpadding="8px" cellspacing="0px" width="80%">
- <thead>
- <tr>
- <th>IDth>
- <th>Nameth>
- <th>Ageth>
- <th>Addressth>
- tr>
- thead>
- <tbody>
- <c:forEach items="${list}" var="user">
- <tr>
- <td>${user.id}td>
- <td>${user.name}td>
- <td>${user.age}td>
- <td>${user.address}td>
- tr>
- c:forEach>
- tbody>
- table>
- body>
- html>
在之前我们讲的请求响应都是同步的,但是在实际开发中我们都是使用异步请求,所以下面我们使用ajax发送异步请求!
在异步请求中数据传输的格式我们都是使用josn来进行传输,速度快,小巧,使用方便!!
在响应的同时,我们也是响应json字符串,在前端解析json字符串即可!
1、发送ajax请求:$.ajax() / $.get() / $.post() / $.load()
2、响应json数据:new ObjectMapper().writeValueAsString()
我们学习完SpringMVC之后,就不用像之前那么麻烦了,还要创建ObjectMapper对象来转换成josn数据进行响应。
SpringMVC已经帮我们做这些事情了。SpringMVC提供了两个注解@RequestBody和@ResponseBody实现josn数据的转换
用于将controller方法返回的对象通过转换器转换为指定的格式(通常为json)之后,写入到response对象的响应体中。
把js文件放到webapp包下的js文件夹中,下面链接即为jquery-3.4.1的文件
链接:https://pan.baidu.com/s/1IFfhWAQs023LK-_9eu0tPw
提取码:ppdf
创建一个html页面,发送ajax异步请求,请求控制类获取数据
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <table border="1" id="table" cellspacing="0px" cellpadding="20px">
- <tr>
- <td>nametd>
- <td>agetd>
- tr>
- table>
- body>
- <script src="js/jquery-3.4.1.js">script>
- <script>
- $.ajax({
- url: 'user/ajaxResponse.do',
- type: 'post',
- dataType: 'json',
- success: function (data) {
- var str = '';
-
- $(data).each(function (i) {
- str += `
-
${data.name} -
${data.age} -
`; - });
- $("#table").append(str);
- }
- })
- script>
- html>
控制类
- @PostMapping("ajaxResponse")
- @ResponseBody
- public User ajaxTest(){
- User user = new User();
- user.setName("jack");
- user.setAge(99);
- return user;
- }
用于接收前端请求体中的json数据,使用@RequestBody注解就可以自动的封装指定的对象中
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Titletitle>
- <script src="js/jquery-3.4.1.js">script>
- head>
- <body>
- <script>
- $(function () {
- $.ajax({
- url: '/user/ajaxRequest.do',
- type: 'POST',
- data: '{"name":"jack","age":99}',
- contentType:'application/json;charset=utf-8',
- success: function (data) {
-
- }
- });
- });
- script>
- body>
- html>
- /**
- * 接受json串
- * @param user
- */
- @PostMapping("ajaxRequest")
- public void test(@RequestBody User user){
- //User(name=jack, age=99)
- System.out.println(user);
- }
SpringMVC在默认情况下,所有的静态资源都会被拦截(js,css。html,图片、视频、音频),在web.xml文件中,我们配置的拦截路径是/
这种形式除了jsp都会被拦截。
- <servlet-mapping>
- <servlet-name>springmvcservlet-name>
-
- <url-pattern>/url-pattern>
- servlet-mapping>
把拦截路径设置为 / 时,会发现连html静态页面都无法访问
对于静态资源,需要手动配置静态资源过滤。有三种形式可以选择:
- <servlet-mapping>
- <servlet-name>springmvcservlet-name>
-
- <url-pattern>/url-pattern>
- servlet-mapping>
-
- <servlet-mapping>
- <servlet-name>defaultservlet-name>
- <url-pattern>*.jpgurl-pattern>
- servlet-mapping>
- <servlet-mapping>
- <servlet-name>defaultservlet-name>
- <url-pattern>*.jsurl-pattern>
- servlet-mapping>
- <servlet-mapping>
- <servlet-name>defaultservlet-name>
- <url-pattern>*.cssurl-pattern>
- servlet-mapping>
- <servlet-mapping>
- <servlet-name>defaultservlet-name>
- <url-pattern>*.htmlurl-pattern>
- servlet-mapping>
- <mvc:resources mapping="/html/**" location="/html/"/>
- <mvc:resources mapping="/img/**" location="/img/" />
- <mvc:resources mapping="/js/**" location="/js/" />
- <mvc:resources mapping="/css/**" location="/css/"/>
- <mvc:default-servlet-handler/>
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。
preHandle | 执行目标方法之前进行拦截; true 放行 false 拦截不放行 |
postHandle | 在目标方法执行之后,进行增强 |
afterCompletion | 在视图渲染完毕后,进行资源释放 |
自定义拦截器:使用自定义拦截器,SpringMVC提供了 HandlerInterceptor 接口。我们重写 preHandle
、postHandle
、afterCompletion
这三个方法!
创建一个interceptor包,在包中创建一个类去实现拦截器接口HandlerInterceptor
- public class MyInterceptor implements HandlerInterceptor {
- //方法执行之前进行拦截
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("执行方法前进行拦截1111111111");
- //放行
- return true;
- }
- //方法执行之后,进行增强
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("目标方法执行之后,进行增强1111111111");
- }
- //视图渲染完毕后,进行资源释放
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("在视图渲染完毕后,进行资源释放11111111111");
- }
- }
配置springmvc-config.xml文件
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
-
-
- <context:component-scan base-package="cn.itssl.*"/>
- <mvc:annotation-driven/>
-
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**"/>
-
- <bean class="cn.itssl.interceptor.MyInterceptor"/>
- mvc:interceptor>
- mvc:interceptors>
-
-
- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/upload/show1.do"/>
-
- <bean class="cn.itssl.interceptor.MyInterceptor"/>
- mvc:interceptor>
- mvc:interceptors>
-
-
-
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**"/>
-
-
-
-
- <bean class="cn.itssl.interceptor.MyInterceptor"/>
- mvc:interceptor>
- mvc:interceptors>
-
-
-
- beans>
多个拦截器,拦截同一个目标资源,形成一个链条,就是拦截器链!
拦截方法的执行顺序:先进先出
拦截器的执行顺序
跟springmvc配置文件中的配置顺序有关系
mvc:interceptor 谁先配置谁先执行!
再创建一个类实现拦截器接口
- public class MyInterceptor2 implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("执行方法前进行拦截22222222222");
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("目标方法执行之后,进行增强22222222");
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("在视图渲染完毕后,进行资源释放222222222");
- }
- }
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**"/>
-
-
- <bean class="cn.itssl.interceptor.MyInterceptor1"/>
- mvc:interceptor>
- mvc:interceptors>
-
-
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**"/>
-
- <bean class="cn.itssl.interceptor.MyInterceptor2"/>
- mvc:interceptor>
- mvc:interceptors>
1、实现Filter接口
2、通过web.xml或注解方式完成配置
3、重写的方法 init doFilter destroy
4、过滤器过滤的是所有请求,不分controller和页面
1、实现HandlerInterceptor接口
2、需要在springmvc核心配置文件中配置3、重写的方法
preHandle 调用handler方法之前执行,true表示放行,false表示不放行
postHandle 调用handler方法之后执行
afterCompletion 视图渲染之后执行
4、只拦截controller请求
REST(英文:Representational State Transfer,简称REST,意思:表述性状态转换,描述了一个架构样式的网络系统,比如web应用)。
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
应用场景:前后端分离开发的架构中
传统url
请求路径处理名字 表明 是做什么操作
请求路径时 也告 请求方式 (addUser + post) (deleteUserById + delete)
前端 | 后台 | 描述 |
---|---|---|
http://localhost:8080/user/findAllUsers | @RequestMapping(/user/findAllUsers) public List | 查询所有用户 |
http://localhost:8080/user/findUserById?id=1 | @RequestMapping(/user/findUserById) public User findUserById(int id) | 查询指定用户 |
http://localhost:8080/user/addUser | @RequestMapping(/user/addUser) public void addUser(User user) | 添加用户 |
http://localhost:8080/user/updateUser | @RequestMapping(/user/updateUser) public void updateUser(User user) | 修改用户 |
http://localhost:8080/user/deleteUserById?id=1 | @RequestMapping(/user/deleteUserById) public User deleteUserById(int id) | 删除用户 |
RESTfull风格
Restful风格的请求是使用==“url+请求方式”(名饲+动词)==表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:
请求方式 | 描述 |
---|---|
GET | 用于获取资源 |
POST | 用于新建资源 |
PUT | 用于更新资源 |
DELETE | 用于删除资源 |
前端 | 后台 | 描述 |
---|---|---|
http://localhost:8080/user/ | @RequestMapping(/user,method=GET) public List | GET查询所有用户 |
http://localhost:8080/user/1 | @RequestMapping(/user/{id},method=GET) public User findUserById(@PathVariable int id) | GET查询id为1用户 |
http://localhost:8080/user/ | @RequestMapping(/user,method=POST) public void addUser(User user) | POST添加用户 |
http://localhost:8080/user/1 | @RequestMapping(/user/{id},method=PUT) public void updateUser(@PathVariable int id) | PUT修改id为1用户 |
http://localhost:8080/user/1 | @RequestMapping(/user/{id},method=DELETE) public User deleteUserById(@PathVariable int id) | DELETE删除id为1的用户 |
上述url地址/user/1中的1就是要获得的请求参数,在SpringMVC中可以使用占位符进行参数绑定。RequestMapping中/user/1可以写成/user/{id},占位符{id}对应的就是1的值。在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作。
- @RequestMapping("user")
- @RestController // @Controller + @ResponseBody
- public class RestFulController {
-
- /**
- * 查询所有 get
- */
- @GetMapping("users")
- public String findAll(){
- return "查询所有";
- }
-
- /**
- * 指定查询 get
- * @param id
- * @return
- */
- @GetMapping("users/{id}")
- public String findUserByid(@PathVariable Integer id){
- return "根据id进行查询,id为:"+id;
- }
-
- /**
- * 添加用户 post
- * @return
- */
- @PostMapping("users")
- public String addUser(){
- return "添加用户";
- }
-
- /**
- * 修改用户 put
- * @return
- */
- @PutMapping("users/{id}")
- public String updateUser(@PathVariable Integer id){
- return "修改用户,id为:"+id;
- }
-
- /**
- * 删除用户 delete
- */
- @DeleteMapping("users/{id}")
- public String deleteUserById(@PathVariable("id") Integer id){
- return "删除用户,id为:"+id;
- }
- }