SpringMVC

ssm: MyBatis + Spring + SpringMVC ==MVC 三层架构==

MVC: 模型 (Dao, Service) 视图 (JSP) 控制器 (Servlet)

dao

service

servlet: 转发, 重定向

jsp / html

1、回顾 Servlet

  1. 导入所需依赖:
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
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>

<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>

<dependency>
<groupId>javax.servlet.</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>

</dependencies>
  1. 编写一个 Servlet 类
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
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取前端参数
String method = req.getParameter("method");

if (method.equals("add")) {
req.getSession().setAttribute("msg", "执行了 add 方法");e
}

if (method.equals("delete")) {
req.getSession().setAttribute("msg", "执行了 delete 方法");e
}

//2.调用业务层

//3.重定向
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
return ;
}
}

  1. 编写 Hello.jsp 在 WEB-INF 目录下新建一个 jsp 文件夹, 新建 test.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<%--
Created by IntelliJ IDEA.
User: 雷神
Date: 2021/9/30
Time: 15:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>

${msg}

</body>
</html>

  1. 在 web.xml 中注册 Servlet
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
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.cu1.Servlet.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

<!--<session-config>
&lt;!&ndash;设置等待时间&ndash;&gt;
<session-timeout>15</session-timeout>
</session-config>-->

<!--欢迎页面 默认 index-->
<!--<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>-->

</web-app>
  1. 配置Tomcat 开启启动测试

MVC 框架要做哪些事情

  1. 将 url 映射到 java 类或 java 类方法
  2. 封装用户提交的数据
  3. 处理请求, 调用相关的业务处理 – 封装相应数据
  4. 将相应数据进行渲染 .jsp / html 等表示层数据

SpringMVC 特点:

  1. 轻量级
  2. 高效 基于请求相应的 MVC 框架‘
  3. 与 Spring 兼容性好, 无缝结合
  4. 约定优于配置
  5. 功能强大: RESful 数据验证, 格式化, 本地化, 主题等
  6. 简洁灵活
  7. 使用的人多

2、中心控制器

DispatcherServlet 最上层继承了 Servlet 所以其本质就是 Servlet

​ Spring 的 Web 框架围绕 DispatcherServlet 设计, DispatcherServlet 的作用是将请求分发到不同的处理器

从 Spring2.5 开始 使用 jAVA 5 或以上版本的用户可以采用基于注解的 controller 声明方式

SpringMVC 框架像许多其他 MVC 框架一样, 以请求为驱动, 围绕一个中心 Servlet 分派请求以及提供其他功能 DispatcherServlet 是一个实际的 Servlet (它继承自 HttpServlet 基类)

img

SpringMVC的原理如下图所示

当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。

img

