目录
1.回顾MVC
1.1 什么是MVC
- MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
- 是将业务逻辑、数据、显示分离的方法来组织代码。
- MVC主要作用是降低了视图与业务逻辑间的双向偶合。
- MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。 也就是说控制器做了个调度员的工作
职责分析:
Controller:控制器
- 取得表单数据
- 调用业务逻辑
- 转向指定的页面
Model:模型
- 业务逻辑
- 保存数据的状态
View:视图
- 显示页面
1.2 回顾servlet
创建一个Maven工程当做父工程,导入pom依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</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>
</dependencies>
建立一个子Maven工程 springMVC-01-servlet 添加web-app支持
导入servlet 和 jsp 的 jar 依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
编写一个servlet用来处理用户的请求
/**
* @author xiaow
* @data 2021/11/17
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取前端参数
String method = req.getParameter("method");
if ("add".equals(method)) {
req.getSession().setAttribute("msg", "使用了add方法");
} else if ("delete".equals(method)) {
req.getSession().setAttribute("msg", "使用了delete方法");
}
// 调用业务层
// 转发或重定向
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
编写jsp页面,在WEB-INF目录下新建一个jsp文件夹,并在里面新建一个test.jsp文件
<html>
<head>
<title>test</title>
<base href="<%=basePath%>">
</head>
<body>
${msg}
</body>
</html>
在web.xml中注册servlet
<?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>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.xiaow.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
配置Tomcat进行测试
- localhost:8080/hello?method=add
- localhost:8080/hello?method=delete
MVC框架要做哪些事情
- 将url映射到java类或java类的方法 .
- 封装用户提交的数据 .
- 处理请求—调用相关的业务处理—封装响应数据 .
- 将响应的数据进行渲染 . jsp / html 等表示层数据 .
说明:
常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF;常见前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM 等等….
2.SpringMVC
2.1 什么是SpringMVC
2.1.1 概述
官方文档:Web on Servlet Stack
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架
SpringMVC的特点
- 轻量级,简单易学
- 高效 , 基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约定优于配置
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简洁灵活
Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
正因为SpringMVC好 , 简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于配置 . 能够进行简单的junit测试 . 支持Restful风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等……所以我们要学习
2.1.2 中心控制器
Spring的web框架围绕DispatcherServlet设计。 DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。
Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者
2.1.3 SpringMVC的执行原理
图为SpringMVC的一个较完整的流程图,实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现。
简要分析执行流程
DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
SpringMVC部署在服务器上的web站点
hello表示控制器
通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
-
HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
-
HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
-
HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
-
HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
-
Handler让具体的Controller执行。
-
Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
-
HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
-
DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
-
视图解析器将解析的逻辑视图名传给DispatcherServlet。
-
DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
-
最终视图呈现给用户
3.HelloSpringMVC
3.1 配置版
新建一个Moudle springMVC-02-hellomvc 添加web-app支持 导入相关依赖
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
确定配置SpringMVC所需要的依赖后
配置web.xml,注册DispatcherServlet
<?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:springMVC的核心,请求分发器,前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- DispatcherServlet要绑定spring的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<!--
在springMVC中:/ /*
/ : 会匹配所有的请求,但是不包括jsp
/* : 不仅会匹配所有的请求,还包括jsp
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
编写SpringMVC 的 配置文件!名称:springmvc-servlet.xml : [servletname]-servlet.xml
说明,这里的名称要求是按照官方来的
- 添加处理器映射器
- 添加处理器适配器
- 添加视图解析器
<?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"/>
<!-- 视图解析器 : 模板引擎 Thymeleaf Freemarker -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图
/**
* @author xiaow
* @data 2021/11/18
*/
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
// 业务代码
String msg = "Hello springMvc!";
modelAndView.addObject("msg", msg);
// 视图跳转
modelAndView.setViewName("hello");
return modelAndView;
}
}
将自己的类交给SpringIOC容器,注册bean
<!-- BeanNameUrlHandlerMapping需要根据bean的id映射 -->
<bean id="/hello" class="com.xiaow.controller.HelloController"/>
编写需要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面
<html>
<head>
<title>Title</title>
<base href="<%=basePath%>">
</head>
<body>
${msg}
</body>
</html>
配置Tomcat启动测试
可能遇到的问题:访问出现404,排查步骤:
- 查看控制台输出,看一下是不是缺少了什么jar包。
- 如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!
- 重启Tomcat 即可解决!
小结:用配置实现mvc是为了理解原理,在真实开发中使用注解,这才是SpringMVC的精髓
3.2 注解版
新建一个Moudle,springmvc-03-hello-annotation ,添加web支持
建立包结构:com.xiaow.controller
在pom.xml中引入核心依赖:主要有Spring框架核心库、Spring MVC、servlet , JSTL等
解决项目的资源过滤问题
<!-- 资源过滤问题 -->
<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>
配置web.xml
注意点:
- 注意web.xml版本问题,要最新版!
- 注册DispatcherServlet
- 关联SpringMVC的配置文件
- 启动级别为1
- 映射路径为 / 【不要用/*,会404】
<?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:springMVC的核心,请求分发器,前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<!-- DispatcherServlet要绑定spring的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--
在springMVC中:/ /*
/ : 会匹配所有的请求,但是不包括jsp
/* : 不仅会匹配所有的请求,还包括jsp
-->
<!--所有请求都会被springmvc拦截 -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
编写springmvc-servlet.xml配置文件
- 让IOC的注解生效
- 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 …..
- MVC的注解驱动
- 配置视图解析器
- 在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问
<?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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包,让指定包下的注解生效,交给ICO容器统一管理 -->
<context:component-scan base-package="com.xiaow.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>
创建controller
编写一个java控制类:com.xiaow.controller.HelloController
/**
* @author xiaow
* @data 2021/11/20
*/
@Controller
@RequestMapping("/HelloController")
public class HelloController {
// 真实访问地址:/HelloController/hello
@RequestMapping("/hello")
public String helloSpringmvc(Model model) {
// 向模型中添加属性msg与值,可以在jsp页面取出并渲染
model.addAttribute("msg", "helloSpringMVC!");
// WEB-INF/jsp/hello.jsp
return "hello";
}
}
- @Controller是为了让Spring IOC容器初始化时自动扫描到
- @RequestMapper是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
- 方法中声明Model类型的参数是为了把Action中的数据带到视图中;
- 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp
创建视图层
- 在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息
- 可以通过EL表示取出Model中存放的值,或者对象
<html>
<head>
<title>springmvc</title>
<base href="<%=basePath%>">
</head>
<body>
${msg}
</body>
</html>
配置Tomcat运行
访问对应的请求链接
运行成功
3.3小结
实现步骤其实非常的简单:
- 新建一个web项目
- 导入相关jar包
- 编写web.xml , 注册DispatcherServlet
- 编写springmvc配置文件
- 接下来就是去创建对应的控制类 , controller
- 最后完善前端视图和controller之间的对应
- 测试运行调试.
使用springMVC必须配置的三大件:
处理器映射器、处理器适配器、视图解析器
通常,我们只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置
4. Controller和RestFul
4.1 Controller(控制器)
- 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
- 控制器负责解析用户的请求并将其转换为一个模型。
- 在Spring MVC中一个控制器类可以包含多个方法
- 在Spring MVC中,对于Controller的配置方式有很多种
4.2 Controller的实现方式
方式一:实现Controller接口
新建一个Moudle,springmvc-04-controller,将刚才的03 拷贝一份
- 删掉HelloController
- mvc的配置文件只留下 视图解析器
编写一个Controller类,ControllerTest1
/**
* @author xiaow
* @data 2021/11/20
*/
// 只要实现了Controller接口的类,就说明这是一个控制器
public class ControllerTest1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", "ControllerTest1");
modelAndView.setViewName("test");
return modelAndView;
}
}
编写完毕后,去Spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类
<bean id="/test1" class="com.xiaow.controller.ControllerTest1"/>
编写前端test.jsp,注意在WEB-INF/jsp目录下编写,对应我们的视图解析器
<html>
<head>
<title>test</title>
<base href="<%=basePath%>">
</head>
<body>
${msg}
</body>
</html>
小结:
- 实现接口Controller定义控制器是比较古老的方法
- 缺点是:一个控制器中只有一个方法,如果要多个方法则要定义多个Controller,定义的方式比较麻烦
方式二:使用注解@Controller
- @Controller注解类型用于声明Spring类的实例是一个控制器(还有另外三种:@Service、@Component)
- Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描
-
<!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 --> <context:component-scan base-package="com.xiaow.controller"/>
-
增加一个ControllerTest2使用注解实现
-
/** * @author xiaow * @data 2021/11/20 */ //@Controller注解的类会自动添加到Spring上下文中 @Controller public class ControllerTest2 { //映射访问路径 @RequestMapping("test2") public String controllerTest2(Model model) { //Spring MVC会自动实例化一个Model对象用于向视图中传值 model.addAttribute("msg", "ControllerTest2"); // /WEB-INF/jsp/test.jsp return "test"; } }
-
运行Tomcat测试
小结:可以发现,我们的两个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系
4.3 RequestMapping
- @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径
@Controller
public class ControllerTest2 {
//映射访问路径
@RequestMapping("/test2")
public String controllerTest2(Model model) {
//Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "ControllerTest2");
// /WEB-INF/jsp/test.jsp
return "test";
}
}
访问路径:localhost:8080/项目名/test2
同时注解类和方法
//@Controller注解的类会自动添加到Spring上下文中
@Controller
@RequestMapping("/ControllerTest2")
public class ControllerTest2 {
//映射访问路径
@RequestMapping("/test2")
public String controllerTest2(Model model) {
//Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "ControllerTest2");
// /WEB-INF/jsp/test.jsp
return "test";
}
}
访问路径:localhost:8080 / 项目名 / ControllerTest2 / test2
4.4 RestFul风格
概念
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
功能
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询
传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用RESTful操作资源 : 可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
新建一个RestFulController类
在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上
/**
* @author xiaow
* @data 2021/11/20
*/
@Controller
public class RestFulController {
// 映射访问路径
@RequestMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model) {
int res = a + b;
//Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "结果为:" + res);
//返回视图位置
return "test";
}
}
测试请求
使用路径变量的好处
-
使路径变得更加简洁;
-
获得参数更加方便,框架会自动进行类型转换。
-
通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/add/1/a,则路径与方法不匹配,而不会是参数转换失败
修改参数类型在测试
/**
* @author xiaow
* @data 2021/11/20
*/
@Controller
public class RestFulController {
// 映射访问路径
@RequestMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable String b, Model model) {
String res = a + b;
//Spring MVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg", "结果为:" + res);
//返回视图位置
return "test";
}
}
使用method属性指定请求类型
用于约束请求的类型,可以收窄请求范围。指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等
添加一个方法进行测试
method = RequestMethod.POST
我们使用浏览器地址栏进行访问默认是Get请求,会报错405
将 method = RequestMethod.POST改为method = RequestMethod.GET再次测试
//映射访问路径,必须是POST请求
@RequestMapping(value = "/test2", method = RequestMethod.GET)
public String test2(Model model) {
model.addAttribute("msg", "Post请求");
return "test";
}
小结:Spring MVC 的 @RequestMapping注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH
所有的地址栏请求默认都会是 HTTP GET 类型的
方法级别的注解变体有如下几个: 组合注解
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@GetMapping是一个组合注解 = @RequestMapping(method = RequestMethod.GET)
5.结果跳转方式
5.1 ModelAndView
设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 .
页面 : {视图解析器前缀} + viewName +{视图解析器后缀}
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
对应的Controller类
/**
* @author xiaow
* @data 2021/11/20
*/
// 只要实现了Controller接口的类,就说明这是一个控制器
public class ControllerTest1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 返回一个模型视图对象
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", "ControllerTest1");
modelAndView.setViewName("test");
return modelAndView;
}
}
5.2 ServletAPI
通过设置ServletAPI , 不需要视图解析器 .
- 通过HttpServletResponse进行输出
- 通过HttpServletResponse实现重定向
- 通过HttpServletResponse实现转发
@Controller
public class ResultGo {
@RequestMapping("/result/t1")
public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.getWriter().println("Hello,Spring BY servlet API");
}
@RequestMapping("/result/t2")
public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.sendRedirect("/index.jsp");
}
@RequestMapping("/result/t3")
public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
//转发
req.setAttribute("msg","/result/t3");
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
}
}
5.3 SpringMVC
通过SpringMVC来实现转发和重定向(无需视图解析器)
将视图解析器注释后测试
@Controller
public class ResultSpringMVC {
@RequestMapping("/rsm/t1")
public String test1(){
//转发
return "/index.jsp";
}
@RequestMapping("/rsm/t2")
public String test2(){
//转发二
return "forward:/index.jsp";
}
@RequestMapping("/rsm/t3")
public String test3(){
//重定向
return "redirect:/index.jsp";
}
}
通过SpringMVC来实现转发和重定向 - 有视图解析器;
重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
可以重定向到另外一个请求实现
@Controller
public class ResultSpringMVC2 {
@RequestMapping("/rsm2/t1")
public String test1(){
//转发
return "test";
}
@RequestMapping("/rsm2/t2")
public String test2(){
//重定向
return "redirect:/index.jsp";
//return "redirect:hello.do"; //hello.do为另一个请求/
}
}
6.数据处理
6.1 提交的域名称和处理方法的参数名一致
提交数据:http://localhost:8080/hello?name=xiaow
处理方法
@GetMapping("/hello")
public String hello(String name) {
System.out.println("请求数据name---> " + name);
return "test";
}
后台结果
6.2 提交的域名称和处理方法的参数名不一致
提交数据:http://localhost:8080/hello?username=xiaow
处理方法
@GetMapping("/hello")
public String hello(@RequestParam("username") String name, Model model) {
// 接收前端的参数
System.out.println("请求数据name---> " + name);
// 将参数传递给前端 model
model.addAttribute("msg", name);
return "test";
}
后台结果
6.3 提交的是一个对象
要求提交的表单域和对象的属性名一致 , 参数使用对象即可
编写实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String userName;
private String passWord;
private int age;
}
处理方法
@GetMapping("/user")
public String user(User user) {
System.out.println("前端数据---> " + user);
return "test";
}
后台结果
注意: 如果使用对象传递,前端传递的参数名和对象属性名一致
6.4 数据显示到前端
第一种:通过ModelAndView
// 只要实现了Controller接口的类,就说明这是一个控制器
public class ControllerTest1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// 返回一个模型视图对象
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", "ControllerTest1");
modelAndView.setViewName("test");
return modelAndView;
}
}
第二种:通过ModelMap
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
// 封装要显示到视图中的数据
// 相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println("前端获取的数据---> " + name);
return "test";
}
提交数据:http://localhost:8080/hello?username=xiaow
后台结果
第三种:通过Model
@RequestMapping("/t1")
public String test1(Model model, @RequestParam("username") String name) {
// 接收前端的参数
System.out.println(name);
// 将参数传递给前端 model
model.addAttribute("msg", name);
// 视图跳转
return "test";
}
对比区别:
Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
6.5 乱码问题
第一种:通过过滤器解决
这里SpringMVC给我们提过了一个过滤器,在web.xml中配置
<!-- 配置SpringMVC的过滤器解决乱码问题 -->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在极端情况下,这种过滤器对get请求的支持不是很友好,所以第二种解决方案
第二种:修改Tomcat配置文件
设置编码
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URLEncoding="UTF-8"
relaxedPathChars="|{}[],%" relaxedQueryChars="|{}[],%"/>
第三种:自定义过滤器(搬)
注:这个也是我在网上找的一些大神写的,一般情况下,SpringMVC默认的乱码处理就已经能够很好的解决了!(这句话也是搬的)
package com.kuang.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解决get和post请求 全部乱码的过滤器
*/
public class GenericEncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//处理response的字符编码
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
// 转型为与协议相关对象
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 对request包装增强
HttpServletRequest myrequest = new MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
//是否编码的标记
private boolean hasEncode;
//定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
public MyRequest(HttpServletRequest request) {
super(request);// super必须写
this.request = request;
}
// 对需要增强方法 进行覆盖
@Override
public Map getParameterMap() {
// 先获得请求方式
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
// post请求
try {
// 处理post乱码
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
// get请求
Map<String, String[]> parameterMap = request.getParameterMap();
if (!hasEncode) { // 确保get手动编码逻辑只运行一次
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
// 处理get乱码
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
//取一个值
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回参数的第一个值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
然后在web.xml中配置此过滤器即可!
尽量保持在能设置编码的地方 全部保持为UTF-8!
7.SSM整合
7.1 环境
- IDEA
- MySQL8.0
- Tomcat9
- Maven3.8
7.2 数据库环境
创建了一个书籍数据库表
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,'从进门到进牢');
7.3 基本环境搭建
新建一个Maven项目, 添加web支持,导入相关依赖
<!-- 依赖:junit、mysql-connect、连接池、mybatis、
servlet、jsp
mybatis-spring、spring、spring-connect、springMVC-->
<dependencies>
<!-- junit lombok -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!-- 数据库连接池 -->
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<!-- jsp、servlet、jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</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.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- spring -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.19.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.16.RELEASE</version>
</dependency>
</dependencies>
Maven资源过滤设置
<!-- 资源过滤问题 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
建立项目基本结构和框架配置
- com.xiaow.pojo
- com.xiaow.dao
- com.xiaow.service
- com.xiaow.controller
- mybatis-config.xml
-
<?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> </configuration>
-
- applicationContext.xml
-
<?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:spring-mvc.xml"/> </beans>
-
7.4 Mybatis层编写
数据库配置文件database.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
# mysql 8.0+ 需要配置时区
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root
编写Mybatis的核心配置文件
<?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>
<!-- 别名 -->
<typeAliases>
<package name="com.xiaow.pojo"/>
</typeAliases>
<!-- 绑定mapper -->
<mappers>
<mapper class="com.xiaow.dao.BooksMapper"/>
</mappers>
</configuration>
编写数据库对应的实体类com.xiaow.pojo.Books(这里使用Lombok插件)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books implements Serializable {
private int bookID;
private String bookName;
private int bookCounts;
String detail;
}
编写Dao层的Mapper接口
public interface BooksMapper {
// 增加一本书
int addBook(Books books);
// 删除一本书
int deleteBookById(@Param("bookID") int id);
// 修改一本书
int updateBook(Books books);
// 查询一本书
Books selectBookById(@Param("bookID") int id);
// 查询所有书
List<Books> selectAllBooks();
// 通过书籍名查询书籍
Books selectBookByName(@Param("bookName") String bookName);
}
编写Mapper接口对应的Mapper.xml文件(需要导入Mybatis依赖)
<?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.xiaow.dao.BooksMapper">
<insert id="addBook" parameterType="books">
insert into books (bookName, bookCounts, detail)
values (#{bookName},#{bookCounts},#{detail});
</insert>
<delete id="deleteBookById" parameterType="_int">
delete from books where bookID = #{bookID}
</delete>
<update id="updateBook" parameterType="books">
update books
set bookName = #{bookName},
bookCounts = #{bookCounts},
detail = #{detail}
where bookID = #{bookID};
</update>
<select id="selectBookById" resultType="books">
select *
from books where bookID = #{bookID};
</select>
<select id="selectAllBooks" resultType="books">
select *
from books;
</select>
<select id="selectBookByName" resultType="books">
select *
from books
where bookName = #{bookName}
</select>
</mapper>
编写Service层的接口和实现类
接口
public interface BooksService {
// 增加一本书
int addBook(Books books);
// 删除一本书
int deleteBookById(int id);
// 修改一本书
int updateBook(Books books);
// 查询一本书
Books selectBookById(int id);
// 查询所有书
List<Books> selectAllBooks();
// 通过书籍名查询书籍
Books selectBookByName(String bookName);
}
实现类
public class BooksServiceImpl implements BooksService {
private BooksMapper booksMapper;
public void setBooksMapper(BooksMapper booksMapper) {
this.booksMapper = booksMapper;
}
@Override
public int addBook(Books books) {
return booksMapper.addBook(books);
}
@Override
public int deleteBookById(int id) {
return booksMapper.deleteBookById(id);
}
@Override
public int updateBook(Books books) {
return booksMapper.updateBook(books);
}
@Override
public Books selectBookById(int id) {
return booksMapper.selectBookById(id);
}
@Override
public List<Books> selectAllBooks() {
return booksMapper.selectAllBooks();
}
@Override
public Books selectBookByName(String bookName) {
return booksMapper.selectBookByName(bookName);
}
}
底层需求操作编写完毕!
7.5 Spring层
配置Spring整合Mybatis(这里使用c3p0连接池)
编写Spring整合Mybatis的相关配置文件 spring-dao.xml
<?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">
<!-- 关联数据库配置文件 -->
<context:property-placeholder location = "classpath:database.properties"/>
<!--
连接池
dbcp:半自动化操作,不能自动连接
cp30:自动化操作(自动化的加载配置文件,并且可以自动设置到对象中)
druid
hikari
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="driverClass" value="${jdbc.driver}"/>
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="20"/>
<!-- 关闭连接后不自动提交 -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 获取连接失败重试次数-->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- 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容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 要扫描的dao包-->
<property name="basePackage" value="com.xiaow.dao"/>
</bean>
</beans>
Spring整合Service层 spring-service.xml
<?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">
<!-- 扫描包 -->
<context:component-scan base-package="com.xiaow.service"/>
<!-- 将业务类注入到bean中,可以通过配置或注解实现-->
<bean id="booksServiceImpl" class="com.xiaow.service.BooksServiceImpl">
<property name="booksMapper" ref="booksMapper"/>
</bean>
<!-- 配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
Spring层编写完毕!大杂烩!一个容器!
7.6 SpringMVC
web.xml
<?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">
<!-- Dispatcher -->
<servlet>
<servlet-name>Dispatcher</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>Dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 乱码过滤 -->
<filter>
<filter-name>CharacterEncoding</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>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
spring-mvc.xml
<?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"
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">
<!-- 注解驱动 -->
<mvc:annotation-driven/>
<!-- 静态资源过滤 -->
<mvc:default-servlet-handler/>
<!-- 扫描包 -->
<context:component-scan base-package="com.xiaow.controller"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
Spring配置整合文件applicationContext.xml
<?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:spring-mvc.xml"/>
</beans>
配置文件暂且结束!开始编写Controller和视图层!
BooksController类编写
@Controller
@RequestMapping("/books")
public class BooksController {
// controller调用service层
@Autowired
private BooksService booksService;
@RequestMapping("/allBooks")
// 查询所有书籍
public String getAllBooks(Model model) {
// 查询数据库数据
List<Books> list = booksService.selectAllBooks();
model.addAttribute("books", list);
return "allBooks";
}
// 跳转到添加书籍页面
@RequestMapping("/addBookPage")
public String addBookPage() {
return "addBookPage";
}
// 添加书籍业务
@RequestMapping("/addBook")
public String addBook(Books books) {
int rows = booksService.addBook(books);
System.out.println("addBook影响行数:=》" + rows);
// 添加数据后 重定向到 @RequestMapping("/allBooks")请求
return "redirect:/books/allBooks";
}
// 跳转到修改书籍页面
@RequestMapping("/updateBookPage/{bookId}")
public String updateBookPage(@PathVariable int bookId, Model model) {
// 根据前端的数据查询book
Books book = booksService.selectBookById(bookId);
// 返回到前端
model.addAttribute("tempBook", book);
return "updateBookPage";
}
// 修改书籍请求
@RequestMapping("/updateBook")
public String updateBook(Books books) {
int rows = booksService.updateBook(books);
System.out.println("updateBook影响行数:=》" + rows);
// 修改数据后 重定向到 @RequestMapping("/allBooks")请求
return "redirect:/books/allBooks";
}
// 删除书籍请求
@RequestMapping("/deleteBook/{bookId}")
public String deleteBook(@PathVariable int bookId) {
int rows = booksService.deleteBookById(bookId);
System.out.println("deleteBook影响行数:=》" + rows);
// 删除书籍后 重定向到 @RequestMapping("/allBooks")请求
return "redirect:/books/allBooks";
}
// 根据书籍名查询书籍
@RequestMapping("/selectBook")
public String seleteBookByName(String queryBookName, Model model) {
Books book = booksService.selectBookByName(queryBookName);
List<Books> list = new ArrayList<>();
list.add(book);
model.addAttribute("books", list);
return "allBooks";
}
}
首页index.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head>
<title>$Title$</title>
<base href="<%=basePath%>">
<style>
a{
text-decoration: none;
color: pink;
font-size: 40px;
}
h1{
width: 500px;
height: 250px;
margin: 100px auto;
text-align: center;
line-height: 250px;
background: black;
border-radius: 5px;
}
</style>
</head>
<body>
<h1 id="butt"><a href="${pageContext.request.contextPath}/books/allBooks">进入书籍</a></h1>
</body>
</html>
书籍列表页面 allBooks.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: Chen
Date: 2021/11/23
Time: 17:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<title>allBooks</title>
<base href="<%=basePath%>">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
</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>
<div class="row">
<div class="col-md-4 column">
<a class="btn btn-primary" href="${pageContext.request.contextPath}/books/addBookPage">添加书籍</a>
</div>
<form class="form-inline" action="${pageContext.request.contextPath}/books/selectBook" method="post">
<div class="form-group">
<label class="sr-only" for="bookName">书籍名</label>
<input type="text" class="form-control" id="bookName" name="queryBookName" placeholder="请输入要查询的书籍名">
</div>
<button type="submit" class="btn btn-default">查询</button>
</form>
</div>
<div class="rwo 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>
<tbody>
<c:forEach var="book" items="${books}">
<tr>
<th>${book.bookID}</th>
<th>${book.bookName}</th>
<th>${book.bookCounts}</th>
<th>${book.detail}</th>
<th>
<a href="${pageContext.request.contextPath}/books/updateBookPage/${book.bookID}">修改</a> |
<a href="${pageContext.request.contextPath}/books/deleteBook/${book.bookID}">删除</a>
</th>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
添加书籍页面 addBookPage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<title>addBook</title>
<base href="<%=basePath%>">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
</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}/books/addBook" method="post">
<div class="form-group">
<label for="bookName">书籍名称</label>
<input type="text" class="form-control" name="bookName" id="bookName">
</div>
<div class="form-group">
<label for="bookCount">书籍数量</label>
<input type="text" class="form-control" name="bookCounts" id="bookCount">
</div>
<div class="form-group">
<label for="detail">书籍概述</label>
<input type="text" class="form-control" name="detail" id="detail">
</div>
<div class="form-group">
<input type="submit" class="form-control" value="添加">
</div>
</form>
</div>
</body>
</html>
修改书籍页面 updateBookPage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<html>
<head>
<title>updateBook</title>
<base href="<%=basePath%>">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>
</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}/books/updateBook" method="post">
<input type="hidden" name="bookID" value="${tempBook.bookID}">
<div class="form-group">
<label for="bookName">书籍名称</label>
<input type="text" class="form-control" name="bookName" value="${tempBook.bookName}" id="bookName">
</div>
<div class="form-group">
<label for="bookCount">书籍数量</label>
<input type="text" class="form-control" name="bookCounts" value="${tempBook.bookCounts}" id="bookCount">
</div>
<div class="form-group">
<label for="detail">书籍概述</label>
<input type="text" class="form-control" name="detail" value="${tempBook.detail}" id="detail">
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
</html>
配置Tomcat进行测试!!
项目结构图
待补充...