Spring MVC基本介绍
MVC设计模式
MVC 设计模式一般指 MVC 框架,M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。使用 MVC 的目的是将 M 和 V 的实现代码分离,使同一个程序可以有不同的表现形式。其中,View 的定义比较清晰,就是用户界面。
在 Web 项目的开发中,能够及时、正确地响应用户的请求是非常重要的。用户在网页上单击一个 URL 路径,这对 Web 服务器来说,相当于用户发送了一个请求。而获取请求后如何解析用户的输入,并执行相关处理逻辑,最终跳转至正确的页面显示反馈结果,这些工作往往是控制层(Controller)来完成的。
在请求的过程中,用户的信息被封装在 User 实体类中,该实体类在 Web 项目中属于数据模型层(Model)。
在请求显示阶段,跳转的结果网页就属于视图层(View)。
像这样,控制层负责前台与后台的交互,数据模型层封装用户的输入/输出数据,视图层选择恰当的视图来显示最终的执行结果,这样的层次分明的软件开发和处理流程被称为 MVC 模式。
在学习 Servlet 及 JSP 开发时,JavaBean 相当于 Model,Servlet 相当于 Controller,JSP 相当于 View。
总结如下:
-
视图层(View):负责格式化数据并把它们呈现给用户,包括数据展示、用户交互、数据验证、界面设计等功能。
-
控制层(Controller):负责接收并转发请求,对请求进行处理后,指定视图并将响应结果发送给客户端。
-
数据模型层(Model):模型对象拥有最多的处理任务,是应用程序的主体部分,它负责数据逻辑(业务规则)的处理和实现数据操作(即在数据库中存取数据)。 SUN 公司推出 JSP 技术的同时,也推出了两种 Web 应用程序的开发模式。即 JSP+JavaBean 和 Servlet+JSP+JavaBean。
JSP+JAVABEAN
JSP+JavaBean 中 JSP 用于处理用户请求,JavaBean 用于封装和处理数据。该模式只有视图和模型,一般把控制器的功能交给视图来实现,适合业务流程比较简单的 Web 程序。

通过上图可以发现 JSP 从 HTTP Request(请求)中获得所需的数据,并进行业务逻辑的处理,然后将结果通过 HTTP Response(响应)返回给浏览器。从中可见,JSP+JavaBean 模式在一定程度上实现了 MVC,即 JSP 将控制层和视图合二为一,JavaBean 为模型层。
JSP+JavaBean 模式中 JSP 身兼数职,既要负责视图层的数据显示,又要负责业务流程的控制,结构较为混乱,并且也不是我们所希望的松耦合架构模式,所以当业务流程复杂的时候并不推荐使用。
Serlet+Jsp+JavaBean
Servlet+JSP+JavaBean 中 Servlet 用于处理用户请求,JSP 用于数据显示,JavaBean 用于数据封装,适合复杂的 Web 程序。

相比 JSP+JavaBean 模式来说,Servlet+JSP+JavaBean 模式将控制层单独划分出来负责业务流程的控制,接收请求,创建所需的 JavaBean 实例,并将处理后的数据返回视图层(JSP)进行界面数据展示。
Servlet+JSP+JavaBean 模式的结构清晰,是一个松耦合架构模式,一般情况下,建议使用该模式。
MVC是什么
Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 Servlet。
Spring MVC 是结构最清晰的 Servlet+JSP+JavaBean 的实现,是一个典型的教科书式的 MVC 构架,不像 Struts 等其它框架都是变种或者不是完全基于 MVC 系统的框架。
Spring MVC 角色划分清晰,分工明细,并且和 Spring 框架无缝结合。Spring MVC 是当今业界最主流的 Web 开发框架,以及最热门的开发技能。
在 Spring MVC 框架中,Controller 替换 Servlet 来担负控制器的职责,用于接收请求,调用相应的 Model 进行处理,处理器完成业务处理后返回处理结果。Controller 调用相应的 View 并对处理结果进行视图渲染,最终客户端得到响应信息。
Spring MVC 框架采用松耦合可插拔的组件结构,具有高度可配置性,比起其它 MVC 框架更具有扩展性和灵活性。
此外,Spring MVC 的注解驱动和对 REST 风格的支持,也是它最具特色的功能。无论是在框架设计,还是扩展性、灵活性等方面都全面超越了 Struts2 等 MVC 框架。并且由于 Spring MVC 本身就是 Spring 框架的一部分,所以可以说与 Spring 框架是无缝集成,性能方面具有先天的优越性,对于开发者来说,开发效率也高于其它的 Web 框架,在企业中的应用越来越广泛,成为主流的 MVC 框架。
SpringMVC优点 缺点
优点:
- 多视图共享一个模型,大大提高了代码的可重用性
- MVC 三个模块相互独立,松耦合架构
- 控制器提高了应用程序的灵活性和可配置性
- 有利于软件工程化管理
- 晰地角色划分,Spring MVC 在 Model、View 和 Controller 方面提供了一个非常清晰的角色划分,这 3 个方面真正是各司其职,各负其责。
- 灵活的配置功能,可以把类当作 Bean 通过 XML 进行配置。
- 提供了大量的控制器接口和实现类,开发者可以使用 Spring 提供的控制器实现类,也可以自己实现控制器接口。
- 真正做到与 View 层的实现无关。它不会强制开发者使用 JSP,可以根据项目需求使用 Velocity、FreeMarker 等技术。
- 国际化支持
- 面向接口编程
- 与 Spring 框架无缝集成
缺点:
- 原理复杂
- 增加了系统结构和实现的复杂性
- 视图对模型数据的低效率访问
MVC 并不适合小型甚至中型规模的项目,花费大量时间将 MVC 应用到规模并不是很大的应用程序,通常得不偿失,所以对于 MVC 设计模式的使用要根据具体的应用场景来决定。
SSM=Mybatis+Spring+SpringMVC MVC三层架构
MVC:模型(dao,service)视图(jsp)控制器(Servlet)
Spring MVC的特点
1,轻量级,简单易学
2,高效,基于请求响应的MVC框架
3,与Spring 兼容性好,无缝结合
4,约定优于系统配置
5,功能强大,RESTful,数据验证,格式话,本地话,主题等
6,简洁灵活
导入依赖包
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<!--J2EE-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</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>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!--springframework-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.16.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!--其他需要的包-->
<dependency
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
HelloController
package com.yuan.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloContorller implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
//业务代码
String result = "Hello SpringMVC";
mv.addObject("msg",result);
//视图跳转
mv.setViewName("test");
return mv;
}
}
Springmvc-servlet
<?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-->
<!--
1获取了ModeLAndView的数据
2.解机ModeLAndView的视图名宁
3.拼接视图名字,找到对应的视图/WEB-INF/jsp/heLlo.jsp
4. 将数据渲染到这个视图Ⅰ
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--/test 自己定义的名称-->
<bean id="/test" class="com.yuan.controller.HelloContorller"/>
</beans>
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">
<!--配置DispatchServlet:这个是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>
<!--启动基本:1:服务器启动就启动-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Spring MVC视图解析器(ViewResolver)
视图解析器(ViewResolver)是 Spring MVC 的重要组成部分,负责将逻辑视图名解析为具体的视图对象。
Spring MVC 提供了很多视图解析类,其中每一项都对应 Java Web 应用中特定的某些视图技术。下面介绍一些常用的视图解析类。
URLBasedViewResolver
UrlBasedViewResolver 是对 ViewResolver 的一种简单实现,主要提供了一种拼接 URL 的方式来解析视图。
UrlBasedViewResolver 通过 prefix 属性指定前缀,suffix 属性指定后缀。当 ModelAndView 对象返回具体的 View 名称时,它会将前缀 prefix 和后缀 suffix 与具体的视图名称拼接,得到一个视图资源文件的具体加载路径,从而加载真正的视图文件并反馈给用户。
使用 UrlBasedViewResolver 除了要配置前缀和后缀属性之外,还需要配置“viewClass”,表示解析成哪种视图。示例代码如下。
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceViewResolver"/> <!--不能省略-->
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
上述视图解析器配置了前缀和后缀两个属性,这样缩短了 view 路径。因此《第一个Spring MVC应用》一节中的 RegisterController 和 LoginController 控制器类的视图路径仅需提供 register 和 login,视图解析器将会自动添加前缀和后缀,此处解析为 /WEB-INF/jsp/register.jsp 和 /WEB-INF/jsp/login.jsp。
上述 viewClass 值为 InternalResourceViewResolver,它用来展示 JSP 页面。如果需要使用 jstl 标签展示数据,将 viewClass 属性值指定为 JstlView 即可。
另外,存放在 /WEB-INF/ 目录下的内容不能直接通过 request 请求得到,所以为了安全性考虑,通常把 jsp 文件放在 WEB-INF 目录下。
Spring MVC和Struts2的区别
Spring MVC 和 Struts2 类似,是一款基于传统 MVC 设计模式的 Java EE 框架。它的核心是一个弹性的控制层,能够很好地发挥 MVC 模式的“分离显示逻辑和业务逻辑”的能力。
而近年来越来越多的开发者选择使用 Spring MVC 技术来代替 Struts2 技术,那么相比于 Struts2 框架,Spring MVC 的优点在哪里呢?
下面来分析一下两者的区别。
1. Spring MVC 基于方法开发,Struts2 基于类开发。
在使用 Spring MVC 框架进行开发时,会将 URL 请求路径与 Controller 类的某个方法进行绑定,请求参数作为该方法的形参。当用户请求该 URL 路径时, Spring MVC 会将 URL 信息与 Controller 类的某个方法进行映射,生成 Handler 对象,该对象中只包含了一个 method 方法。方法执行结束之后,形参数据也会被销毁。
而在使用 Struts2 框架进行开发时,Action 类中所有方法使用的请求参数都是 Action 类中的成员变量,随着方法变得越来越多,就很难分清楚 Action 中那么多的成员变量到底是给哪一个方法使用的,整个 Action 类会变得十分混乱。
相比较而言,Spring MVC 优点是其所有请求参数都会被定义为相应方法的形参,用户在网页上的请求路径会被映射到 Controller 类对应的方法上,此时请求参数会注入到对应方法的形参上。Spring MVC 的这种开发方式类似于 Service 开发。
2. Spring MVC 可以进行单例开发,Struts2 无法使用单例
Spring MVC 支持单例开发模式,而 Struts2 由于只能通过类的成员变量接受参数,所以无法使用单例模式,只能使用多例。
3. 经过专业人员的大量测试,Struts2 的处理速度要比 SpringMVC 慢,原因是 Struts2 使用了 Struts 标签,Struts 标签由于设计原因,会出现加载数据慢的情况
这里仅仅比较了 Spring MVC 在某些方面相比 Struts2 的优势,但这并不能说明 Spring MVC 比 Struts2 优秀,仅仅因为早期 Struts2 使用广泛,所以出现的漏洞也比较多,但是在新版本的 Struts2 中也修复了许多漏洞。Spring MVC 自诞生以来,几乎没有什么致命的漏洞 。且 Spring MVC 基于方法开发,这一点较接近 Service 开发,这也是 Spring MVC 近年来备受关注的原因之一。
InternalResourceViewResolver
InternalResourceViewResolver 为“内部资源视图解析器”,是日常开发中最常用的视图解析器类型。它是 URLBasedViewResolver 的子类,拥有 URLBasedViewResolver 的一切特性。
InternalResourceViewResolver 能自动将返回的视图名称解析为 InternalResourceView 类型的对象。InternalResourceView 会把 Controller 处理器方法返回的模型属性都存放到对应的 request 属性中,然后通过 RequestDispatcher 在服务器端把请求 forword 重定向到目标 URL。也就是说,使用 InternalResourceViewResolver 视图解析时,无需再单独指定 viewClass 属性。示例代码如下。
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceViewResolver"/> <!--可以省略-->
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
FreeMarkerViewResolver
FreeMarkerViewResolver 是 UrlBasedViewResolver 的子类,可以通过 prefix 属性指定前缀,通过 suffix 属性指定后缀。
FreeMarkerViewResolver 最终会解析逻辑视图配置,返回 freemarker 模板。不需要指定 viewClass 属性。
FreeMarkerViewResolver 配置如下。
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="prefix" value="fm_"/>
<property name="suffix" value=".ftl"/>
</bean>
下面指定 FreeMarkerView 类型最终生成的实体视图(模板文件)的路径以及其他配置。需要给 FreeMarkerViewResolver 设置一个 FreeMarkerConfig 的 bean 对象来定义 FreeMarker 的配置信息,代码如下。
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl" />
</bean>
定义了 templateLoaderPath 属性后,Spring 可以通过该属性找到 FreeMarker 模板文件的具体位置。当有模板位于不同的路径时,可以配置 templateLoaderPath 属性,来指定多个资源路径。
然后定义一个 Controller,让其返回 ModelAndView,同时定义一些返回参数和视图信息。
@Controller
@RequestMapping("viewtest")
public class ViewController {
@RequestMapping("freemarker")
public ModelAndView freemarker() {
ModelAndView mv = new ModelAndView();
mv.addObject("username", "BianChengBang");
mv.setViewName("freemarker");
return mv;
}
}
Spring MVC执行流程
在学习框架之前,首先来了解一下 Spring MVC 框架的整体请求流程和使用到的 API 类。
Spring MVC 框架是高度可配置的,包含多种视图技术,例如 JSP、FreeMarker、Tiles、iText 和 POI。Spring MVC 框架并不关心使用的视图技术,也不会强迫开发者只使用 JSP。
Spring MVC 执行流程3
Spring MVC 执行流程如图 1 所示。