3、Hello, SpringMVC

  1. 新建一个Moudle , springmvc-02-hello , 添加web的支持!

  2. 确定导入了SpringMVC 的依赖

  3. 配置web.xml, 注册DispatcherServlet

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">
    <!--1.注册DispatcherServlet-->
    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!--启动级别-1-->
    <load-on-startup>1</load-on-startup>
    </servlet>
    <!--/ 匹配所有的请求;(不包括.jsp)-->
    <!--/* 匹配所有的请求;(包括.jsp)-->
    <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    </web-app>
  4. 编写SpringMVC 的 配置文件! 名称: springmvc-servlet.xml : [servletname]-servlet.xml

    说明,这里的名称要求是按照官方来的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    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">

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    <!--视图解析器:DispatcherServlet给他的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
    <!--前缀-->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--后缀-->
    <property name="suffix" value=".jsp"/>
    </bean>

    <!--Handler-->
    <bean id="/hello" class="com.cu1.Controller.HelloController"/>

    </beans>
  5. 添加 处理映射器

    1
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
  6. 添加 处理器适配器

    1
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
  7. 添加 视图解析器

    1
    2
    3
    4
    5
    6
    7
    <!--视图解析器:DispatcherServlet给他的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
    <!--前缀-->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--后缀-->
    <property name="suffix" value=".jsp"/>
    </bean>
  8. 编写要操作业务的Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package com.cu1.Controller;

    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    //注意:这里我们先导入Controller接口
    public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    //ModelAndView 模型和视图
    ModelAndView mv = new ModelAndView();
    //封装对象,放在ModelAndView中。Model
    mv.addObject("msg","HelloSpringMVC!");
    //封装要跳转的视图,放在ModelAndView中
    mv.setViewName("hello");
    //: /WEB-INF/jsp/hello.jsp
    return mv;
    }
    }

  9. 将写好的 Controller 类交给SpringIOC容器,注册bean

    1
    <bean id="/hello" class="com.cu1.Controller.HelloController"/>
  10. 写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <%--
    Created by IntelliJ IDEA.
    User: 雷神
    Date: 2021/10/5
    Time: 21:08
    To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>Title</title>
    </head>
    <body>

    ${msg}

    </body>
    </html>

  11. 配置Tomcat 启动测试

可能遇到的问题:访问出现404,排查步骤:

  1. 查看控制台输出,看一下是不是缺少了什么jar包。

  2. 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!

新建一个 lib 文件夹后点第一个 选中所有依赖后点击 Ok 即可

最后重启 Tomcat 即可

4、SpringMVC 执行原理

img

图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现

简要分析执行流程

DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。

我们假设请求的url为 : http://localhost:8080/SpringMVC/hello

如上url拆分成三部分:

http://localhost:8080服务器域名

SpringMVC部署在服务器上的web站点

hello表示控制器

  1. 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。

  2. HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。

  3. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

  5. HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。

  6. Handler让具体的Controller执行。

  7. Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

  8. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。

  9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。

  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet。

  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

  12. 最终视图呈现给用户。

5、SpringMVC 注解

  1. 编写 xml 文件

    web.xml

    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
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0">

    <!--1.注册DispatcherServlet-->
    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!--启动级别-1-->
    <load-on-startup>1</load-on-startup>
    </servlet>
    <!--/ 匹配所有的请求;(不包括.jsp)-->
    <!--/* 匹配所有的请求;(包括.jsp)-->
    <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>

    </web-app>

    Springmvc-servlet.xml

    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
    <?xml version="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">

    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.cu1.controller"/>

    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler/>

    <!-- 支持mvc注解驱动
    在spring中一般采用@RequestMapping注解来完成映射关系
    要想使@RequestMapping注解生效
    必须向上下文中注册DefaultAnnotationHandlerMapping
    和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理。
    而annotation-driven配置帮助我们自动完成上述两个实例的注入。
    -->
    <mvc:annotation-driven />

    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
    <!-- 前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!-- 后缀 -->
    <property name="suffix" value=".jsp"/>
    </bean>

    </beans>
    1. 编写 controller 文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Controller
    //类里面请求路径前都要加 /h
    @RequestMapping("/h")
    public class HelloController {

    //真实访问地址: 项目名/h/hello
    @RequestMapping("/hello")
    public String hello(Model model) {
    //封装数据 向模型中添加属性 msg 与值 可以在 jsp 界面中取出并渲染
    model.addAttribute("msg", "Hello, SpringMVCAnnotation!");
    //会被视图解析器处理
    return "hello";
    }
    }

    • @RequestMapping 注解的功能

    从注解名称上我们可以看到,@RequestMapping 注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。

    SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。

    • @RequestMapping 注解的位置

    @RequestMapping 标识一个类:设置映射请求的请求路径的初始信息

    @RequestMapping 标识一个方法:设置映射请求请求路径的具体信息

    如果一个类上添加了 @RequestMapping 注解 那么就给这个类中所有的映射加上了一个初始 (父) 地址

流程:

  • 首先通过 url 通过映射处理和查找控制器找到注解的相应映射的类中的方法
  • 通过 HandlerAdapter 表示处理器适配器执行找到的方法
  • 将返回值中的视图名传递给 HandlerAdapter 以及在类中封装的数据
  • 显示视图

==说明==

​ 若出现了 500 错误要将 pom.xml 以及 该项目的 JDK版本降至 11

6、RestFul和控制器

控制器Controller

  • 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
  • 控制器负责解析用户的请求并将其转换为一个模型。
  • 在Spring MVC中一个控制器类可以包含多个方法
  • 在Spring MVC中,对于Controller的配置方式有很多种

控制器 Controller 的使用方式有两种

  • 在 3 中使用继承 Controller 并实现方法
  • 使用 Controller 注解 (推荐该使用方式)

说明:

  • 实现接口Controller定义控制器是较老的办法
  • 缺点是:一个控制器中只有一个方法,如果要多个方法则需要定义多个Controller;定义的方式比较麻烦;

**使用注解 @Controller **

  • Controller 注解类型用于声明Spring类的实例是一个控制器(在讲IOC时还提到了另外3个注解);
  • Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。

多个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系。

@RequestMapping

在 5 中进行了描述 此处略过

RestFul 风格

概念

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

资源:互联网所有的事物都可以被抽象为资源

资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。

分别对应 添加、 删除、修改、查询。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Controller
public class RestFulController {

//@RequestMapping("/add/{a}/{b}")
@GetMapping("/add/{a}/{b}")
public String test(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg", "add 结果为:" + res);
return "add";
}

@PostMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
model.addAttribute("msg", "add 结果1为:" + res + 5);
System.out.printf("11111111111");
return "add";
}
}

/{a} 表示取出 add 后参数将其赋值给变量 a @PathVariable 注解为指定这个参数为接收前端传递的相对应的参数

若前端传递的为一个对象

1
2
3
4
5
6
7
8
9
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private int age;

}

这里使用 lombok 要注意使用版本不要过低 此处使用的为 1.18 版本

UserController:

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
@Controller
@RequestMapping("/user")
public class UserController {

//localhost:8080/user/t1?name = ***;
@GetMapping("/t1")
public String test1(@RequestParam("username") String name, Model model) {
//1. 接收前端参数
System.out.println("接收到前端的参数为: " + name);

//2. 将返回的结果传递给前端
model.addAttribute("msg", name);

//3.跳转视图
return "add";
}

//前端接收的是一个对象: id, name, age
/*
* 1. 接收前端用户传递的参数 判断参数的名字 假设名字直接在方法上 可以直接使用
* 2. 假设传递的是一个对象 User 匹配 User 对象中的字段名 如果名字与对象中属性名一致则会接收 否则该属性会接收失败
* */
@GetMapping("/t2")
public String test2(User user) {
System.out.println(user);
return "add";
}
}

若是参数名与前端传递的参数不同, 需要 @RequestParam("username") 来指定接收参数的名字

要跳转的 jsp 页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%--
Created by IntelliJ IDEA.
User: 雷神
Date: 2021/10/7
Time: 15:02
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/SpringMVC_04/add/1/3" method="post">
<input type="submit">
</form>

</body>
</html>

注\: form 表单的路径应写完整 在提交时不会自动补全项目路径

  1. 思考:使用路径变量的好处?
    • 使路径变得更加简洁;
    • 获得参数更加方便,框架会自动进行类型转换。
    • 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/commit/1/a,则路径与方法不匹配,而不会是参数转换失败。

所有的地址栏请求默认都会是 HTTP GET 类型的。

方法级别的注解变体有如下几个:组合注解

1
2
3
4
5
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

关于 Model

image-20211007215256133

Model 本质为一个接口, model 接收的为某一个实现类 此处大但猜测为 ModelMap

ModelMap 实现了除了 Model 必要的功能之外又扩展了更多的功能 但平时使用其实现的 Model 的接口已经够用了 Model 可以理解提供了更简易的功能

7、解决乱码

此处没啥好说的 直接使用 SpringMVC提供的过滤器即可 配置在 web.xml

1
2
3
4
5
6
7
8
9
10
11
12
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

更高级的自定义过滤器可以自行搜索

8、JSON

8.1、什么是JSON?

  • JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广泛。
  • 采用完全独立于编程语言的文本格式来存储和表示数据。
  • 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
  • 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:

  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

JSON 键值对是用来保存 JavaScript 对象的一种方式,和 JavaScript 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:

1
2
3
{"name": "QinJiang"}
{"age": "3"}
{"sex": "男"}

JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。

1
2
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串