SpringMVC 的执行流程如下。
- 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
- 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
- DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
- HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
- Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
- HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
- DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
- ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
- DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
- 视图负责将结果显示到浏览器(客户端)。
Spring MVC接口
Spring MVC 涉及到的组件有 DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)、Handler(处理器)、ViewResolver(视图解析器)和 View(视图)。下面对各个组件的功能说明如下。
1)DispatcherServlet
DispatcherServlet 是前端控制器,从图 1 可以看出,Spring MVC 的所有请求都要经过 DispatcherServlet 来统一分发。DispatcherServlet 相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展。
2)HandlerMapping
HandlerMapping 是处理器映射器,其作用是根据请求的 URL 路径,通过注解或者 XML 配置,寻找匹配的处理器(Handler)信息。
3)HandlerAdapter
HandlerAdapter 是处理器适配器,其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)。
4)Handler
Handler 是处理器,和 Java Servlet 扮演的角色一致。其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至 ModelAndView 对象中。
5)View Resolver
View Resolver 是视图解析器,其作用是进行解析操作,通过 ModelAndView 对象中的 View 信息将逻辑视图名解析成真正的视图 View(如通过一个 JSP 路径返回一个真正的 JSP 页面)。
6)View
View 是视图,其本身是一个接口,实现类支持不同的 View 类型(JSP、FreeMarker、Excel 等)。
以上组件中,需要开发人员进行开发的是处理器(Handler,常称Controller)和视图(View)。通俗的说,要开发处理该请求的具体代码逻辑,以及最终展示给用户的界面。
1·我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
. http://localhost:8080服务器域名
. 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根据视图解析器解析的视图结果,调用具体的视图。
-
12.最终视图呈现给用户。
SpringMVC 基本语法操作
@Controller和@RequestMapping注解
将依赖注入到 Spring MVC 控制器时需要用到 @Autowired 和 @Service 注解。
@Autowired 注解属于 org.springframework.beans.factory. annotation 包,可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
@Service 注解属于 org.springframework.stereotype 包,会将标注类自动注册到 Spring 容器中。````
实例
HelloContorller
@Controller
public class HelloController {
//真实访问地址:项目名/HelloController/hello
@RequestMapping("/hello")
public String hello(Model model) {
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
//封装数据
model.addAttribute("msg","Hello,SpringMVC");
//WEB-INF/jsp/hello.jsp
return "hello";
}
}
```cpp
```java
<!--访问的是index下的login-->
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/register")
public String register() {
return "register";
}
}
```cpp
springmvc-servlet.xml
```javascript
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="com.yuan.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>
```cpp
web.xml
```java
<?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">
<!--配置DispatchServlet:这个是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>
<!--启动基本:1:服务器启动就启动-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
```cpp
1. 新建一个web项目
2. 导入相关jar包
3. 编写web.xml,注册DispatcherServlet
4. 编写spring mvc配置文件
5. 接下来就是去创建对应的控制类,controller
6. 最后完善前端视图和controller之间的对应、
7.测试运行调试.
使用springMVC必须配置的三大件:
处理器映射器、处理器适配器、视图解析器
#### Controller
控制器Controller
控制器复制提供访问应用程序的行为,通常通过接口或注解定义两种方式实现
控制器负责解析用户请求将其转换一个模型。
在Spring mvc中一个控制器可以包含多个方法
在Spring MVC中,对于Controller的配置方式有很多种
#### RestFul 风格
RestFul就是一个资源定位集资源操作的风格,也不是标准协议,只是一种风格,基于这个设计的软件可以更简洁,更有层次,更易于实现缓存机制。
**功能**
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用Post delete,put,get,使用不同方法对资源操作
分别对应:添加,删除,修改,查询
传统方式操作资源︰通过不同的参数来实现不同的效果!方法单一,post和get
在Spring MVC中可以使用@PathVariable注解,让方法参数的值对应绑定到一个URI模板变量上。
使用RESTful操作资源:可以通过不同的请求方式来实现不同的效果!
方法级别的注解变体有如下几个:组合注解
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
在Spring MVC中可以使用@PathVariable注解,让方法参数的值对应绑定到一个URI模板变量
代码:
TestController
```java
package com.yuan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class TestController {
/*
get请求1
*/
@RequestMapping(value = "/t1/{a}/{b}",method = RequestMethod.GET)
public String Test01(@PathVariable int a,@PathVariable int b, Model model){
int sum=a+b;
model.addAttribute("msg","sum和为"+sum);
return "test";
}
/**
* post请求
* @param a 请求的参数
* @param b 请求的参数
* @param model
* @return
*/
@PostMapping("/t1/{a}/{b}")
public String Test02(@PathVariable int a,@PathVariable int b, Model model){
int sum=a+b;
model.addAttribute("msg","sum和为"+sum);
return "test";
}
}
```cpp
jsp页面,从浏览器地址输入
index2
```xml-dtd
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/t1/12/10" method="post">
<input type="submit"/>
</form>
</body>
</html>
```cpp
#### Spring 结果的跳转方式
ModelAndView
设置ModelAndView对象,根据view的名称,和视图解析器跳到指定的页面.
页面︰{视图解析器前缀}+ viewName +{视图解析器后缀}
**Spring MVC重定向和转发**
Spring MVC 请求方式分为转发、重定向 2 种,分别使用 forward 和 redirect 关键字在 controller 层进行处理。
重定向是将用户从当前处理请求定向到另一个视图(例如 JSP)或处理请求,以前的请求(request)中存放的信息全部失效,并进入一个新的 request 作用域;转发是将用户对当前处理的请求转发给另一个视图或处理请求,以前的 request 中存放的信息不会失效。
转发是服务器行为,重定向是客户端行为。
**1)转发过程**
客户浏览器发送 http 请求,Web 服务器接受此请求,调用内部的一个方法在容器内部完成请求处理和转发动作,将目标资源发送给客户;在这里转发的路径必须是同一个 Web 容器下的 URL,其不能转向到其他的 Web 路径上,中间传递的是自己的容器内的 request。
在客户浏览器的地址栏中显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。
**2)重定向过程**
客户浏览器发送 http 请求,Web 服务器接受后发送 302 状态码响应及对应新的 location 给客户浏览器,客户浏览器发现是 302 响应,则自动再发送一个新的 http 请求,请求 URL 是新的 location 地址,服务器根据此请求寻找资源并发送给客户。
在这里 location 可以重定向到任意 URL,既然是浏览器重新发出了请求,那么就没有什么 request 传递的概念了。在客户浏览器的地址栏中显示的是其重定向的路径,客户可以观察到地址的变化。重定向行为是浏览器做了至少两次的访问请求。
```javascript
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/login")
public String login() {
//转发到一个请求方法(同一个控制器类可以省略/index/)
return "forward:/index/isLogin.jsp";
}
@RequestMapping("/isLogin")
public String isLogin() {
//重定向到一个请求方法
return "redirect:/index/isRegister.jsp";
}
@RequestMapping("/isRegister")
public String isRegister() {
//转发到一个视图
return "register";
}
}
```cpp
#### Springmvc 数据处理
Nodel只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;
ModelMap继承了LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
ModelAndview 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
实体类:
```javascript
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
private int age;
}
```cpp
Controller
```javascript
@Controller
@RequestMapping("user")
public class ModelTest1 {
//前端接收的是一个参数 user/t1?name=aaa
@GetMapping("t1")
public String ModelTest01(@RequestParam("name") String name, Model model){
//传递给前端的参数
model.addAttribute("msg",name);
return "test";
}
//前端接收的是一个对象 id name age
//1,按收刖城用尸传递的参数,判断参数的名子,假攻名子且按仕力法上,叮以且按便用
//2.假设传递的是一个对象User,匹配user对象中的字段名;如果名字一致则oK,否则,匹配不到
//http://localhost:8080/user/t2?id=1&name=2&age=3
@GetMapping("t2")
public String ModelTest02(User user){
System.out.println(user);
return "test";
}
}
```cpp
#### 乱码问题解决
tamcat配置文件:
server:
```javascript
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>
```cpp
使用Spring MVC的配置过滤器
```javascript
<!--配置Spring MVC乱码过滤器-->
<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>
```cpp
乱码终极解决方案
新建一个包:filter 建一个类GenericEncodingFilter
```javascript
package com.yuan.filter;
<br/>
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 {
public void destroy() {
}
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);
}
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;
}
}
```cpp
在web.xml配置
```javascript
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.yuan.filter.GenericEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```cpp
#### Spring Json
什么是JSON?
.JSON(JavaScript Object Notation, JS对象标记)是一种轻量级的数据交换格式,目前使用特别广泛。
·采用完全独立于编程语言的文本格式来存储和表示数据。
·采用完全独立于编程语言的文本格式来存储和表示数据。
·易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在JavaScript 语言中,一切都是对象。因此,任何JavaScript支持的类型都可以通过JSON来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:
·对象表示为键值对,数据由逗号分隔
·花括号保存对象
。方括号保存数组
JSON键值对是用来保存JavaScript对象的一种方式,和JavaScript对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号""包裹,使用冒号∶分隔,然后紧接着值:
导入json依赖
```javascript
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
```cpp
如果json乱码可以在springmvc-servlet.xml配置
```javascript
<!-- 处理请求返回json字符串的中文乱码问题 -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- StringHttpMessageConverter编码为UTF-8,防止乱码 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" />
</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"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
```cpp
@Controller 走视图解析器
@RestController 返回字符串不走视图解析器
@RequestMapping(value = "j1",produces = "application/json;charset=utf-8")解决josn乱码问题一般不用 在xml配置即可
@ResponseBody它就不会走视图解析器,会直接返回一个字符串 配合@Controller使用
UserController类
```javascript
package com.yuan.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.yuan.pojo.User;
import com.yuan.utils.JosnUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
//@Controller 走视图解析器
@RestController //返回字符串不走视图解析器
public class UserController {
//@RequestMapping(value = "j1",produces = "application/json;charset=utf-8")解决josn乱码问题一般不用 在xml配置即可
// @ResponseBody它就不会走视图解析器,会直接返回一个字符串 配合@Controller使用
@RequestMapping("j1")
public String json() throws JsonProcessingException {
//创建一个对象
User user = new User("小黑",18,"男");
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(user);
return str;
}
//集合
@RequestMapping("j2")
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<User> list=new ArrayList<User>();
//创建一个对象
User user1 = new User("小黑1",18,"男");
User user2 = new User("小黑2",18,"男");
User user3 = new User("小黑3",18,"男");
User user4 = new User("小黑4",18,"男");
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
String str = mapper.writeValueAsString(list);
return str;
}
//时间 第一种方式
@RequestMapping("j3")
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Date date = new Date();
//自定义日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return mapper.writeValueAsString(sdf.format(date));
}
//时间 第二种方式
@RequestMapping("j4")
public String json4() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//自定义日期的格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mapper.setDateFormat(sdf);
Date date = new Date();
return mapper.writeValueAsString(date);
}
//集合 工具类
@RequestMapping("j5")
public String json5() throws JsonProcessingException {
List<User> list=new ArrayList<User>();
//创建一个对象
User user1 = new User("小黑1",18,"男");
User user2 = new User("小黑2",18,"男");
User user3 = new User("小黑3",18,"男");
User user4 = new User("小黑4",18,"男");
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
return JosnUtils.getJson(list);
}
/**
* 集合工具类调用
* @return
*/
@RequestMapping("j6")
public String Json6(){
Date date = new Date();
return JosnUtils.JosnUtils(date,"yyyy-MM-dd HH:mm:ss");
}
}
```cpp
JsonUtils工具类
```javascript
/**
* 工具类
*/
public class JosnUtils {
public static String getJson(Object object){
return JosnUtils(object,"yyyy-MM-dd HH:mm:ss");
}
public static String JosnUtils(Object object, String SimpleDate){
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//自定义日期的格式
SimpleDateFormat sdf = new SimpleDateFormat(SimpleDate);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
```cpp
#### fast JSON
导入依赖包
```javascript
<!--导入fastJSON包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
```cpp
fastJSON基本使用
```javascript
/**
* fastJSON的使用
*/
@RestController
public class UserFastJosnController {
@RequestMapping("fastJSON1")
public String Test1(){
List<User> list=new ArrayList<User>();
//创建一个对象
User user1 = new User("小黑1",18,"男");
User user2 = new User("小黑2",18,"男");
User user3 = new User("小黑3",18,"男");
User user4 = new User("小黑4",18,"男");
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
System.out.println("****java对象转JOSN对象****");
String str1=JSON.toJSONString(list);
System.out.println( "JSON.toJSONString(list)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);
System.out.println("\n******JSON字符串转Java对象*******");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
System.out.println("\n******Java对象转JSON对象******");
JSONObject jsonobject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject)JSON.toJSON(user2)==>"+jsonobject1.getString("name"));
System.out.println("\n******JSON对象转Java对象******");
User to_java_user = JSON.toJavaObject(jsonobject1,User.class);
System.out.println("JSON.toJava0bject(jsonobject1,User.class)==>"+to_java_user);
return "test";
}
}
```cpp
#### Spring mvc拦截器
概述
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。
**过滤器与拦截器的区别**:拦截器是AOP思想的具体应用。
**过滤器**
. servlet规范中的一部分,任何java web工程都可以使用
·在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
**拦截器**
·拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
·拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的
在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中,即平时所说的“权限检测”及“日志记录”。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。
Spring MVC 提供了 Interceptor 拦截器机制,用于请求的预处理和后处理。
在开发一个网站时可能有这样的需求:某些页面只希望几个特定的用户浏览。对于这样的访问权限控制,应该如何实现呢?拦截器就可以实现上述需求。在 Struts2 框架中,拦截器是其重要的组成部分,Spring MVC 框架也提供了拦截器功能。
Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。
**拦截器的定义**
在 Spring MVC 框架中定义一个拦截器需要对拦截器进行定义和配置,主要有以下 2 种方式。
1. 通过实现 HandlerInterceptor 接口或继承 HandlerInterceptor 接口的实现类(例如 HandlerInterceptorAdapter)来定义;
2. 通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义。
配置
````javascript
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 配置一个全局拦截器,拦截所有请求 -->
<bean class="con.yuan.TestInterceptor" />
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/**" />
<!-- 配置不需要拦截作用的路径 -->
<mvc:exclude-mapping path="" />
<!-- 定义<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
<bean class="con.yuan.TestInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/gotoTest" />
<!-- 定义在<mvc:interceptor>元素中,表示匹配指定路径的请求才进行拦截 -->
<bean class="con.yuan.TestInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
一般配置
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 配置拦截器作用的路径 -->
<mvc:mapping path="/**"/>
<bean class="net.biancheng.interceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
```cpp
- <mvc:interceptors>:该元素用于配置一组拦截器。
- <bean>:该元素是 <mvc:interceptors> 的子元素,用于定义全局拦截器,即拦截所有的请求。
- <mvc:interceptor>:该元素用于定义指定路径的拦截器。
- <mvc:mapping>:该元素是 <mvc:interceptor> 的子元素,用于配置拦截器作用的路径,该路径在其属性 path 中定义。path 的属性值为`/**`时,表示拦截所有路径,值为`/gotoTest`时,表示拦截所有以`/gotoTest`结尾的路径。如果在请求路径中包含不需要拦截的内容,可以通过 <mvc:exclude-mapping> 子元素进行配置。
```java
public class MyInterceptor implements HandlerInterceptor {
//return ture;执行下一个拦截器,放行
// return ture;不执行下一个拦截器
public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
System.out.println("=======处理前=======");
return true;
}
public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("=======处理后=======");
}
public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=======清理=======");
}
}
```cpp
使用拦截器做一个登录功能
LoginController
```java
package com.yuan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/user")
public class LoginController {
@RequestMapping("/main")
public String main() {
return "main";
}
@RequestMapping("/dologin")
public String dologin() {
return "login";
}
//登录
@RequestMapping("/login")
public String Login(HttpSession session, String username, String password, Model model){
if("yuan".equals(username)&&password.equals("123")){
session.setAttribute("username", username);
model.addAttribute("username",username);
return "main";
}
return "login";
}
//注销
@RequestMapping("/zhuXiao")
public String zhuXiao(HttpSession session){
session.removeAttribute("username");
return "mian";
}
}
```cpp
LoginInterceptor
```javascript
package com.yuan.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session=request.getSession();
//判断什么情况登录
//登录页面也会放行
if (request.getRequestURI().contains("dologin")) {
return true;
}
//只要式到了login就放行
if(request.getRequestURI().contains("login")){
return true;
}
//第一次登录没有session的
if(session.getAttribute("usernam")!=null){
return true;
}
//没有登录跳转到登录页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
```cpp
applicationContext.xml
```javascript
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean class="com.yuan.config.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
```cpp
login.jsp
```html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录表单</title>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/user/login">
<p>用户名: <input type="text" name="username"/></p>
<p>密码:<input type="password" name="password"></p>
<p><input type="submit" value="提交"/></p>
</form>
</body>
</html>
```cpp
main.jsp
```html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>首页</h1>
${username}
<a href="${pageContext.request.contextPath}/user/zhuXiao">注销</a>
</body>
</html>
```cpp
#### Spring MVC数据校验
pom.xml文件依赖
```java
<!-- 数据校验 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.0.CR2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
```cpp
JSR 303 不需要编写验证器,它定义了一套可标注在成员变量、属性方法上的校验注解
| 名称 | 说明 |
| ---------------------------- | ------------------------------------------------------------ |
| @Null | 被标注的元素必须为 null |
| @NotNull | 被标注的元素必须不为 null |
| @AssertTrue | 被标注的元素必须为 true |
| @AssertFalse | 被标注的元素必须为 false |
| @Min(value) | 被标注的元素必须是一个数字,其值必须大于等于指定的最小值 |
| @Max(value) | 被标注的元素必须是一个数字,其值必须小于等于指定的最大值 |
| @DecimalMax(value) | 被标注的元素必须是一个数字,其值必须大于等于指定的最大值 |
| @DecimalMin(value) | 被标注的元素必须是一个数字,其值必须小于等于指定的最小值 |
| @size | 被标注的元素的大小必须在指定的范围内 |
| @Digits(integer,fraction) | 被标注的元素必须是一个数字,其值必须在可接受的范围内;integer 指定整数精度,fraction 指定小数精度 |
| @Past | 被标注的元素必须是一个过去的日期 |
| @Future | 被标注的元素必须是一个将来的日期 |
| @Pattern(value) | 被标注的元素必须符合指定的正则表达式 |
User实体类
```java
package net.biancheng.po;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
public class User {
@NotNull(message = "用户id不能为空")
private Integer id;
@NotNull
@Length(min = 2, max = 8, message = "用户名不能少于2位大于8位")
private String name;
@Email(regexp = "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]", message = "邮箱格式不正确")
private String email;
}
```cpp
addUser.jsp
```java
%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>添加用户</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/validate" method="post">
用户id:<input type="text" name="id" />
<br>
用户名:<input type="text" name="name" />
<br>
邮箱:<input type="text" name="email" />
<br>
<input type="submit" value="提交" />
</form>
</body>
</html>
```cpp
UserController
```java
package net.biancheng.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import net.biancheng.po.User;
@Controller
public class UserController {
@RequestMapping("/validate")
public String validate(@Valid User user, BindingResult result) {
// 如果有异常信息
if (result.hasErrors()) {
// 获取异常信息对象
List<ObjectError> errors = result.getAllErrors();
// 将异常信息输出
for (ObjectError error : errors) {
System.out.println(error.getDefaultMessage());
}
}
return "index";
}
@RequestMapping(value = "/addUser")
public String add() {
return "addUser";
}
```cpp
**@Valid**:用于验证注解是否符合要求,直接加在变量user之前,在变量中添加验证信息的要求,当不符合要求.在实体类加注解时候用到
#### Spring MVC异常处理
Spring MVC 有以下 3 种处理异常的方式:
1. 使用 Spring MVC 提供的简单异常处理器 SimpleMappingExceptionResolver。
2. 实现 Spring 的异常处理接口 HandlerExceptionResolver,自定义自己的异常处理器。
3. 使用 @ExceptionHandler 注解实现异常处理`
```java
@ExceptionHandler({ ArithmeticException.class })
public String testArithmeticException(Exception e) {
System.out.println("打印错误信息 ===> ArithmeticException:" + e);
// 跳转到指定页面
return "error";
}
```cpp
全局异常:SimpleMappingExceptionResolver:springmvc-service
```java
<!--全局异常-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 定义默认的异常处理页面,当该异常类型注册时使用 -->
<property name="defaultErrorView" value="error"/>
<!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
<property name="exceptionAttribute" value="ex"/>
<!-- 定义需要特殊处理的异常,用类名或完全路径名作为key,异常页名作为值 -->
<property name="exceptionMappings">
<props>
<prop key="ArithmeticException">error</prop>
<!-- 在这里还可以继续扩展对不同异常类型的处理 -->
</props>
</property>
</bean>
```cpp
#### Spring mvc文件上传和下载
文件下载有以下两种实现方法:
- 通过超链接实现下载:实现简单,但暴露了下载文件的真实位置,并且只能下载 Web 应用程序所在目录下的文件,WEB-INF 目录除外。
- 利用程序编码实现下载:增强安全访问控制,可以下载除 Web 应用程序所在目录以外的文件,也可以将文件保存到数据库中。
文件上传是项目开发中最常见的功能之一,springMVC可以很好的支持文件上传,但是
SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。
前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;
**对表单中的enctype属性做个详细的说明:**
application/x-www=form-urlencoded:默认方式,只处理表单域中的value 属性值,采用这种编码方式的表单会将表单域中的值处理成URL编码式。multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。 text/plain:除了把空格转换为“+”号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
文件上传
导入包
```java
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!--导入api高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
```cpp
applicationContext.xml
```java
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
```cpp
文件上传
index.jsp
```java
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
```cpp
FileController
第一种
```java
package com.yuan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
@Controller
public class FileController {
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
//获取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
//如果文件名为空,直接回到首页!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名 : "+uploadFileName);
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream(); //文件输入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
//读取写出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
}
```cpp
第二种
```java
/*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的方法直接写文件(注意这个时候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
return "redirect:/index.jsp";
}
```cpp
文件下载
```java
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "基础语法.jpg";
//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、 读取文件--输入流
InputStream input=new FileInputStream(file);
//3、 写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}
```cpp
index,jsp
```html
<a href="/download">点击下载</a>
```cpp
#### 异步方式实现文件上传
jsp
```html
<%--
Created by IntelliJ IDEA.
User: 111
Date: 2022-01-19
Time: 19:07
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>评论发表页面</title>
<style>
#box {
width: 800px;
margin: 50px auto;
text-align: center;
padding: 10px;
border: 1px skyblue solid;
}
table {
margin-top: 20px;
width: 100%;
}
textarea{ resize:none;}
</style>
</head>
<body>
<div id="box">
<p style="margin-right:430px ">你现在所在的位置是:论文管理页面>>论文发表页面</p>
<form id="from" enctype="multipart/form-data" method="post" >
<input type="hidden" name="createdBy" value="${sessionScope.userId}">
<p>论文题目:<input type="text" name="title"/></p>
<p style="margin-right: 140px">类型:<select name="type">
<c:forEach items="${allTCode}" var="all">
<option value="${all.id}">${all.codeName}</option>
</c:forEach>
</select>
</p>
<p>
论文摘要:<textarea rows="3" cols="20" name="paperSummary">
</textarea>
</p>
<p style="margin-left: 90px">
评论内容: <input type="file" name="file" id="file"/>
</p>
<p><button type="submit">保存</button> <button>返回</button></p>
</form>
</div>
<script src="${pageContext.request.contextPath}/js/jquery-1.12.4.js"></script>
<script type="text/javascript">
$(function () {
$("#from").submit(function () {
// let str=$("#from").serialize()
let file =$("#file")[0].files[0]//获取文件
let title=$("[name='title']").val();
let type=$("[name='type']").val();
let paperSummary=$("[name='paperSummary']").val();
let createdBy=$("[name='createdBy']").val();
let formData=new FormData;
formData.append("file",file)
formData.append("title",title)
formData.append("type",type)
formData.append("paperSummary",paperSummary)
formData.append("createdBy",createdBy)
$.ajax({
url:"${pageContext.request.contextPath}/toInsert",
type:"post",//请求方式
async:'true',
cache:false,
data:formData,
contentType:false,
processData: false,
dataType:'json',
success:function (data) {
if (data>0){
alert("新增成功")
}else {
alert("新增失败")
}
}
})
return false;
})
})
</script>
</body>
</html>
```cpp
#### 后台代码
````java
/**
* 新增论文
* @return
*/
@RequestMapping("/toInsert")
@ResponseBody
public Object toInsert(TPaper tPaper, @RequestParam(value = "file",defaultValue = "",required = false) CommonsMultipartFile file,
HttpServletRequest request) throws IOException {
String fileName = file.getOriginalFilename();//获取文件名
System.out.println("上传文件名 : "+fileName);
//上传路径保存设置
String path = request.getSession().getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+realPath);
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
tPaper.setCreationDate(new Date());//获取当前时间
tPaper.setPaperPath(path);//设置保存路径
tPaper.setModifyDate(new Date());
System.err.println(tPaper.toString());
int row = tPaperService.inseret(tPaper);
System.err.println("===============>"+row);
if (row>0) {
return 2;
}else {
return -1;
}
}
mybatis分页插件
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- mybatis分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
同步controller
@Controller
@RequestMapping("/app")
public class AppInfoController {
@Autowired
private AppInfoService appInfoService;
/**
* 跳转至手游审核
*/
@RequestMapping("/appInfo")
public Object AppInfoInfo(Model model){
//从第一条开始 每页查询10条数据
PageHelper.startPage(1, 10);
Page<AppInfo> objects = (Page<AppInfo>) appInfoService.listInfos();
PageInfo<AppInfo> appInfo = new PageInfo<>(objects,10);
List<AppInfo> appInfos = appInfo.getList();
model.addAttribute("app",appInfos);
model.addAttribute("getTotal",appInfo.getTotal());
return "/backend/applist";
}
AjAX
@RequestMapping("/AppInfoInfo")
@ResponseBody
public List<AppInfo> AppInfoInfo(Model model){
//从第一条开始 每页查询10条数据
PageHelper.startPage(1, 10);
Page<AppInfo> objects = (Page<AppInfo>) appInfoService.listInfos();
PageInfo<AppInfo> appInfo = new PageInfo<>(objects,10);
//将用户信息放入appInfos对象里
List<AppInfo> appInfos = appInfo.getList();
model.addAttribute("app",appInfo);
model.addAttribute("getTotal",appInfo.getTotal());
return appInfos;
}
```cpp
# Spring MVC整合(1)
#### applicationContext.xml
```javascript
<?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
https://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>
```cpp
#### spring-dao.xml
```java
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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:自动化操作(自动化的加载配置文件,并且可以自动设置到对象种!)
这里用C3P0
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"/>
<property name="jdbcUrl" value="${url}"/>
<property name="user" value="${name}"/>
<property name="password" value="${password}"/>
<!--c3p0连接池的私有属性-->
<property name="maxPoolSize" value="13"/>
<property name="minPoolSize" value="10"/>
<!--关闭连接后不自动提交commit-->
<property name="autoCommitOnClose" value="false"/>
<!--获取连接超时时间-->
<property name="checkoutTimeout" value="100000"/>
<!--当前连接失败重试次数-->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!--SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--映入连接池-->
<property name="dataSource" ref="dataSource"/>
<!--绑定myabtis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--配置dao接口扫描包,动态的实现了Dao接口可以注入到Spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入SqlSessionFactory 对应上面的sqlSessionFactory id-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--要扫描的包-->
<property name="basePackage" value="com.yuan.mapper"/>
</bean>
</beans>
```cpp
#### spring-service.xml
```javascript
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--扫描service下的包-->
<context:component-scan base-package="com.yuan.service"/>
<!--将业务类,注入到Spring,可以通过配置,或注解实现 @Service-->
<bean id="deviceServiceImpl" class="com.yuan.service.impl.DeviceServiceImpl">
<property name="deviceMapper" ref="deviceMapper"/>
</bean>
<!--声明事物配置 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合aop配置事物置入-->
<!--配置事物类通知-->
<tx:advice id="interceptor" transaction-manager="transactionManager">
<!--给方法配置事物-->
<tx:attributes>
<!--一般配置*号即可-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事物切入-->
<aop:config>
<!--*.*(..) 代表里面的所有的类和所有的方法-->
<aop:pointcut id="pointcut" expression="execution(* com.yuan.service.impl.*.*(..))"/>
<aop:advisor advice-ref="interceptor" pointcut-ref="pointcut"/>
</aop:config>
</beans>
```cpp
#### spring-mvc.xml
```java
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.注解驱动-->
<mvc:annotation-driven/>
<!--2.静态资源过滤-->
<mvc:default-servlet-handler/>
<!--静态资源,扫描statics包-->
// <mvc:resources mapping="/statics/**" location="/statics/"/>
<!--扫描包:controller-->
<context:component-scan base-package="com.yuan.controller"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--json转换器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
<!--springmvc 统一解决json中文乱码问题-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</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"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
```cpp
#### mybatis-config.xml
```java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--配置数据源-->
<typeAliases>
<package name="com.yuan.pojo"/>
</typeAliases>
<!--注册xml-->
<mappers>
<package name="com.yuan.mapper"/>
</mappers>
</configuration>
```cpp
#### database.properties
```java
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/devicedb?useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong
name=root
password=root
```cpp
#### web.xml
```java
<?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">
<!--设置启动的默认跳转的页面-->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--DispatcherServlet-->
<servlet>
<servlet-name>springmvc</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>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--乱码过滤-->
<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>
<!--session 过期时间为15分钟-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
```cpp
#### pom.xml
```java
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>1.8</jdk.version>
</properties>
<!--依赖-->
<dependencies>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!--数据库连接池 c3p0-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!--Servlet jsp-->
<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.1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</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.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.13</version>
</dependency>
<!--导入小辣椒-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!--导入aop-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aspectj/aspectjrt -->
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!--导入fastJSON包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<!--MappingJackson2HttpMessageConverter将数据转为Json格式依赖-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.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>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
```cpp
#### Device
```javascript
/**
* 实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Device {
private int id; //主键id
private String deviceNo; //编号
private String deviceName;//设备名称
private int status;//运行状态
private String maintainDate;//日期
}
```cpp
#### DeviceMapper
```javascript
package com.yuan.mapper;
import com.yuan.pojo.Device;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 设备接口
*/
@Repository
public interface DeviceMapper {
/**
* 查询全部设备
* @return
*/
public List<Device> allList();
/**
* 根据设备编号查询
* @param id 查询名称
* @return
*/
public Device listDevice(@Param("id") int id);
/**
* 新增设备
* @param device 设备对象
* @return
*/
public int InsertDevice(Device device);
/**
*根据设备编号删除
* @param id 设备id
* @return
*/
public int DeleteDevice(@Param("id") int id);
/**
* 修改设备
* @param device 设备对象
* @return
*/
public int UpdateDevice(Device device);
/**
* 通过设备名称查询
* @param name
* @return
*/
public Device getDeviceName(@Param("name") String name);
/**
* 模糊查询
* @param name
* @return
*/
public List<Device> listDevices(@Param("name") String name);
}
```cpp
#### DeviceMapper.xml
```javascript
<?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.yuan.mapper.DeviceMapper">
<!--新增设备信息-->
<insert id="InsertDevice" parameterType="Device">
INSERT INTO devicedb.device (deviceNo, deviceName, status, maintainDate)
VALUES(#{deviceNo}, #{deviceName},#{status},#{maintainDate});
</insert>
<!--修改设备信息-->
<update id="UpdateDevice" parameterType="Device">
UPDATE devicedb.device SET deviceNo=#{deviceNo},
deviceName=#{deviceName},
status=#{status},
maintainDate=#{maintainDate} WHERE id=#{id};
</update>
<!--删除设备信息-->
<delete id="DeleteDevice" parameterType="int">
delete from device where id=#{id}
</delete>
<!--根据名称查询设备信息-->
<select id="listDevice" resultType="com.yuan.pojo.Device">
SELECT * FROM device
WHERE id=#{id};
</select>
<!--查询全部设备-->
<select id="allList" resultType="com.yuan.pojo.Device">
SELECT * FROM device
</select>
<!--通过设备名称查询-->
<select id="getDeviceName" resultType="com.yuan.pojo.Device">
SELECT * FROM device where deviceName =#{name}
</select>
<!--根据名称模糊查询-->
<select id="listDevices" resultType="com.yuan.pojo.Device">
select * from device
<where>
<if test="name!=null or name!=''">
deviceName like concat("%",#{name},"%")
</if>
</where>
</select>
</mapper>
```cpp
#### DeviceService
```javascript
package com.yuan.service;
import com.yuan.pojo.Device;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 设备实现类
*/
public interface DeviceService {
/**
* 查询全部设备
* @return
*/
public List<Device> allList();
/**
* 根据设备编号查询
* @param id 查询名称
* @return
*/
public Device listDevice(int id);
/**
* 新增设备
* @param device 设备对象
*/
public int InsertDevice(Device device);
/**
*根据设备编号删除
* @param id 设备id
* @return
*/
public int DeleteDevice(int id);
/**
* 修改设备
* @param device 设备对象
* @return
*/
public int UpdateDevice(Device device);
/**
* 通过设备名称查询
* @param name
* @return
*/
public Device getDeviceName(String name);
/**
* 模糊查询
* @param name
* @return
*/
public List<Device> listDevices( String name);
}
```cpp
#### DeviceServiceImpl
```javascript
package com.yuan.service.impl;
import com.yuan.mapper.DeviceMapper;
import com.yuan.pojo.Device;
import com.yuan.service.DeviceService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeviceServiceImpl implements DeviceService {
//调用Mapper类
@Autowired
public DeviceMapper deviceMapper;
public void setDeviceMapper(DeviceMapper deviceMapper) {
this.deviceMapper = deviceMapper;
}
/**
* 查询全部设备
* @return
*/
public List<Device> allList() {
return deviceMapper.allList();
}
/**
* 根据设备编号查询
* @param id 查询名称
* @return
*/
@Override
public Device listDevice(int id) {
return deviceMapper.listDevice(id);
}
/**
* 新增设备
* @param device 设备对象
* @return
*/
public int InsertDevice(Device device) {
return deviceMapper.InsertDevice(device);
}
/**
* 根据设备编号删除
* @param id 设备id
* @return
*/
public int DeleteDevice(int id) {
return deviceMapper.DeleteDevice(id);
}
/**
* 修改设备
* @param device 设备对象
* @return
*/
public int UpdateDevice(Device device) {
return deviceMapper.UpdateDevice(device);
}
/**
* 通过设备名称查询
* @param name
* @return
*/
@Override
public Device getDeviceName(String name) {
return deviceMapper.getDeviceName(name);
}
/**
* 模糊查询
* @param name
* @return
*/
@Override
public List<Device> listDevices(String name) {
return deviceMapper.listDevices(name);
}
}
```cpp
#### index.jsp
```javascript
<%--
Created by IntelliJ IDEA.
User: 111
Date: 2021-11-26
Time: 10:39
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<a href="${pageContext.request.contextPath}/device/allDevice">跳转到查询全部设备</a>
<a href="allDeviceAjax.jsp">跳转到查询全部设备使用Ajax</a>
</body>
</html>
```cpp
### 使用同步方式实现增删改查
#### DeviceController
```java
package com.yuan.controller;
import com.yuan.pojo.Device;
import com.yuan.service.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/device")
public class DeviceController {
//controller调service层
@Autowired
@Qualifier("deviceServiceImpl")
private DeviceService deviceService;
//查询全部设备,并且返回一个页面展示
@RequestMapping("/allDevice")
public String Device(Model model) {
List<Device> deviceList = deviceService.allList();
model.addAttribute("list",deviceList);
return "allDevice";
}
//跳转新增设备页面
@RequestMapping("/addDevice")
public String InsertDeviceList(){
return "addDevice";
}
//发送添加请求
@RequestMapping("/InsertDevice")
public String InsertDevice(Device device){
deviceService.InsertDevice(device);
return "redirect:/device/allDevice";//重定向device/allDevice页面
}
//跳转到toUpdate页面
@RequestMapping("/toUpdate")
public String UpDate(int id,Model model){
Device device = deviceService.listDevice(id);
model.addAttribute("deviceInfo",device);
return "toUpdate";
}
//修改设备提交
@RequestMapping("/UpdateDevices")
public String UpdateDevice(Device device){
deviceService.UpdateDevice(device);
System.out.println("执行修改方法");
return "redirect:/device/allDevice";
}
@RequestMapping("/DeleteDevice/{id}")
public String DeleteDevice(@PathVariable("id") int id){
deviceService.DeleteDevice(id);
System.out.println("执行了删除方法");
return "redirect:/device/allDevice";
}
//根据名称查询
@RequestMapping("/getDeviceName")
public String getDeviceName(String deviceName,Model model){
List<Device> list=new ArrayList<>();
if(deviceName==null||deviceName.equals("")){
list=deviceService.allList();
model.addAttribute("error", "未查到该设备");
}
Device device = deviceService.getDeviceName(deviceName);
list.add(device);
model.addAttribute("list",list);
return "allDevice";
}
}
```cpp
#### allDevice.jsp
```html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<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">
<h2><small>查询全部设备</small></h2>
</div>
<div class="row">
<div class="col-md-4 column">
<!--新增-->
<a class="btn btn-primary" href="${pageContext.request.contextPath}/device/addDevice">新增设备</a>
</div>
<div class="col-md-4 column"></div>
<div class="col-md-4 column">
<!--根据名称查询-->
<form class="form-inline" action="${pageContext.request.contextPath}/device/getDeviceName" method="post">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="deviceName" placeholder="输入设备名称">
</div>
</div>
<button type="submit" class="btn btn-primary">查询</button>
<span style="font-weight: bold;color: red">${error}</span>
</form>
</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>
<!--通过forEach遍历-->
<tbody>
<c:forEach var="device" items="${list}" >
<c:if test="${device.deviceName!=null}">
<tr>
<td hidden="hidden">${device.id}</td>
<td>${device.deviceNo}</td>
<td>${device.deviceName}</td>
<td>${device.status==0?"禁用":"启用"}</td>
<td>${device.maintainDate}</td>
<td><a href="${pageContext.request.contextPath}/device/toUpdate?id=${device.id}">修改</a> |
<a href="${pageContext.request.contextPath}/device/DeleteDevice/${device.id}">删除</a>
</td>
</tr>
</c:if>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
```cpp
#### addDevice.jsp
```html
<%--
Created by IntelliJ IDEA.
User: 111
Date: 2021-11-26
Time: 18:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<link href= "https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<html>
<head>
<title>新增设备</title>
</head>
<body>
<div class="container" style="width: 400px;margin: 0 auto">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h2><small>新增设备</small></h2>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/device/InsertDevice" method="post">
<!--name名称和数据库字段名称一一对应-->
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备编号</label>
<input type="text" class="form-control" name="deviceNo" placeholder="设备编号" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备名称</label>
<input type="text" class="form-control" name="deviceName" placeholder="设备名称" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">状态</label>
<input type="text" class="form-control" name="status" placeholder="设备状态:输入数字(0/1)" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">日期</label>
<input type="text" class="form-control" name="maintainDate" placeholder="设备日期" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="提交">
</div>
</form>
</div>
</body>
</html>
```cpp
#### toDevice.jsp
```html
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 111
Date: 2021-11-26
Time: 18:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<link href= "https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<html>
<head>
<title>修改设备</title>
</head>
<body>
<div class="container" style="width: 400px;margin: 0 auto">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h2><small>修改设备</small></h2>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/device/UpdateDevices" method="post">
<input type="hidden" class="form-control" name="id" value="${deviceInfo.id}" required>
<!--name名称和数据库字段名称一一对应-->
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备编号</label>
<input type="text" class="form-control" name="deviceNo" value="${deviceInfo.deviceNo}" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备名称</label>
<input type="text" class="form-control" name="deviceName" value="${deviceInfo.deviceName}" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">状态</label>
<input type="text" class="form-control" name="status" value="${deviceInfo.status}" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">日期</label>
<input type="text" class="form-control" name="maintainDate" value="${deviceInfo.maintainDate}" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
</html>
```cpp
### 使用异步Ajax实现
#### DeviceController2
```java
package com.yuan.controller;
import com.alibaba.fastjson.JSON;
import com.yuan.pojo.Device;
import com.yuan.service.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 用Ajax实现
*/
@Controller
//@RestController //@RestController注解相当于@ResponseBody + @Controller合在一起的作用。
public class DeviceController2 {
@Qualifier("deviceServiceImpl")
@Autowired
private DeviceService deviceService;
/**
* 根据标题模糊查询
* @param
* @return
*/
@RequestMapping("/allDeviceAjax")
@ResponseBody
public List<Device> allLists(String name){
System.err.println("参数"+name);
List<Device> deviceList=null;
if (name != null) {
deviceList= deviceService.listDevices(name);
}else {
deviceList= deviceService.listDevices("");
}
return deviceList;
}
/**
* 新增设备
* @param device
* @return
*/
@RequestMapping("/InsertDeviceAjax")
@ResponseBody
public int InsertDevice(Device device){
return deviceService.InsertDevice(device);
}
/**
* 删除设备
* @param id
* @return
*/
@RequestMapping("/DeleteDevice")
@ResponseBody
public int DeleteDevice(int id){
return deviceService.DeleteDevice(id);
}
@RequestMapping("/toUpdateAjax")
public String device(int id,Model model){
Device device = deviceService.listDevice(id);
model.addAttribute("deviceInfo",device);
return "toUpdateAjax";
}
/**
* 修改
* @param device
* @return
*/
@RequestMapping("/UpdateDevice")
@ResponseBody
public int UpdateDevice(Device device){
return deviceService.UpdateDevice(device);
}
}
```cpp
#### allDeviceAjax.jsp
```html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<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">
<h2><small>查询全部设备</small></h2>
</div>
<div class="row">
<div class="col-md-4 column">
<!--新增-->
<a class="btn btn-primary" href="addDeviceAjax.jsp">新增设备</a>
</div>
<div class="col-md-4 column"></div>
<div class="col-md-4 column">
<!--根据名称查询-->
<form class="form-inline" method="post" id="from">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="deviceName" placeholder="输入设备名称">
</div>
</div>
<button type="submit" class="btn btn-primary">查询</button>
</form>
</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>
<tbody id="dataList">
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script src="${pageContext.request.contextPath}js/jquery-1.12.4.js"></script>
<script>
$(function () {
data();
$("#from").submit(function () {
data();
$("[name='deviceName']").val()
return false;
})
function data() {
$.ajax({
url:"${pageContext.request.contextPath}/allDeviceAjax",
type:"post",
dataType:"json",
data:{
name:$("[name='deviceName']").val()
},
success:function (data) {
$("#dataList").empty();
$(data).each(function (i,e) {
$("#dataList").append(" <tr>\n" +
" <td hidden='hidden'>"+e.id+"</td>\n" +
" <td>"+e.deviceNo+"</td>\n" +
" <td>"+e.deviceName+"</td>\n" +
" <td>"+(e.status==0?"禁用":"启用")+"</td>\n" +
" <td>"+e.maintainDate+"</td>\n" +
" <td><a href='${pageContext.request.contextPath}/toUpdateAjax?id="+e.id+"'>修改</a> | \n" +
" <a href='javascript:void(0)' name='delete'>删除</a></td>\n" +
" </tr>")
})
//删除
$("[name='delete']").bind("click",function () {
let $Str=$(this).parent().parent()
$.post("${pageContext.request.contextPath}/DeleteDevice",
{id:$Str.find("td:eq(0)").text()},
function (data) {
if(data>0){
$Str.remove()
alert("删除成功")
}else {
alert("删除失败")
}
})
})
}
})
}
return false;
})
</script>
</body>
</html>
```cpp
#### addDeviceAjax.jsp
```html
<%--
Created by IntelliJ IDEA.
User: 111
Date: 2021-11-26
Time: 18:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<link href= "https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<html>
<head>
<title>新增设备</title>
</head>
<body>
<div class="container" style="width: 400px;margin: 0 auto">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h2><small>新增设备</small></h2>
</div>
</div>
</div>
<form action="" method="post" id="from">
<!--name名称和数据库字段名称一一对应-->
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备编号</label>
<input type="text" class="form-control" name="deviceNo" placeholder="设备编号" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备名称</label>
<input type="text" class="form-control" name="deviceName" placeholder="设备名称" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">状态</label>
<input type="text" class="form-control" name="status" placeholder="设备状态:输入数字(0/1)" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">日期</label>
<input type="text" class="form-control" name="maintainDate" placeholder="设备日期" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="提交">
</div>
</form>
</div>
<script src="js/jquery-1.12.4.js"></script>
<script>
$(function () {
$("#from").submit(function () {
let json=$("#from").serialize();
$.ajax({
url:"${pageContext.request.contextPath}/InsertDeviceAjax",
data:json,
success:function (data) {
if(data>0){
alert("新增成功");
location.href='allDeviceAjax.jsp';
}else {
alert("新增失败")
location.href='allDeviceAjax.jsp';
}
}
})
return false;
})
})
</script>
</body>
</html>
```cpp
#### toUpdateAjax.jsp
```html
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 111
Date: 2021-11-26
Time: 18:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<link href= "https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<html>
<head>
<title>修改设备</title>
</head>
<body>
<div class="container" style="width: 400px;margin: 0 auto">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h2><small>修改设备</small></h2>
</div>
</div>
</div>
<form method="post" id="from">
<input type="hidden" class="form-control" name="id" value="${deviceInfo.id}" required>
<!--name名称和数据库字段名称一一对应-->
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备编号</label>
<input type="text" class="form-control" name="deviceNo" value="${deviceInfo.deviceNo}" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">设备名称</label>
<input type="text" class="form-control" name="deviceName" value="${deviceInfo.deviceName}" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">状态</label>
<input type="text" class="form-control" name="status" value="${deviceInfo.status}" required>
</div>
<div class="form-group">
<%--@declare id="dname"--%><label for="Dname">日期</label>
<input type="text" class="form-control" name="maintainDate" value="${deviceInfo.maintainDate}" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
<script src="../../js/jquery-1.12.4.js"></script>
<script>
//修改
$(function () {
$("#from").submit(function () {
let $str=$(this).serialize();
$.ajax({
url:"${pageContext.request.contextPath}/UpdateDevice",
data:$str,
success:function (data) {
if(data>0){
alert("修改成功")
location.href='../allDeviceAjax.jsp';
}else {
alert("修改失败")
location.href='../allDeviceAjax.jsp';
}
}
})
return false;
})
})
</script>
</body>
</html>
```cpp
# Spring MVC整合实现分页(2)
## applicationContext.xml
```java
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:applicationContext-mybatis.xml"/>
<import resource="classpath:spring-service.xml"/>
<import resource="classpath:spring-mvc.xml"/>
</beans>
```cpp
## applicationContext-mybatis.xml
```java
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" scope="singleton">
<property name="url" value="${dbcp.url}"/>
<property name="driverClassName" value="${dbcp.driver}"/>
<property name="username" value="${dbcp.user}"/>
<property name="password" value="${dbcp.password}"/>
<property name="initialSize" value="${initialSize}"/>
<property name="maxActive" value="${maxActive}"/>
<property name="maxIdle" value="${maxIdle}"/>
<property name="minIdle" value="${minIdle}"/>
<property name="maxWait" value="${maxWait}"/>
<property name="removeAbandoned" value="${removeAbandoned}"/>
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}"/>
</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 对应上面的sqlSessionFactory id-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--扫描mapper-->
<property name="basePackage" value="com.votingsystemdb.mapper"/>
</bean>
</beans>
```cpp
## database.properties
```java
dbcp.driver=com.mysql.cj.jdbc.Driver
dbcp.url=jdbc:mysql://localhost:3306/votingsystem?useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong
dbcp.user=root
dbcp.password=root
minIdle=45
maxIdle=50
initialSize=5
maxActive=100
maxWait=100
removeAbandonedTimeout=180
removeAbandoned=true
```cpp
## log4j.properties
```java
log4j.rootLogger=debug,CONSOLE,file
#log4j.rootLogger=ERROR,ROLLING_FILE
log4j.logger.cn.cvs=debug
log4j.logger.org.apache.ibatis=debug
log4j.logger.org.mybatis.spring=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug
<br/>
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=debug
log4j.appender.CONSOLE.DatePattern=yyyy-MM-dd
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern= - (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
<br/>
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern=yyyy-MM-dd
#TestSSM项目名
log4j.appender.file.File=${TestSSM.root}/logs/log.log
log4j.appender.file.Append=true
log4j.appender.file.Threshold=debug
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern= - (%r ms) - %d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
<br/>
log4j.logger.com.opensymphony.xwork2=debug
```cpp
## mybatis-config.xml
```java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--配置数据源-->
<typeAliases>
<package name="com.votingsystemdb.pojo"/>
</typeAliases>
<!-- mybatis分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--分页合理话-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
<!--注册xml-->
<mappers>
<package name="com.votingsystemdb.mapper"/>
</mappers>
</configuration>
```cpp
## spring-mvc.xml
```java
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!---注解驱动-->
<mvc:annotation-driven/>
<!--静态资源过滤问题-->
<mvc:default-servlet-handler/>
<!--扫描controller-->
<context:component-scan base-package="com.votingsystemdb.controller"/>
<!--3,控制层注解-->
<mvc:annotation-driven>
<!--消息转换器-->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json;charset=UTF-8"/>
</bean>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json</value>
</list>
</property>
<!--date日期格式转换-->
<property name="features">
<list>
<value>WriteDateUseDateFormat</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--4,配置多视图解析器-->
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- 是否启用参数支持,默认为true(支持),即xxx?format=json、xml等形式。 -->
<property name="favorParameter" value="true"/>
<!-- favorPathExtension:是否支持扩展名,默认为true(支持),扩展名指xxx.json、xxx.xml等形式 -->
<property name="favorPathExtension" value="true"/>
<!-- 默认ContentType -->
<property name="defaultContentType" value="application/json"/>
<!-- 配置映射关系 -->
<!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用 -->
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
html=text/html
</value>
</property>
</bean>
<!--5,VIEW解析定义。内容协商视图解析器;根据contentNegotiationManager使用的不同mediaTypes决定不同的 view进行响应 默认使用json-->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<!-- 内容协商管理器 用于决定media type -->
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<!--指定默认视图解析-->
<property name="defaultViews">
<bean class="com.alibaba.fastjson.support.spring.FastJsonJsonView">
<property name="charset" value="utf-8"/>
</bean>
</property>
<!--视图解析器-->
<property name="viewResolvers">
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- <property name="prefix" value="/WEB-INF/jsp/"/>-->
<property name="suffix" value=".jsp"/>
</bean>
</property>
</bean>
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
</beans>
```cpp
## spring-service.xml
```java
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--扫描service-->
<context:component-scan base-package="com.votingsystemdb.service"/>
<!--事物配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--配置dataSource-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置aop-->
<tx:advice id="interceptor" transaction-manager="transactionManager">
<!--给事物事物方法配置-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事物切入-->
<aop:config>
<!--*.*(..) 代表里面的所有的类和所有的方法-->
<aop:pointcut id="pointcut" expression="execution(* com.votingsystemdb.service.impl.*.*(..)))"/>
<aop:advisor advice-ref="interceptor" pointcut-ref="pointcut"/>
</aop:config>
</beans>
```cpp
## web.xml
```java
<?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">
<!--设置启动的默认跳转的页面-->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--DispatcherServlet-->
<servlet>
<servlet-name>springmvc</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>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--乱码过滤-->
<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>
<!--session 过期时间为15分钟-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<!--日志输出-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
</web-app>
```cpp
## pom.xml
````java
<!--依赖-->
<dependencies>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!--数据库连接池 dbcp-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!--Servlet jsp-->
<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.1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</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.3.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.13</version>
</dependency>
<!--导入小辣椒-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!--导入aop-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aspectj/aspectjrt -->
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!--导入fastJSON包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<!--MappingJackson2HttpMessageConverter将数据转为Json格式依赖-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.12</version>
</dependency>
<!--分页查询-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!--导入api高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</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>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
SubjectsMapper
@Repository
public interface SubjectsMapper {
/**
* 查询所有主题
* @return
*/
List<Subjects> allSubjects();
}
SubjectsMapper.xml
<?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.votingsystemdb.mapper.SubjectsMapper">
<!--查询所有主题-->
<select id="allSubjects" resultType="com.votingsystemdb.pojo.Subjects">
SELECT * from `subjects`;
</select>
</mapper>
```cpp
## SubjectService
```java
public interface SubjectsService {
/**
* 查询所有主题
* @return
*/
List<Subjects> allSubjects();
}
```cpp
## SubjectServiceImpl
````java
@Service
public class SubjectsServiceImpl implements SubjectsService {
@Autowired
private SubjectsMapper subjectsMapper;
<br/>
/**
* 查询所有主题
*
* @return
*/
@Override
public List<Subjects> allSubjects() {
return subjectsMapper.allSubjects();
}
}
SubjectsController
@Controller
public class SubjectsController {
@Autowired
private SubjectsService subjectsService;
<br/>
/**
* 分页查询
* @param pageNum
* @param pageSize
* @return
*/
@RequestMapping("/allsubject")
@ResponseBody
public Object allsubject(
@RequestParam(value = "pageNum",defaultValue = "1",required = false) Integer pageNum,
@RequestParam(value = "pageSize", defaultValue = "3", required = false) Integer pageSize){
PageHelper.startPage(pageNum, pageSize);
Page<Subjects> subjects = (Page<Subjects>)subjectsService.allSubjects();
PageInfo<Subjects> subjectsInfo = new PageInfo<>(subjects,3);
return subjectsInfo;
}
}
```cpp
## index.jsp
```java
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>全部主题</title>
<style>
#box {
width: 800px;
margin: 0 auto;
text-align: center;
}
table {
margin-top: 20px;
width: 100%;
}
</style>
</head>
<body>
<div id="box">
<h3>全部主题</h3>
<table border="1">
<tr>
<th>序号</th>
<th>主题</th>
<th>投票/查看</th>
<th>创建时间</th>
</tr>
<tbody id="datalist">
</tbody>
</table>
<p id="dian"></p>
</div>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.12.4.js"></script>
<script>
function data(pageNum){
$.ajax({
url:"${pageContext.request.contextPath}/allsubject",
data:{
pageNum:pageNum
},
type:"GET",
dataType:"json",
success:function (data) {
// 当前页
let pageNum = data.pageNum;
// 总页数
let pags = data.pages;
$("#datalist").empty();
$(data.list).each(function (i,e) {
$("#datalist").append(" <tr>\n" +
" <td>"+e.id+"</td>\n" +
" <td><a href='${pageContext.request.contextPath}/getTitle?title="+e.title+"'>"+e.title+"</td>\n" +
" <td>"+e.totalVotes+"/"+e.viewTimes+"</td>\n" +
" <td>"+e.createDate+"</td>\n" +
" </tr>")
})
//$("#dian").html(" <a href='javascript:void(0)' onclick='data(1)'>首页</a>\n" +
// " <a href='javascript:void(0)' onclick='data("+pageNum-1+")'>上一页</a>\n" +
// " <a href='javascript:void(0)' onclick='data("+pageNum+1+")'>下一页</a>\n" +
// " <a href='javascript:void(0)' onclick='data("+pags+")'>尾页</a>\n" +
// " <span>共"+pags+"第"+pageNum+"页</span>")
//或者
$('#dian').html("<a href='javascript:data(1)'>首页</a> " +
"<a href='javascript:data("+(pageNum-1)+")'>上一页</a> " +
"<a href='javascript:data("+pageNum+1+")'>下一页</a> " +
"<a href='javascript:data("+pags+")' >尾页</a>");
}
})
}
$(function () {
data();
})
</script>
</body>
</html>