8.2、Jackson 的使用

  1. Json 解决乱码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!--json 乱码问题配置-->
    <mvc:annotation-driven>
    <mvc:message-converters>
    <bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <constructor-arg value="utf-8"></constructor-arg>
    </bean>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="objectMapper">
    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
    <property name="failOnEmptyBeans" value="false"></property>
    </bean>
    </property>
    </bean>
    </mvc:message-converters>
    </mvc:annotation-driven>
  2. 导入 Jacksonjar

    1
    2
    3
    4
    5
    6
    7
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.2</version>
    </dependency>

  3. 编写 JsonUtils 工具类

    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
    public class JsonUtils {

    public static String getJson(Object object) {
    return getJson(object, "yyy-MM-dd HH:mm:ss");
    }

    public static String getJson(Object o, String dateFormat) {
    ObjectMapper mapper = new ObjectMapper();

    //使用 ObjectMapper 来解决进行格式化输出 关闭时间戳的形式
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    //自定义日期格式
    SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
    mapper.setDateFormat(sdf);

    String str = null;
    try {
    str = mapper.writeValueAsString(o);
    } catch (JsonProcessingException e) {
    e.printStackTrace();
    }
    return str;
    }
    }

  4. 测试

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    //这个类下所有相应处理都不会走视图解析器 只会返回字符串
    //@RestController
    @Controller
    public class UserController {

    @RequestMapping("/j1")
    @ResponseBody//他不会走视图解析器 会直接返回一个字符串
    public String json1() throws JsonProcessingException {

    //jackson ObejectMapper
    ObjectMapper mapper = new ObjectMapper();

    //创建一个对象
    User user = new User("Cu1", 3, "男");

    String str = mapper.writeValueAsString(user);
    return str;
    }

    //JSON 返回多个对象
    @RequestMapping("/j2")
    @ResponseBody//他不会走视图解析器 会直接返回一个字符串
    public String json2() throws JsonProcessingException {

    ArrayList<User> userList = new ArrayList<>();

    User user = new User("Cu1", 3, "男");
    User user1 = new User("Cu2", 3, "男");
    User user2 = new User("Cu3", 3, "男");

    userList.add(user);
    userList.add(user1);
    userList.add(user2);

    return JsonUtils.getJson(userList);
    }

    //JSON 返回时间对象
    @RequestMapping("/j3")
    @ResponseBody//他不会走视图解析器 会直接返回一个字符串
    public String json3() throws JsonProcessingException {

    //jackson ObejectMapper
    ObjectMapper mapper = new ObjectMapper();

    return JsonUtils.getJson(new Date(), "yyy-MM-dd HH:mm:ss");
    }
    }

    关于 @RestControllerResponseBody

    @ResponseBody: 放在方法上, 返回值不会被视图解析器解析 而是直接将返回值传递给前端

    @RestController 放在类上 即类中所有处理请求的方法返回值都不会被视图解析器解析 而是直接将返回值传递给前端

8.3、fastJson

  1. 导入 fastJsonjar

    1
    2
    3
    4
    5
    6
    <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
    </dependency>
  2. fastJson 三个主要的类:

  • JSONObject 代表 json 对象

    • JSONObject 实现了 Map 接口, 猜想 JSONObject 底层操作是由 Map 实现的

    • JSONObejct 对应 Json 对象 通过各种形式的 get()方法可以获取 json 对象中的数据 也可也利用诸如

      size() , isEmpty() 等方法获取 **“键: 值” **对的个数和判断是否为空 其本质是通过 Map接口并调用接口中的方法完成的

  • JSONArray 代表 json 的数组对象

    • 内部是有 List 接口中的方法来完成操作的
  • JSON 代表 JSONObjcet 和 JSONArray 的转化

    • JSON类源码分析与使用
    • 主要是实现 json 对象, json 数组对象, javabean 对象, json 字符串 之间的互相转化

关于具体使用请参考 fastJson

9、整合 SSM

项目结构

9.1、整合 MyBatis

  1. 建立数据库:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE DATABASE `ssmbuild`;
    USE `ssmbuild`;
    DROP TABLE IF EXISTS `books`;
    CREATE TABLE `books` (
    `bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
    `bookName` VARCHAR(100) NOT NULL COMMENT '书名',
    `bookCounts` INT(11) NOT NULL COMMENT '数量',
    `detail` VARCHAR(200) NOT NULL COMMENT '描述',
    KEY `bookID` (`bookID`)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)
    VALUES (1,'Java',1,'从入门到放弃'),
    (2,'MySQL',10,'从删库到跑路'),
    (3,'Linux',5,'从进门到进牢');
  2. 将 MyBatis 与 Spring 整合

    由于 MyBatis 与 Spring 整合后不需要再配置数据源 只需要设置别名日志 以及注册 Mapper 就可以了

    mybatis-config.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="UTF8"?>
    <!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>

    <!--配置数据源 交给 Spring 去做-->

    <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--注册mapper.xml-->
    <mappers>
    <mapper class="com.cu1.dao.BookMapper"/>
    </mappers>

    </configuration>

    Spring-dao.xml

    ==友情提示:== 千万不要使用 c3p0 数据源 不然你会怀疑人生 Spring 自带的数据源就可以了

    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
    39
    40
    <?xml version="1.0" encoding="UTF8"?>
    <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"
    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">

    <!--1. 关联数据库配置文件-->
    <context:property-placeholder location="classpath:database.properties"/>

    <!--2. 连接池
    dbcp 半自动化操作 不能自动连接
    c3p0 自动化操作(自动化的加载配置文件 并可以自动设置到对象中)
    druidh
    hikari
    -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.pwd}"/>
    </bean>

    <!--3. sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!--绑定 MyBatis 的配置文件-->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <!--配置 dao 接口扫描包 可以动态的实现了 dao 接口可以注入到 Spring 容器中-->
    <!--解释 :https://www.cnblogs.com/jpfss/p/7799806.html-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!--注入 sqlSessionFactory-->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <!--扫描要扫描的 dao 包-->
    <property name="basePackage" value="com.cu1.dao"/>
    </bean>

    </beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface BookMapper {

//增加一本书
int addBook(Books books);

//删除一本书
int deleteBookById(@Param("bookId") int id);

//更新一本书
int updateBook(Books books);

//查询一本书
Books queryBookById(@Param("bookId") int id);

//查询全部的书
List<Books> queryAllBook();

//按照名称查询书籍
Books queryBookByName(String bookName);
}

BookMapper.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--绑定接口-->
<mapper namespace="com.cu1.dao.BookMapper">

<insert id="addBook" parameterType="com.cu1.pojo.Books">
insert into ssmbuild.books (bookName, bookCounts, detail)
values(#{bookName}, #{bookCounts}, #{detail});
</insert>

<delete id="deleteBookById" parameterType="int">
delete from ssmbuild.books where bookID = #{bookId};
</delete>

<update id="updateBook" parameterType="com.cu1.pojo.Books">
update ssmbuild.books
set bookName = #{bookName}, bookCounts = #{bookCounts}, detail = #{detail}
where bookID = #{bookID};
</update>

<select id="queryBookById" resultType="com.cu1.pojo.Books">
select * from ssmbuild.books where bookID = #{bookId};
</select>

<select id="queryAllBook" resultType="com.cu1.pojo.Books">
select * from ssmbuild.books;
</select>

<select id="queryBookByName" resultType="com.cu1.pojo.Books">
select * from ssmbuild.books where bookName = #{bookName};
</select>

</mapper>

设计思想:

​ 首先确定要实现的业务, 以接口的方式给出, 再使用 BookMapper.xml 绑定接口的 SQL 语句, 由于已经使用了包扫描机制 所以这里无需再写出接口的实现类 Spring 将以反射的机制来自动实现实现类

9.2、服务层的搭建

​ 先以接口 BookService 的形式给出 Service 要实现的服务 然后使用 BookServiceImpl 继承 BookService 来实现所需要的服务 同时实现方法时直接调用 Dao 层相对应的服务实现方法即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface BookService {
//增加一本书
int addBook(Books books);

//删除一本书
int deleteBookById(int id);

//更新一本书
int updateBook(Books books);

//查询一本书
Books queryBooksById(int id);

//查询全部的书
List<Books> queryAllBook();

//按照名称查询书籍
Books queryBookByName(String bookName);
}

Service 实现

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
public class BookServiceImpl implements BookService {

//service 调 dao 层
private BookMapper bookMapper;

public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}

@Override
public int addBook(Books books) {
return bookMapper.addBook(books);
}

@Override
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}

@Override
public int updateBook(Books books) {
return bookMapper.updateBook(books);
}

@Override
public Books queryBooksById(int id) {
return bookMapper.queryBookById(id);
}

@Override
public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}

@Override
public Books queryBookByName(String bookName) { return bookMapper.queryBookByName(bookName); }
}

Spring-Service.xml

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

<!--1. 扫描 Service 下的包-->
<context:component-scan base-package="com.cu1.service"/>

<!--2. 将所有业务类注入到 Spring 可以通过配置或者注解-->
<bean id="BookServiceImpl" class="com.cu1.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>

<!--3. 声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>

<!--4. AOP事务支持-->

</beans>

9.3、整合 SpringMVC

springmvc-servlet.xml

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
<?xml version="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">

<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.cu1.controller"/>

<!-- 让Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler/>

<!-- 支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效
必须向上下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理。
而annotation-driven配置帮助我们自动完成上述两个实例的注入。
-->
<mvc:annotation-driven />

<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀 -->
<property name="suffix" value=".jsp"/>
</bean>

</beans>

web.xml

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
39
40
41
42
43
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--DispatcherServlet-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--一定要注意:我们这里加载的是总的配置文件,之前被这里坑了!-->
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--encodingFilter-->
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--Session过期时间-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>

<absolute-ordering />

</web-app>

==注意:==

1
2
3
<param-name>contextConfigLocation</param-name>
<!--一定要注意:我们这里加载的是总的配置文件,之前被这里坑了!-->
<param-value>classpath:applicationContext.xml</param-value>

applicationContext.xml 是一个将上面的 Spring-dao.xml Spring-Service.xml springmvc-servlet.xml 汇总起来的总文件

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">

<import resource="classpath:Spring-dao.xml"/>
<import resource="classpath:Spring-Service.xml"/>
<import resource="classpath:springmvc-servlet.xml"/>

</beans>

Controller 层

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@Controller
@RequestMapping("/book")
public class BookController {

//调用 Service 层
@Autowired
@Qualifier("BookServiceImpl")
private BookService bookService;

//查询全部的书籍 并且返回到一个书籍展示页面
@RequestMapping("/allBook")
public String list(Model model) {
List<Books> books = bookService.queryAllBook();
model.addAttribute("list", books);
return "allBook";
}

/*跳转到增加书籍页面*/
@RequestMapping("/toAddBook")
public String toAddPaper() {
return "addBook";
}

/*添加书籍的请求*/
@RequestMapping("/addBook")
public String addBook(Books books) {
bookService.addBook(books);
//重定向到 RequsetMapping("/allBook") 请求
return "redirect:/book/allBook";
}


/*跳转到修改页面*/
@RequestMapping("/toUpdateBook/{bookId}")
public String toUpdatePaper(@PathVariable("bookId") int id, Model model) {
Books books = bookService.queryBooksById(id);
model.addAttribute("books", books);
return "updateBook";
}

@RequestMapping("/updateBook")
public String updateBooks(Books books) {
bookService.updateBook(books);
//重定向到 RequsetMapping("/allBook") 请求
return "redirect:/book/allBook";
}

//删除书籍
@RequestMapping("/deleteBook/{id}")
public String deleteBook(@PathVariable("id") int id) {
bookService.deleteBookById(id);
return "redirect:/book/allBook";
}

//查询书籍
@RequestMapping("/queryBook")
public String queryBook(String queryBookName, Model model) {
Books books = bookService.queryBookByName(queryBookName);
List<Books> list = new ArrayList<Books>();
list.add(books);
if (books == null) {
list = bookService.queryAllBook();
model.addAttribute("error", "未查到");
}
model.addAttribute("list", list);
return "allBook";
}
}

到这里所有架构和配置文件已经完成,但是还没有导入 maven 依赖 如果按照视频上的版本或者不是比较新的版本

那么就会出现很多问题 排查起来太痛苦

这里强烈建议所需依赖全部导入最新版本!!!!

pom.xml

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?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></groupId>
<artifactId></artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>

<!--Servlet - JSP -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>

<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>

</project>

当你导入这些依赖之后 问题可能只解决了一部分 之前的问题被下面的错误取代

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
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: More than one fragment with the name [spring_web] was found. This is not legal with relative ordering. See section 8.2.2 2c of the Servlet specification for details. Consider using absolute ordering.
at org.apache.tomcat.util.descriptor.web.WebXml.orderWebFragments(WebXml.java:2200)
at
org.apache.tomcat.util.descriptor.web.WebXml.orderWebFragments(WebXml.java:2159)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1124)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:769)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:299)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94)
at

org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5176)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 10 more

21-Jan-2019 01:51:04.709 SEVERE [localhost-startStop-1]
org.apache.catalina.startup.HostConfig.deployWAR Error deploying web application archive [C:\Users\dennismo\Dev\Projects\Production Prep\file-upload-module\webapps\file-upload-0.0.1-SNAPSHOT.war]
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/file-upload-0.0.1-SNAPSHOT]]
at

org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:758)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:985)
at


org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

如果是使用了本文提供的 web.xml 应该就不会遇到这种报错 这一切都归功于 web.xml 中的 <absolute-ordering /> 标签

9.4、前端的构建

上面都是处于服务端的实现 现在开始构建前端

addBook.jsp

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<%--
Created by IntelliJ IDEA.
User: 雷神
Date: 2021/10/11
Time: 9:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>增加</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>

<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>新增书籍</small>
</h1>
</div>
</div>
</div>

<<form action="${pageContext.request.contextPath}/book/addBook" method="post">
<div class="form-group">
<label for="bkname">书籍名称</label>
<input type=text name="bookName" class="form-control" id="bkname" required>
</div>
<div class="form-group">
<label for="bknum">书籍数量</label>
<input type=text name="bookCounts" class="form-control" id="bknum" required>
</div>

<div class="form-group">
<label for="bkdetail">书籍描述</label>
<input type=text name="detail" class="form-control" id="bkdetail" required>
</div>

<div class="form-group">
<input type="submit" class="form-control" value="添加">
</div>

</form>

</div>

</body>
</html>

allBook.jsp

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 雷神
Date: 2021/10/9
Time: 13:29
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示页面</title>
<%--Bootstrap 美化界面--%>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>

<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>书籍列表 -> 显示所有书籍</small>
</h1>
</div>
</div>

<div class="row">
<div class="color-md-4 column">
<%--toAddBook--%>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增书籍</a>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">显示全部书籍</a>
</div>

<%--查询书籍--%>
<div class="color-md-4 column">
<form class="form-inline" action="${pageContext.request.contextPath}/book/queryBook" method="post" style="float: right">
<span style="color: red; font-weight: bold">${error}</span>
<input type="text" name="queryBookName" class="form-control" placeholder="请输入要查询的书籍名称">
<input type="submit" value="查询" class="btn btn-primary">
</form>
</div>

</div>

</div>

<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>书籍编号</th>
<th>书籍名称</th>
<th>书籍数量</th>
<th>书籍详情</th>
<th>操作</th>
</tr>
</thead>
<%-- 书籍从数据库中查询出来 从这个 list 中遍历出来--%>
<tbody>
<c:forEach var="book" items="${list}">
<tr>
<td>${book.bookID}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
<td>
<a href="${pageContext.request.contextPath}/book/toUpdateBook/${book.bookID}">修改</a>
&nbsp;| &nbsp;
<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>

updateBook.jsp

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<%--
Created by IntelliJ IDEA.
User: 雷神
Date: 2021/10/11
Time: 10:51
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改书籍</title>

<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>修改书籍</small>
</h1>
</div>
</div>
</div>

<<form action="${pageContext.request.contextPath}/book/updateBook" method="post">

<%--出现的问题 提交了修改 SQL 的请求 但是修改失败 初次考虑是事务出现问题
事务没有问题的情况下 查看 SQL 语句 看能否执行成功
此时前端要传递隐藏域
--%>

<input type="hidden" name="bookID" value="${books.bookID}">

<div class="form-group">
<label for="bkname">书籍名称</label>
<input type=text name="bookName" class="form-control" id="bkname" value="${books.bookName}" required>
</div>
<div class="form-group">
<label for="bknum">书籍数量</label>
<input type=text name="bookCounts" class="form-control" id="bknum" value="${books.bookCounts}" required>
</div>

<div class="form-group">
<label for="bkdetail">书籍描述</label>
<input type=text name="detail" class="form-control" id="bkdetail" value="${books.detail}" required>
</div>

<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>

</form>
</div>
</body>
</html>

index.jsp

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
<%--
Created by IntelliJ IDEA.
User: 雷神
Date: 2021/10/8
Time: 21:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍管理</title>

<style>
a{
text-decoration: none;
color: black;
font-size: 18px;
}
h3{
width: 180px;
height: 38px ;
margin: 100px auto;
text-align: center;
line-height: 38px;
background: deepskyblue;
border-radius: 5px;
}
</style>

</head>
<body>

<h3>
<a href="${pageContext.request.contextPath}/book/allBook">进入书籍页面</a>
</h3>
</body>
</html>