首先感谢动力节点和老师的教学分享!Respect!
学习视频来源:
B站:
https://www.bilibili.com/video/BV1oP4y1K7QT/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=07c8a1a7d89af39fe20c3a6894f5ff6a
文件资源:
主流框架 链接:https://pan.baidu.com/s/10HGe7wP1aed2HUCihc3-yQ?pwd=afjd 提取码:afjd
SpringMVC5 学习笔记
文章目录
一、SpringMVC概述
1. 什么是SpringMVC
它是基于MVC开发模式的框架,用来优化控制器。它是Spring家族的一员。它也具备IOC和AOP。
- 什么是MVC?
- 它是一种开发模式,它是模型视图控制器的简称。所有的web应用都是基于MVC开发。
- M:模型层,包含实体类,业务逻辑层,数据访问层
- V:视图层,html,javaScript,vue等都是视图层,用来显现数据
- C:控制器,它是用来接收客户端的请求,并返回响应到客户端的组件,Servlet就是组件
2. SpringMVC框架的优点
-
轻量级,基于MVC的框架
-
易于上手,容易理解,功能强大
-
它具备IOC和AOP
- 方便整合Strtus,MyBatis,Hiberate,JPA 等其他框架。
-
完全基于注解开发
- 在Controller, Service, Dao 都可以使用注解。方便灵活。
- 使用@Controller 创建处理器对象,
- @Service 创建业务对象,
- @Autowired 或者@Resource 在控制器类中注入 Service,在Service 类中注入 Dao。
-
SpringMVC优化的方向
-
SpringMVC执行的流程
执行流程说明:
-
向服务器发送HTTP请求,请求被前端控制器 DispatcherServlet 捕获。
-
DispatcherServlet 根据
<servlet-name>
中的配置对请求的URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用 HandlerMapping 获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以 HandlerExecutionChain 对象的形式返回。 -
DispatcherServlet 根据获得的Handler,选择一个合适的 HandlerAdapter。
-
提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
-
HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。
-
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。
-
数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。
-
数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。
-
-
Handler(Controller)执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。
-
根据返回的ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet。
-
ViewResolver 结合Model和View,来渲染视图。
-
视图负责将渲染结果返回给客户端
-
3. 基于注解的SpringMVC框架开发的步骤
-
新建项目,选择webapp模板。
-
修改目录,添加缺失的test,java,resources(两套),并修改目录属性
-
修改pom.xml文件,添加SpringMVC的依赖,添加Servlet的依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.shanglinsong</groupId> <artifactId>springmvc_001_demo</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>springmvc_001_demo Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <!-- SpringMVC依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!-- Servlet依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>springmvc_001_demo</finalName> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> </resources> </build> </project>
-
在/main/resources目录下利用XML的Spring模板添加springmvc.xml配置文件,指定包扫描,添加视图解析器。该文件名可以任意命名。推荐使用springmvc.xml。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--添加包扫描--> <context:component-scan base-package="com.shanglinsong.springmvc.controller"></context:component-scan> <!--添加视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--配置前缀--> <property name="prefix" value="/admin/"></property> <!--配置后缀--> <property name="suffix" value=".jsp"></property> </bean> </beans>
-
SpringMVC框架为了避免对于请求资源路径与扩展名上的冗余,在视图解析器
InternalResouceViewResolver 中引入了请求的前辍与后辍。而action中只需给出要跳转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接。
-
<context:component-scan>
: 用来进行包扫描,这里用于指定@Controller注解所在的包路径。
-
-
删除web.xml文件,新建web.xml(若版本无问题则不需要删除,删除原生web.xml文件的主要目的是为了防止版本过老无法支持框架运行)
-
在web.xml文件中注册springMVC框架(所有的web请求都是基于servlet的)
- 因为web的请求都是由Servlet来进行处理的,而SpringMVC的核心处理器就是一个DispatcherServlet,它负责接收客户端的请求,并根据请求的路径分派给对应的action(控制器)进行处理,处理结束后依然由核心处理器DispatcherServlet进行响应返回。
- 中央调度器的全限定性类名在导入的 Jar 文件 spring-webmvc-5.2.5.RELEASE.jar 的第一个包org.springframework.web.servlet下可找到。
<!--注册SpringMVC框架--> <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:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 指定拦截什么样的请求 http://localhost:8080/one http://localhost:8080/index.jsp http://localhost:8080/demo.action <a href="${pageContext.request.contextPath}/demo.action">访问服务器</a> --> <url-pattern>*.action</url-pattern> </servlet-mapping>
<param-value>classpath:springmvc.xml</param-value>
表示从类路径下加载SpringMVC的配置文件。<url-pattern>
指定拦截以.action结尾的请求,交给核心处理器DispatcherServlet处理。
-
在webapp目录下新建admin目录,在admin目录下新建main.jsp页面,删除index.jsp页面,并新建,发送请求给服务器
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/22 Time: 18:31 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>springmvc_001_demo</title> </head> <body> <a href="${pageContext.request.contextPath}/sls/hello.action">访问action</a> </body> </html>
-
在webapp目录上新添目录/admin。在/admin目录下新建main.jsp页面。用来进行服务器处理完毕后数据的回显。
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/22 Time: 18:34 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>main</title> </head> <body> <h2>main.......</h2> </body> </html>
-
开发HelloSpringMvc.java -->控制器(相当于以前的servlet)。这是一个普通的类,不用继承和实现接口。类中的每个方法就是一个具体的action控制器。
package com.shanglinsong.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.controller.HelloSpringMVC * @date 2023/1/22 * @since 1.0 */ @Controller //交给Spring去创建对象 @RequestMapping("/sls") public class HelloSpringMVC { /** * 以前的Servlet的规范 * protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {} * action中所有的功能实现都是由方法来完成的 * action方法的规范 * 1)访问权限是public * 2)方法的返回值任意,以返回String居多。 * 3)方法名称任意 * 4)方法可以没有参数,如果有可是任意类型,用来接收客户端提交上来的数据。 * 5)要使用@RequestMapping注解来声明一个访问的路径(名称) * */ @RequestMapping("/hello") public String one(){ System.out.println("服务器被访问到啦!"); return "main"; //可以直接跳到/admin/main.jsp页面上 } }
- @Controller:表示当前类为处理器,交给Spring容器去创建对象。
- @RequestMapping:表示路径映射。该注解可以加在类上相当于包名,还可以加在方法上相当于action的名称,都是来指定映射路径的。
- 其中:
- /sls 是类上的注解路径
- /hello 是方法上的注解路径
- 其中:
-
添加tomcat进行测试功能
二、SpringMVC注解式开发
1. 分析web请求
-
web请求执行的流程
核心处理器
index.jsp<--------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法
one.jsp <---------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法 -
DispatcherServlet要在web.xml文件中注册才可用。
2. @RequestMapping注解详解
2.1 指定模块名称
-
通过@RequestMapping 注解可以定义处理器对于请求的映射规则。该注解可以注解在方法上,也可以注解在类上,但意义是不同的。value 属性值常以“/”开始。@RequestMapping 的 value 属性用于定义所匹配请求的 URI。
-
一个@Controller 所注解的类中,可以定义多个处理器方法。当然,不同的处理器方法所匹配的 URI 是不同的。这些不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中。但若这些请求具有相同的 URI 部分,则这些相同的 URI部分可以被抽取到注解在类之上的@RequestMapping 的 value 属性中。此时的这个 URI 表示模块(相当于包)的名称。URI 的请求是相对于 Web 的根目录。换个角度说,要访问处理器的指定方法,必须要在方法指定 URI 之前加上处理器类前定义的模块名称。
-
此注解就是来映射服务器访问的路径。
-
此注解可加在方法上,是为此方法注册一个可以访问的名称(路径)
@RequestMapping("/demo") public String demo(){ System.out.println("服务器被访问到了......."); return "main"; //可以直接跳到/admin/main.jsp页面上 }
<a href="${pageContext.request.contextPath}/demo.action">访问服务器</a>
-
此注解可以加在类上,相当于是包名(虚拟路径),区分不同类中相同的action的名称
@RequestMapping("/user") public class DemoAction1 {..}
<a href="${pageContext.request.contextPath}/user/demo.action">访问服务器</a>
2.2 对请求提交方式的定义
-
对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交
-
方式进行限制,即只有满足该 method 属性指定的提交方式的请求,才会执行该被注解方法。Method 属性的取值为 RequestMethod 枚举常量。常用的为
RequestMethod.GET
与RequestMethod.POST
,分别表示提交方式的匹配规则为 GET 与 POST 提交。 -
此注解可区分get请求和post请求
@Controller
public class ReqAction {
@RequestMapping(value = "/req",method = RequestMethod.GET)
public String req(){
System.out.println("我是处理get请求的........");
return "main";
}
@RequestMapping(value = "/req" ,method = RequestMethod.POST)
public String req1(){
System.out.println("我是处理post请求的........");
return "main";
}
}
-
客户端浏览器常用的请求方式,及其提交方式有以下几种:
- 也就是说,只要指定了处理器方法匹配的请求提交方式为 POST,则相当于指定了请求发送的方式:要么使用表单请求,要么使用 AJAX 请求。其它请求方式被禁用。
- 当然,若不指定 method 属性,则无论是 GET 还是 POST 提交方式,均可匹配。即对于请求的提交方式无要求。
-
一一对应 举例:
-
GET请求:
jsp:
<form action="${pageContext.request.contextPath}/sls/hello1.action" method="get"> <input type="submit" value="get提交"> </form>
action:
@RequestMapping(value = "/hello1", method = RequestMethod.GET) public String reqGet(){ System.out.println("服务器被访问到啦,访问提交形式为GET!"); return "main"; }
请求结果:
-
POST请求:
jsp:
<form action="${pageContext.request.contextPath}/sls/hello1.action" method="post"> <input type="submit" value="post提交"> </form>
action:
@RequestMapping(value = "/hello1", method = RequestMethod.POST) public String reqPost(){ System.out.println("服务器被访问到啦,访问提交形式为POST!"); return "main"; }
请求结果:
-
3. 五种数据提交方式的优化
- 前四种数据注入的方式,会自动进行类型转换。但无法自动转换日期类型。
-
单个提交数据
在方法中声明一个和表单提交的参数名称相同的参数,由框架按照名称直接注入。
- 页面:
<form action="${pageContext.request.contextPath}/one.action"> 姓名:<input name="myname"><br> 年龄:<input name="age"><br> <input type="submit" value="提交"> </form>
- action:
@RequestMapping("/one") public String one(String myname,int age){ // ===>自动注入,并且类型转换 System.out.println("myname="+myname+",age="+(age+100)); return "main"; }
-
对象封装提交数据
在方法中声明一个自定义的实体类参数,框架调用实体类中相应的setter方法注入属性值,只要保证实体类中成员变量的名称与提交请求的name属性值一致即可。
在提交请求中,保证请求参数的名称与实体类中成员变量的名称一致,则可以自动创建对象,则可以自动提交数据,自动类型转换,自动封装数据到对象中。
- 实体类:
public class Users { private String name; private int age; getter and setter constructor toString }
- 页面:
<form action="${pageContext.request.contextPath}/two.action" method="post"> 姓名:<input name="name"><br> 年龄:<input name="age"><br> <input type="submit" value="提交"> </form>
- action:
@RequestMapping("/two") public String two(Users u){ System.out.println(u); return "main"; }
-
动态占位符提交
使用框架提供的一个注解@PathVariable,将请求url中的值作为参数进行提取,只能是超链接。restful风格下的数据提取方式。restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
仅限于超链接或地址拦提交数据。它是一杠一值,一杠一大括号,使用注解@PathVariable来解析。
- 页面:
<a href="${pageContext.request.contextPath}/three/张三/22.action">动态提交</a>
- action:
@RequestMapping("/three/{uname}/{uage}") public String three( @PathVariable("uname") // ===>用来解析路径中的请求参数 String name, @PathVariable("uage") int age){ System.out.println("name="+name+",age="+(age+100)); return "main"; }
-
映射名称不一致
提交请求参数与action方法的形参的名称不一致,使用注解@RequestParam来解析
- 页面:
<form action="${pageContext.request.contextPath}/sls/four.action" method="get"> 姓名:<input name="name"><br> 年龄:<input name="age"><br> <input type="submit" value="提交"> </form>
- action:
@RequestMapping("/four") public String four( @RequestParam("name") // ===>专门用来解决名称不一致的问题 String uname, @RequestParam("age") int uage){ System.out.println("uname="+uname+",uage="+(uage+100)); return "main"; }
-
手工提取数据
在方法参数中声明一个request对象,使用request的getParameter()获取表单提交的数据,这样得到的数据还要手工进行数据类型的转换。
- 页面:
<form action="${pageContext.request.contextPath}/sls/five.action" method="post"> 姓名:<input name="name"><br> 年龄:<input name="age"><br> <input type="submit" value="提交"> </form>
- action:
@RequestMapping("/five") public String five(HttpServletRequest request){ String name = request.getParameter("name"); int age = Integer.parseInt(request.getParameter("age")); System.out.println("name="+name+",age="+(age+100)); return "main"; }
4. 中文乱码解决方案
-
在web.xml文件中配置过滤器。
<filter> <filter-name>encode</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!-- 配置参数 private String encoding; private boolean forceRequestEncoding; private boolean forceResponseEncoding; --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encode</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
5. action方法的返回值
-
String:
- 客户端资源的地址,自动拼接前缀和后缀。还可以屏蔽自动拼接字符串,可以指定返回的路径。
- 处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址。
-
Object:
- 返回json格式的对象。自动将对象或集合转为json。使用的jackson工具进行转换,必须要添加jackson依赖。一般用于ajax请求。
- 处理器方法也可以返回 Object 对象。这个 Object 可以是 Integer,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。
- Ajax请求多用于Object返回值类型。由于转换器底层使用了Jackson 转换方式将对象转换为JSON 数据,所以需要添加Jackson的相关依赖。
-
void:
- 无返回值,一般用于ajax请求。
- 对于处理器方法返回 void 的应用场景,应用在AJAX 响应处理。若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。我们SSM整合案例中的分页使用的就是无返回值。
-
基本数据类型,用于ajax请求。
-
ModelAndView:
- 若处理器方法处理完后,需要跳转到其它资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中需要定义 ModelAndView 对象。
- 在使用时,若该处理器方法只是进行跳转而不传递数据,或只是传递数据而并不向任何资源跳转(如对页面的 Ajax 异步响应),此时若返回 ModelAndView,则将总是有一部分多余:要么 Model 多余,要么 View 多余。即此时返回 ModelAndView 将不合适。
- 较少使用。
6. 完成ajax请求访问服务器,返回学生集合
-
添加jackson依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.8</version> </dependency>
-
在webapp目录下新建js目录,添加jQuery函数库
-
在index.jsp页面上导入函数库
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/28 Time: 16:48 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>AjaxDemo</title> </head> <body> <script src="js/jquery-3.3.1.js"></script> <script> /*function show(){ $.ajax({ url: "${pageContext.request.contextPath}/ajax.action", type: "get", dataType: "json", success: function(stu){ $("#oneStu").html(stu.name + "----" + stu.age); } }) }*/ function show() { $.ajax({ url:"${pageContext.request.contextPath}/ajax.action", dataType:"json", type:"get", success:function (list) { // alert(list); var s=""; $.each(list,function (i,stu) { // alert(stu); s+=stu.name+"----"+stu.age+"<br>"; }); $("#mydiv").html(s); } }); } </script> <a href="javascript:show()">ajax访问服务器,返回一个学生</a> <br> <%--<div id="oneStu"></div>--%> <div id="mydiv"></div> </body> </html>
-
在action上添加注解@ResponseBody,用来处理ajax请求
package com.shanglinsong.springmvc.controller; import com.shanglinsong.springmvc.pojo.Student; import jdk.nashorn.internal.objects.annotations.Constructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.List; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.controller.AjaxDemo * @date 2023/1/28 * @since 1.0 */ @Controller public class AjaxDemo { /*@RequestMapping("/ajax") @ResponseBody public Object ajax(){ System.out.println("接收到了请求"); Student stu = new Student("张三", 22); return stu; }*/ //处理ajax请求,一定要加@ResponseBody @ResponseBody @RequestMapping("/ajax") public List<Student> ajax(){ Student stu1 = new Student("张三",22); Student stu2 = new Student("李四",24); Student stu3 = new Student("王五",23); List<Student> list = new ArrayList<>(); list.add(stu1); list.add(stu2); list.add(stu3); //调用json转换工具ObjectMapper进行转换 return list; //===>springmvc负责转换成json } }
-
在springmvc.xml文件中添加注解驱动
<mvc:annotationdriven/>
,它用来解析@ResponseBody注解<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.shanglinsong.springmvc.controller"></context:component-scan> <mvc:annotation-driven></mvc:annotation-driven> </beans>
-
测试结果:
-
网页端:
-
直接访问ajax.action,返回值为json格式数据
-
7. 四种跳转方式
-
默认的跳转是请求转发,直接跳转到jsp页面展示,
- 还可以使用框架提供的关键字redirect:,进行一个重定向操作,包括重定向页面和重定向action,
- 使用框架提供的关键字forward:,进行服务器内部转发操作,包括转发页面和转发action。
- 当使用redirect:和forward:关键字时,视图解析器中前缀后缀的拼接就无效了。
-
本质还是两种跳转:请求转发和重定向,衍生出四种是:
- 请求转发页面
@RequestMapping("/one") public String one(){ System.out.println("这是请求转发页面跳转........."); return "main"; //默认是请求转发,使用视图解析器拼接前缀后缀进行页面跳转 }
- 转发action
@RequestMapping("/two") public String two(){ System.out.println("这是请求转发action跳转........."); // /admin/ /other.action .jsp //forward: 这组字符串可以屏蔽前缀和后缀的拼接.实现请求转发跳转 return "forward:/other.action"; //默认是请求转发,使用视图解析器拼接前缀后缀进行页面跳转 }
- 重定向页面
@RequestMapping("/three") public String three(){ System.out.println("这是重定向页面......."); //redirect: 这组字符串可以屏蔽前缀和后缀的拼接.实现重定向跳转 return "redirect:/admin/main.jsp"; }
- 重定向action
@RequestMapping("/four") public String four(){ System.out.println("这是重定向action......."); //redirect: 这组字符串可以屏蔽前缀和后缀的拼接.实现重定向跳转 return "redirect:/other.action"; }
- 随便跳
@RequestMapping("/five") public String five(){ System.out.println("这是随便跳......."); return "forward:/fore/login.jsp"; }
-
测试
-
jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/28 Time: 19:06 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>forward and redirect</title> </head> <body> <a href="${pageContext.request.contextPath}/one.action">请求转发页面(默认)</a><br> <a href="${pageContext.request.contextPath}/two.action">请求转发action</a><br> <a href="${pageContext.request.contextPath}/three.action">重定向页面</a><br> <a href="${pageContext.request.contextPath}/four.action">重定向action</a><br> </body> </html>
-
JumpAction
package com.shanglinsong.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.controller.JumpAction * @date 2023/1/28 * @since 1.0 */ @Controller public class JumpAction { @RequestMapping("/one") public String one() { System.out.println("请求转发页面(默认)"); //以前的访问方式 //request.getRequestDispatcher("/admin/main.jsp").forward(request,response); //观察地址栏的变化: http://localhost:8080/one.action //return "main"; //默认的访问方式是自动拼接前缀和后缀进行跳转 return "forward:/admin/main.jsp";//只要使用了forward:就可以屏蔽前缀和后缀的拼接,自己手工构建返回的全部路径+.jsp } @RequestMapping("/two") public String two(){ System.out.println("请求转发action"); //观察地址栏的变化: http://localhost:8080/two.action return "forward:/other.action"; //不使用forward:,就会是这样的路径 /admin/other.action/.jsp } @RequestMapping("/three") public String three(){ System.out.println("重定向页面"); //观察地址栏的变化 http://localhost:8080/admin/main.jsp return "redirect:/admin/main.jsp";//只要使用了redirect:就可以屏蔽前缀和后缀的拼接 } @RequestMapping("/four") public String four(){ System.out.println("重定向action"); //观察地址栏的变化 http://localhost:8080/other.action return "redirect:/other.action";//只要使用了redirect:就可以屏蔽前缀和后缀的拼接 } }
-
OtherAction
package com.shanglinsong.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.controller.OtherAction * @date 2023/1/28 * @since 1.0 */ @Controller public class OtherAction { @RequestMapping("/other") public String other(){ return "other"; } }
-
8. SpringMVC默认的参数类型
-
不需要去创建,直接拿来使用即可。
- HttpServletRequest
- HttpServletResponse
- HttpSession
- Model
- Map
- ModelMap
-
做一个数据,传到main.jsp页面上
Users u = new Users("张三",22); //传递数据 request.setAttribute("requestUsers",u); session.setAttribute("sessionUsers",u); model.addAttribute("modelUsers",u); map.put("mapUsers",u); modelMap.addAttribute("modelMapUsers",u);
- 注意:Map,Model,ModelMap和request一样,都使用请求作用域进行数据传递。所以服务器端的跳转必须是请求转发。
-
测试
-
jsp
<a href="${pageContext.request.contextPath}/param.action">测试默认参数类型</a>
-
ParamAction
package com.shanglinsong.springmvc.controller; import com.shanglinsong.springmvc.pojo.Student; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.Map; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.controller.ParamAction * @date 2023/1/28 * @since 1.0 */ @Controller public class ParamAction { @RequestMapping("/param") public String param(HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model, ModelMap modelMap, Map map){ // Map, Model, ModelMap, request 都使用请求作用域进行传值, // 所以必须使用请求转发方式进行跳转,否则丢失数据 Student stu = new Student("张三", 22); request.setAttribute("requestStu", stu); session.setAttribute("sessionStu", stu); modelMap.addAttribute("modelMapStu", stu); model.addAttribute("modelStu", stu); map.put("mapStu", stu); // 切记请求转发,使用redirect重定向会丢失数据 return "main"; } }
-
main.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/28 Time: 19:11 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Main</title> </head> <body> <h2>Main........</h2> <p>requestStudent: ${requestStu}</p> <p>sessionStudent: ${sessionStu}</p> <p>modelMapStudent: ${modelMapStu}</p> <p>modelStudent: ${modelStu}</p> <p>mapStudent: ${mapStu}</p> </body> </html>
-
页面呈现
-
9.日期处理
-
日期的提交处理
-
jsp
<form action="${pageContext.request.contextPath}/mydate.action"> 日期:<input type="date" name="mydate"><br> <input type="submit" value="提交"> </form>
-
单个日期处理
要使用注解@DateTimeFormat,此注解必须搭配springmvc.xml文件中的
<mvc:annotationdriven标签>
@RequestMapping("/mydate") public String submitDate( HttpServletRequest request, @DateTimeFormat(pattern = "yyyy-MM-dd") Date mydate){ System.out.println(mydate); System.out.println(sdf.format(mydate)); request.setAttribute("mydate", sdf.format(mydate)); return "show"; }
-
类中全局日期处理
注册一个注解,用来解析本类中所有的日期类型,自动转换。
@InitBinder public void initBinder(WebDataBinder dataBinder){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true)); } @RequestMapping("/mydate") public String submitDate( HttpServletRequest request, // @DateTimeFormat(pattern = "yyyy-MM-dd") Date mydate){ System.out.println(mydate); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); System.out.println(sdf.format(mydate)); request.setAttribute("mydate", sdf.format(mydate)); return "show"; }
-
在类的成员setXXX()方法上使用@DateTimeFormat注解
@DateTimeFormat(pattern = "yyyy-MM-dd") public void setBirthday(Date birthday) { this.birthday = birthday; }
但这种解决方案要在每个使用日期类型的地方都去添加使用@DateTimeFormat注解,比较麻烦,我们可以使用@InitBinder注解来进行类中统一日期类型的处理。
-
-
日期的显示处理
在页面上显示好看的日期,必须使用JSTL。
步骤:
- 添加依赖jstl
<dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
-
在页面上导入标签库
-
如果是单个日期对象,直接转为好看的格式化的字符串进行显示.
-
如果是list中的实体类对象的成员变量是日期类型,则必须使用jstl进行显示.
-
<%--导入jstl核心标签库--%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%--导入jstl格式化标签库--%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
- 使用标签显示数据
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 10:14 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--导入jstl核心标签库--%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%--导入jstl格式化标签库--%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <html> <head> <title>show</title> </head> <body> <h3>mydate: ${mydate}</h3> <table width="800px" border="1"> <tr> <th>姓名</th> <th>年龄</th> <th>生日</th> </tr> <c:forEach items="${list}" var="stu"> <tr> <td>${stu.name}</td> <td>${stu.age}</td> <td>${stu.birthday}------ <fmt:formatDate value="${stu.birthday}" pattern="yyyy-MM-dd"></fmt:formatDate></td> </tr> </c:forEach> </table> </body> </html>
-
action
@RequestMapping("/list") public String list(HttpServletRequest request) throws ParseException { Student stu1 = new Student("张三", 22,sdf.parse("2000-01-01")); Student stu2 = new Student("李四", 33, sdf.parse("2001-08-11")); Student stu3 = new Student("王五", 44, sdf.parse("2002-09-21")); List<Student> list = new ArrayList<>(); list.add(stu1); list.add(stu2); list.add(stu3); request.setAttribute("list",list); return "show"; }
-
测试结果
10. 资源在WEB-INF目录下
-
此目录下的动态资源,不可直接访问,只能通过请求转发的方式进行访问 。
-
很多企业会将动态资源放在WEB-INF目录下,这样可以保证资源的安全性。在WEB-INF目录下的动态资源不可以直接访问,必须要通过请求转发的方式进行访问。这样避免了通过地址栏直接对资源的访问。
-
重定向也无法访问动态资源。
-
目录结构
-
默认index.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 10:47 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>index</title> </head> <body> <h1>登录</h1> <form action="${pageContext.request.contextPath}/login.action"> 姓名:<input type="text" name="name"><br> 密码:<input type="password" name="password"><br> <input type="submit" value="提交"> </form> </body> </html>
-
jsp/index.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 10:56 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>index</title> </head> <body> <h2>index......</h2> </body> </html>
-
jsp/login.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 10:57 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>login</title> </head> <body> <h2>login......</h2> <h2>${msg}</h2> </body> </html>
-
jsp/main.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 10:58 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>main</title> </head> <body> <h2>main......</h2> </body> </html>
-
ShowAction
package com.shanglinsong.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.HttpRequestHandler; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.controller.ShowAction * @date 2023/1/29 * @since 1.0 */ @Controller public class ShowAction { @RequestMapping("/showIndex") public String showIndex(){ System.out.println("访问到了index页面!"); return "index"; } @RequestMapping("/showLogin") public String showLogin(){ System.out.println("访问到了login页面!"); return "login"; } @RequestMapping("/showMain") public String showMain(){ System.out.println("访问到了main页面!"); return "main"; } @RequestMapping("/login") public String login(String name, String password, HttpServletRequest request){ if("admin".equals(name) && "123".equals(password)){ return "main"; } request.setAttribute("msg", "用户名或密码不正确!"); return "login"; } }
-
如此配置,网页将无法直接通过url对jsp文件进行访问,只能通过请求转发方式进行访问。
三、SpringMVC的拦截器
-
针对请求和响应进行的额外的处理。在请求和响应的过程中添加预处理,后处理和最终处理。
-
SpringMVC 中的 Interceptor 拦截器,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器执行处理器之前”。当然,在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器。
-
拦截器的应用场景
- 日志记录:记录请求信息的日志
- 权限检查,如登录检查
- 性能检测:检测方法的执行时间
-
拦截器的执行原理
1. 拦截器执行的时机
-
preHandle():
在请求被处理之前进行操作,预处理
- 该方法在处理器方法执行之前执行。
- 其返回值为 boolean,若为 true,则紧接着会执行处理器方法,且会将 afterCompletion()方法放入到一个专门的方法栈中等待执行。
-
postHandle():
在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果,后处理
- 该方法在处理器方法执行之后执行。
- 处理器方法若最终未被执行,则该方法不会执行。
- 由于该方法是在处理器方法执行完后执行,且该方法参数中包含 ModelAndView,所以该方法可以修改处理器方法的处理结果数据,且可以修改跳转方向。
-
afterCompletion():
所有的请求响应结束后执行善后工作,清理对象,关闭资源 ,最终处理。
- 当preHandle()方法返回 true 时,会将该方法放到专门的方法栈中,等到对请求进行响应的所有工作完成之后才执行该方法。即该方法是在中央调度器渲染(数据填充)了响应页面之后执行的,此时对 ModelAndView 再操作也对响应无济于事。
- afterCompletion 最后执行的方法,清除资源,例如在 Controller 方法中加入数据等。
2. 拦截器实现的两种方式
- 继承HandlerInterceptorAdapter的父类
- 实现HandlerInterceptor接口,实现的接口,推荐使用实现接口的方式
3. 拦截器实现的步骤
-
修改web.xml文件中请求路径
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
目录结构
-
改造登录方法,在session中存储用户信息,用于进行权限验证
package com.shanglinsong.springmvc.controller; import com.shanglinsong.springmvc.pojo.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpSession; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.controller.LearnInterceptor * @date 2023/1/29 * @since 1.0 */ @Controller public class LearnInterceptor { // 通过请求转发跳到WEB-INF目录下的资源上 login.jsp @RequestMapping(value = "/login", method = RequestMethod.GET) public String show(){ return "login"; } // 验证登录 @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(User user, HttpSession session){ if ("admin".equalsIgnoreCase(user.getUsername()) && "admin".equalsIgnoreCase(user.getPassword())){ // 将用户数据封装在session中 session.setAttribute("user", user); // 跳转值主页 return "main"; } session.setAttribute("msg", "用户名或密码不正确"); return "login"; } // 访问主页 @RequestMapping("/main") public String toMain(){ return "main"; } // 退出功能 @RequestMapping("/logout") public String logout(HttpSession session){ session.invalidate(); return "login"; } }
-
开发拦截器的功能。实现HandlerInterceptor接口,重写preHandle()方法
package com.shanglinsong.springmvc.interceptor; import com.shanglinsong.springmvc.pojo.User; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.springmvc.interceptor.LoginInterceptor * @date 2023/1/29 * @since 1.0 */ public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("======================="); // 通过取出session中的user对象,来判断是否登录过 HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); if (null != user){ return true; } // 不符合登录条件的请求,给出提示,打回到登录页面 request.setAttribute("msg", "您还没有登录,请先登录"); request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); return false; } }
-
在springmvc.xml文件中注册拦截器
<!-- 注册拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 配置拦截的路径(哪些请求被拦截) --> <mvc:mapping path="/**"/> <!-- 设置放行的请求 --> <mvc:exclude-mapping path="/login"/> <mvc:exclude-mapping path="/showLogin"/> <!-- 设置进行功能处理的拦截器类 --> <bean class="com.shanglinsong.springmvc.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
-
index.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 14:27 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>首页</title> </head> <body> <h1>欢迎进入系统!</h1> <form action="${pageContext.request.contextPath}/login"> <input type="submit" value="点击进入登录界面"> </form> </body> </html>
-
login.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 14:32 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录界面</title> </head> <body> <h2>登录</h2> <form action="${pageContext.request.contextPath}/login" method="post"> 用户名:<input type="text" name="username"><br> 密 码:<input type="password" name="password"><br> <input type="submit" value="登录"> <input type="reset" value="重置"> </form> <h3>${msg}</h3> </body> </html>
-
直接通过url访问main
-
输入错误
-
-
main.jsp
<%-- Created by IntelliJ IDEA. User: ShiningSong Date: 2023/1/29 Time: 14:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>main</title> </head> <body> <h2>${user.getUsername()}好,欢迎回来</h2> <form action="${pageContext.request.contextPath}/logout"> <input type="submit" value="退出登录"> </form> </body> </html>
-
点击退出登录返回至login界面,此时再通过url访问main
-
四、SSM整合的步骤
-
建库,建表
-
使用Navicat执行语句生成数据库以及表
/* Navicat Premium Data Transfer Source Server : zar Source Server Type : MySQL Source Server Version : 80022 Source Host : localhost:3306 Source Schema : ssmusers Target Server Type : MySQL Target Server Version : 80022 File Encoding : 65001 Date: 26/06/2021 16:26:14 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; CREATE DATABASE IF NOT EXISTS `ssmuser` DEFAULT CHARACTER SET utf8; USE `ssmuser`; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `card_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `card_no` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `user_sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `user_age` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `user_role` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`user_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('15968162087363060', '身份证', '114264195202156467', '张三', '男', '30', '办事人员和有关人员'); INSERT INTO `user` VALUES ('15968162346981977', '护照', 'A32532654', '李四', '男', '29', '不便分类的其他从业人员'); INSERT INTO `user` VALUES ('15968162893439470', '身份证', '112344198709094532', '王五', '男', '31', '农、林、牧、渔、水利业生产人员'); INSERT INTO `user` VALUES ('15968163245457143', '身份证', '453234199909094532', '赵六', '男', '34', '未知'); INSERT INTO `user` VALUES ('15968163514764733', '军官证', '军7657868', '钱七', '女', '23', '不便分类的其他从业人员'); INSERT INTO `user` VALUES ('15968165113694372', '台湾往来大陆通行证', '43256786', '周八', '女', '48', '生产、运输设备操作人员及有关人员'); INSERT INTO `user` VALUES ('15968165371931786', '港澳居民通行证', 'C98767665', '吴九', '女', '35', '不便分类的其他从业人员'); INSERT INTO `user` VALUES ('15968941217553030', '身份证', '343546199801018768', '郑十', '男', '22', '军人'); INSERT INTO `user` VALUES ('15968943937844616', '身份证', '445453199603025756', '冯十一', '女', '31', '不便分类的其他从业人员'); INSERT INTO `user` VALUES ('15968944123869023', '护照', 'B54322654', '陈十二', '女', '39', '农、林、牧、渔、水利业生产人员'); INSERT INTO `user` VALUES ('15968953962316864', '身份证', '110232199505056789', '朱十三', '女', '33', '商业、服务业人员'); INSERT INTO `user` VALUES ('15968954638794962', '身份证', '110654196604079098', '孔十四', '女', '29', '生产、运输设备操作人员及有关人员'); SET FOREIGN_KEY_CHECKS = 1;
-
执行结果
-
-
新建Maven项目,选择webapp模板
-
修改目录,完成结构如下:
-
修改pom.xml文件(使用老师提供)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.shanglinsong</groupId> <artifactId>springmvc_007_ssm</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>springmvc_007_ssm Maven Webapp</name> <url>http://maven.apache.org</url> <!-- 集中定义依赖版本号 --> <properties> <junit.version>4.12</junit.version> <spring.version>5.1.2.RELEASE</spring.version> <mybatis.version>3.2.8</mybatis.version> <mybatis.spring.version>1.2.2</mybatis.spring.version> <mybatis.paginator.version>1.2.15</mybatis.paginator.version> <mysql.version>8.0.17</mysql.version> <slf4j.version>1.6.4</slf4j.version> <druid.version>1.0.9</druid.version> <pagehelper.version>5.1.2</pagehelper.version> <jstl.version>1.2</jstl.version> <servlet-api.version>3.0.1</servlet-api.version> <jsp-api.version>2.0</jsp-api.version> <jackson.version>2.9.6</jackson.version> </properties> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.11</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20140107</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis.spring.version}</version> </dependency> <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artifactId> <version>${mybatis.paginator.version}</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- 德鲁伊数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- jsp相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> </dependency> <!-- json处理工具包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.28</version> </dependency> <!-- 文件上传用 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> </dependencies> <build> <finalName>springmvc_007_ssm</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <filtering>false</filtering> </resource> </resources> </build> </project>
-
添加jdbc.properties属性文件
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssmuser?serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=123
-
添加SqlMapConfig.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> <!--设置日志输出语句,显示相应操作的sql语名--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!-- 分页插件 --> <!--<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins>--> </configuration>
-
添加applicationContext_mapper.xml文件(数据访问层的核心配置文件)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <!-- 读取jdbc.properties属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <!-- 创建数据源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 创建SqlSessionFactoryBean --> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置数据源 --> <property name="dataSource" ref="dataSource"></property> <!-- 配置mybatis的核心配置文件 --> <property name="configLocation" value="classpath:SqlMapConfig.xml"></property> <!--注册实体类--> <property name="typeAliasesPackage" value="com.shanglinsong.ssm.pojo"></property> </bean> <!-- 创建mapper文件的扫描器--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.shanglinsong.ssm.mapper"></property> </bean> </beans>
-
添加applicationContext_service.xml文件(业务逻辑层的核心配置文件)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 设置业务逻辑层的包扫描器, 目的是在指定路径下,使用@Service注解的类,Spring负责创建对象,并添加依赖--> <context:component-scan base-package="com.shanglinsong.ssm.service.impl"></context:component-scan> <!-- 设置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 添加事务切面 --> <tx:advice id="myadvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*select*" read-only="true"/> <tx:method name="*find*" read-only="true"/> <tx:method name="*get*" read-only="true"/> <tx:method name="*search*" read-only="true"/> <tx:method name="*insert*" propagation="REQUIRED"/> <tx:method name="*save*" propagation="REQUIRED"/> <tx:method name="*add*" propagation="REQUIRED"/> <tx:method name="*delete*" propagation="REQUIRED"/> <tx:method name="*remove*" propagation="REQUIRED"/> <tx:method name="*drop*" propagation="REQUIRED"/> <tx:method name="*clear*" propagation="REQUIRED"/> <tx:method name="*update*" propagation="REQUIRED"/> <tx:method name="*modify*" propagation="REQUIRED"/> <tx:method name="*change*" propagation="REQUIRED"/> <tx:method name="*set*" propagation="REQUIRED"/> <tx:method name="**" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!-- 完成切面的切入点和织入 --> <aop:config> <aop:pointcut id="mypointcut" expression="execution(* com.shanglinsong.ssm.service.impl.*.*(..))"/> <aop:advisor advice-ref="myadvice" pointcut-ref="mypointcut"></aop:advisor> </aop:config> </beans>
-
添加spirngmvc.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 添加包扫描器 --> <context:component-scan base-package="com.shanglinsong.ssm.controller"></context:component-scan> <!-- 添加视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/admin/"></property> <!-- 后缀 --> <property name="suffix" value=".jsp"></property> </bean> <!-- 设置文件上传核心组件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean> <!-- 设置注解驱动 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 解决跨域问题 --> <mvc:cors> <mvc:mapping path="/**" allowed-origins="*" allowed-methods="POST,GET,OPTIONS,DELETE,PUT" allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With" allow-credentials="true"></mvc:mapping> </mvc:cors> </beans>
- 注意解决跨域问题.
什么是跨域?
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域.
域名:
主域名不同 http://www.baidu.com/index.html -->http://www.sina.com/test.js
子域名不同 http://www.666.baidu.com/index.html -->http://www.555.baidu.com/test.js
域名和域名ip http://www.baidu.com/index.html -->http://180.149.132.47/test.js
端口:
http://www.baidu.com:8080/index.html–> http://www.baidu.com:8081/test.js
协议:
http://www.baidu.com:8080/index.html–> https://www.baidu.com:8080/test.js
备注:
- 端口和协议的不同,只能通过后台来解决
- localhost和127.0.0.1虽然都指向本机,但也属于跨域
- 另外一种解决方案是在控制器上添加@CrossOrigin注解.
- 或者自定义过滤器,进行跨域处理.
-
删除web.xml文件,新建,改名,设置中文编码,并注册spirngmvc框架,并注册Spring框架
<?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"> <!-- 添加字符编码过滤器 --> <filter> <filter-name>encode</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!-- private String encoding; private boolean forceRequestEncoding; private boolean forceResponseEncoding; --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceRequestEncoding</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encode</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 注册SpringMVC框架 --> <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:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 注册Spring框架 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext_*.xml</param-value> </context-param> </web-app>
-
新建实体类user
package com.shanglinsong.ssm.pojo; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.ssm.pojo.User * @date 2023/1/29 * @since 1.0 */ public class User { private String userId; // 用户id private String cardType; // 证件类型 private String cardNo; // 证件号码 private String userName; // 用户姓名 private String userSex; // 用户性别 private String userAge; // 用户年龄 private String userRole; // 用户角色 @Override public String toString() { return "User{" + "userId='" + userId + '\'' + ", cardType='" + cardType + '\'' + ", cardNo='" + cardNo + '\'' + ", userName='" + userName + '\'' + ", userSex='" + userSex + '\'' + ", userAge='" + userAge + '\'' + ", userRole='" + userRole + '\'' + '}'; } public User() { } public User(String userId, String cardType, String cardNo, String userName, String userSex, String userAge, String userRole) { this.userId = userId; this.cardType = cardType; this.cardNo = cardNo; this.userName = userName; this.userSex = userSex; this.userAge = userAge; this.userRole = userRole; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getCardType() { return cardType; } public void setCardType(String cardType) { this.cardType = cardType; } public String getCardNo() { return cardNo; } public void setCardNo(String cardNo) { this.cardNo = cardNo; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserSex() { return userSex; } public void setUserSex(String userSex) { this.userSex = userSex; } public String getUserAge() { return userAge; } public void setUserAge(String userAge) { this.userAge = userAge; } public String getUserRole() { return userRole; } public void setUserRole(String userRole) { this.userRole = userRole; } }
-
新建UserMapper.java接口
package com.shanglinsong.ssm.mapper; import com.shanglinsong.ssm.pojo.User; import org.apache.ibatis.annotations.Param; import java.util.List; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.ssm.mapper.UserMapper * @date 2023/1/29 * @since 1.0 */ public interface UserMapper { /** * 分页查询 User * @param startRows 起始页 * @return */ List<User> queryUserPage(Integer startRows); /** * 分页查询 User 带条件 * @param userName * @param userSex * @param startRows * @return */ List<User> selectUserPage( @Param("userName") String userName, @Param("userSex") String userSex, @Param("startRows") Integer startRows ); /** * 查询 User 个数 * @param userName * @param userSex * @return */ Integer getRowCount( @Param("userName") String userName, @Param("userSex") String userSex ); /** * 添加 User * @param user * @return */ Integer createUser(User user); /** * 根据 userId 删除 User * @param userId * @return */ Integer deleteUserById(String userId); /** * 根据 userId 批量删除 User * @param userIds * @return */ Integer deleteUserByIdList( @Param("list") List userIds ); /** * 根据 userId 更新 User * @param user * @return */ Integer updateUserById(User user); }
-
新建UserMapper.xml实现增删改查所有功能
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.shanglinsong.ssm.mapper.UserMapper"> <resultMap id="BaseResultMap" type="com.shanglinsong.ssm.pojo.User"> <id property="userId" column="user_id" jdbcType="VARCHAR"></id> <result property="cardType" column="card_type" jdbcType="VARCHAR"></result> <result property="cardNo" column="card_no" jdbcType="VARCHAR"></result> <result property="userName" column="user_name" jdbcType="VARCHAR"></result> <result property="userSex" column="user_sex" jdbcType="VARCHAR"></result> <result property="userAge" column="user_age" jdbcType="VARCHAR"></result> <result property="userRole" column="user_role" jdbcType="VARCHAR"></result> </resultMap> <sql id="Base_Column_List"> user_id, card_type, card_no, user_name, user_sex, user_age, user_role </sql> <!-- 分页查询 User List<User> queryUserPage(Integer startRows); --> <select id="queryUserPage" resultMap="BaseResultMap" parameterType="Integer"> select <include refid="Base_Column_List"/> from user order by user_id desc limit #{startRows, jdbcType=INTEGER}, 5 </select> <!-- 分页查询 User 带条件 List<User> selectUserPage( @Param("userName") String userName, @Param("userSex") String userSex, @Param("startRows") String startRows ); --> <select id="selectUserPage" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from user <where> <if test="userName != null and userName != ''"> and user_name like concat("%", #{userName}, "%") </if> <if test="userSex != null and userSex != ''"> and user_sex = #{userSex} </if> </where> order by user_id desc limit #{startRows, jdbcType=INTEGER}, 5 </select> <!-- 查询 User 个数 Integer getRowCount( @Param("userName") String userName, @Param("userSex") String userSex ); --> <select id="getRowCount" resultType="java.lang.Integer"> select count(*) from user <where> <if test="userName != null and userName != ''"> and user_name like concat("%", #{userName}, "%") </if> <if test="userSex != null and userSex != ''"> and user_sex = #{userSex} </if> </where> </select> <!-- 添加 User Integer createUser(User user); --> <insert id="createUser" parameterType="com.shanglinsong.ssm.pojo.User"> insert into user (<include refid="Base_Column_List"/>) values (#{userId}, #{cardType}, #{cardNo}, #{userName}, #{userSex}, #{userAge}, #{userRole}) </insert> <!-- 根据 userId 删除 User Integer deleteUserById(String userId); --> <delete id="deleteUserById" parameterType="String"> delete from user where user_id = #{userId, jdbcType=VARCHAR} </delete> <!-- 根据 userId 批量删除 User Integer deleteUserByIdList( @Param("list") List userIds ); --> <delete id="deleteUserByIdList" parameterType="java.util.List"> delete from user where user_id in <foreach collection="list" item="item" index="index" open="(" close=")" separator=","> #{item, jdbcType=VARCHAR} </foreach> </delete> <!-- 根据 userId 更新 User Integer updateUserById(User user); --> <update id="updateUserById" parameterType="com.shanglinsong.ssm.pojo.User"> update user <set> <if test="cardNo != null"> card_no = #{cardNo, jdbcType=VARCHAR}, </if> <if test="cardType != null"> card_type = #{cardType, jdbcType=VARCHAR}, </if> <if test="userName != null"> user_name = #{userName, jdbcType=VARCHAR}, </if> <if test="userSex != null"> user_sex = #{userSex, jdbcType=VARCHAR}, </if> <if test="userAge != null"> user_age = #{userAge, jdbcType=VARCHAR}, </if> <if test="userRole != null"> user_role = #{userRole, jdbcType=VARCHAR} </if> </set> where 1 = 1 and user_id = #{userId, jdbcType=VARCHAR} </update> </mapper>
-
新建service接口和实现类
-
com.shanglinsong.ssm.service.UserService
package com.shanglinsong.ssm.service; import com.shanglinsong.ssm.pojo.User; import org.apache.ibatis.annotations.Param; import java.util.List; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.ssm.service.UserService * @date 2023/1/30 * @since 1.0 */ public interface UserService { /** * 分页查询 User * @param startRows 起始页 * @return */ List<User> queryUserPage(Integer startRows); /** * 分页查询 User 带条件 * @param userName * @param userSex * @param startRows * @return */ List<User> selectUserPage( @Param("userName") String userName, @Param("userSex") String userSex, @Param("startRow") Integer startRows ); /** * 查询 User 个数 * @param userName * @param userSex * @return */ Integer getRowCount( @Param("userName") String userName, @Param("userSex") String userSex ); /** * 添加 User * @param user * @return */ Integer createUser(User user); /** * 根据 userId 删除 User * @param userId * @return */ Integer deleteUserById(String userId); /** * 根据 userId 批量删除 User * @param userIds * @return */ Integer deleteUserByIdList( @Param("list") List userIds ); /** * 根据 userId 更新 User * @param user * @return */ Integer updateUserById(User user); }
-
com.shanglinsong.ssm.service.impl.UserServiceImpl
package com.shanglinsong.ssm.service.impl; import com.shanglinsong.ssm.mapper.UserMapper; import com.shanglinsong.ssm.pojo.User; import com.shanglinsong.ssm.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.ssm.service.impl.UserServiceImpl * @date 2023/1/30 * @since 1.0 */ @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> queryUserPage(Integer startRows) { return userMapper.queryUserPage(startRows); } @Override public List<User> selectUserPage(String userName, String userSex, Integer startRows) { return userMapper.selectUserPage(userName, userSex, startRows); } @Override public Integer getRowCount(String userName, String userSex) { return userMapper.getRowCount(userName, userSex); } @Override public Integer createUser(User user) { return userMapper.createUser(user); } @Override public Integer deleteUserById(String userId) { return userMapper.deleteUserById(userId); } @Override public Integer deleteUserByIdList(List userIds) { return userMapper.deleteUserByIdList(userIds); } @Override public Integer updateUserById(User user) { return userMapper.updateUserById(user); } }
-
-
新建测试类,完成所有功能的测试
-
完整代码
package com.shanglinsong.ssm.test; import com.shanglinsong.ssm.pojo.User; import com.shanglinsong.ssm.service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.ArrayList; import java.util.List; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.ssm.test.SSMTest * @date 2023/1/30 * @since 1.0 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext_mapper.xml", "classpath:applicationContext_service.xml"}) public class SSMTest { @Autowired private UserService userService; // 根据 userId 更新 User @Test public void testUpdateUserById(){ User updateUser = new User("22222222222", "发财证", "888888888888888888", "shanglinsong", "男", "30", "架构师"); Integer count = userService.updateUserById(updateUser); System.out.println(count == 1? "修改命运成功!": "修改失败!继续加油吧!"); } // 根据 userId 批量删除 User @Test public void testDeleteUserByIdList(){ ArrayList<String> userIds = new ArrayList<>(); userIds.add("12345678910"); userIds.add("12345678911"); userIds.add("22222222222"); // System.out.println(userIds); Integer count = userService.deleteUserByIdList(userIds); System.out.println(count == 3 ? "删除成功!": "删除失败!"); } // 根据 userId 删除 User @Test public void testDeleteUserById(){ Integer count = userService.deleteUserById("12345678910"); System.out.println(count == 1 ? "幸运星删除成功": "幸运星删除失败"); count += userService.deleteUserById("12345678911"); System.out.println(count == 2 ? "倒霉蛋删除成功": "倒霉蛋删除失败"); count += userService.deleteUserById("22222222222"); System.out.println(count == 3 ? "二逼shanglinsong删除成功": "二逼shanglinsong删除失败"); } //添加 User /* private String userId; // 用户id private String cardType; // 证件类型 private String cardNo; // 证件号码 private String userName; // 用户姓名 private String userSex; // 用户性别 private String userAge; // 用户年龄 private String userRole; // 用户角色 */ @Test public void testCreateUser(){ User user1 = new User("12345678910", "身份证", "66666620000101662X", "幸运星", "女", "23", "董事长"); User user2 = new User("12345678911", "身份证", "44444419991231221X", "倒霉蛋", "男", "23", "研究僧"); User user3 = new User("22222222222", "二逼证", "222222222222222222", "shanglinsong", "男", "26", "无业游民"); Integer count = userService.createUser(user1); System.out.println(count == 1 ? "幸运星添加成功": "幸运星添加失败"); count += userService.createUser(user2); System.out.println(count == 2 ? "倒霉蛋添加成功": "倒霉蛋添加失败"); count += userService.createUser(user3); System.out.println(count == 3 ? "二逼shanglinsong添加成功": "二逼shanglinsong添加失败"); } // 查询 User 个数 @Test public void testGetRowCount(){ Integer rowCount = userService.getRowCount(null, null); System.out.println("一共有" + rowCount + "条记录"); } // 分页查询 User 带条件 @Test public void testSelectUserPage(){ List<User> users = userService.selectUserPage("十", "女", 0); users.forEach(user -> System.out.println(user)); } // 分页查询 User @Test public void testQueryUserPage(){ List<User> users = userService.queryUserPage(0); users.forEach(user -> System.out.println(user)); } }
-
分页查询 User
@Test public void testQueryUserPage(){ List<User> users = userService.queryUserPage(0); users.forEach(user -> System.out.println(user)); }
执行结果:
-
分页查询 User 带条件
@Test public void testSelectUserPage(){ List<User> users = userService.selectUserPage("十", "女", 0); users.forEach(user -> System.out.println(user)); }
执行结果:
-
查询 User 个数
@Test public void testGetRowCount(){ Integer rowCount = userService.getRowCount(null, null); System.out.println("一共有" + rowCount + "条记录"); }
执行结果:
-
添加 User
/* private String userId; // 用户id private String cardType; // 证件类型 private String cardNo; // 证件号码 private String userName; // 用户姓名 private String userSex; // 用户性别 private String userAge; // 用户年龄 private String userRole; // 用户角色 */ @Test public void testCreateUser(){ User user1 = new User("12345678910", "身份证", "66666620000101662X", "幸运星", "女", "23", "董事长"); User user2 = new User("12345678911", "身份证", "44444419991231221X", "倒霉蛋", "男", "23", "研究僧"); User user3 = new User("22222222222", "二逼证", "222222222222222222", "shanglinsong", "男", "26", "无业游民"); Integer count = userService.createUser(user1); System.out.println(count == 1 ? "幸运星添加成功": "幸运星添加失败"); count += userService.createUser(user2); System.out.println(count == 2 ? "倒霉蛋添加成功": "倒霉蛋添加失败"); count += userService.createUser(user3); System.out.println(count == 3 ? "二逼shanglinsong添加成功": "二逼shanglinsong添加失败"); }
执行结果:
-
根据 userId 删除 User
@Test public void testDeleteUserById(){ Integer count = userService.deleteUserById("12345678910"); System.out.println(count == 1 ? "幸运星删除成功": "幸运星删除失败"); count += userService.deleteUserById("12345678911"); System.out.println(count == 2 ? "倒霉蛋删除成功": "倒霉蛋删除失败"); count += userService.deleteUserById("22222222222"); System.out.println(count == 3 ? "二逼shanglinsong删除成功": "二逼shanglinsong删除失败"); }
执行结果:
-
根据 userId 批量删除 User(再利用添加 User 测试重新添加3个用户)
@Test public void testDeleteUserByIdList(){ ArrayList<String> userIds = new ArrayList<>(); userIds.add("12345678910"); userIds.add("12345678911"); userIds.add("22222222222"); // System.out.println(userIds); Integer count = userService.deleteUserByIdList(userIds); System.out.println(count == 3 ? "删除成功!": "删除失败!"); }
执行结果:
-
根据 userId 更新 User
@Test public void testUpdateUserById(){ User updateUser = new User("22222222222", "发财证", "888888888888888888", "shanglinsong", "男", "30", "架构师"); Integer count = userService.updateUserById(updateUser); System.out.println(count == 1? "修改命运成功!": "修改失败!继续加油吧!"); }
执行结果:
-
-
新建控制器,完成所有功能
package com.shanglinsong.ssm.controller; import com.shanglinsong.ssm.pojo.User; import com.shanglinsong.ssm.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * @author shanglinsong * @version 1.0 * @className com.shanglinsong.ssm.controller.UserController * @date 2023/1/30 * @since 1.0 */ @CrossOrigin @RestController @RequestMapping("user") public class UserController { @Autowired private UserService userService; // 分页查询 User @RequestMapping("/queryUserPage") public List<User> queryUserPage(Integer page){ // 计算分页查询开始行 int pageNow = page == null ? 1 : page; int pageSize = 5; int startRows = pageSize*(page-1); return userService.queryUserPage(startRows); } // 分页查询 User 带条件 @RequestMapping("/selectUserPage") public List<User> selectUserPage(String userName, String userSex, Integer page){ // 计算分页查询开始行 int pageNow = page == null ? 1 : page; int pageSize = 5; int startRows = pageSize*(page-1); return userService.selectUserPage(userName, userSex, startRows); } // 查询 User 个数 @RequestMapping("/getRowCount") public Integer getRowCount(String userName, String userSex){ return userService.getRowCount(userName, userSex); } // 添加 User @RequestMapping("/createUser") public Integer createUser(User user){ // 生成随机userId Random random = new Random(); Integer userId = random.nextInt(9000) + 1000; user.setUserId(System.currentTimeMillis() + String.valueOf(userId)); return userService.createUser(user); } // 根据 userId 删除 User @RequestMapping("/deleteUserById") public Integer deleteUserById(String userId){ return userService.deleteUserById(userId); } // 根据 userId 批量删除 User // 当映射名称不一样时需要使用@RequestParam注解 // 由于没有看文档才出现这个问题,工作中一定要按照文档办事! @RequestMapping("/deleteUserByIdList") public Integer deleteUserByIdList( @RequestParam("userIdList") String userIds){ // System.out.println("=========="); // System.out.println(userIds); // 去除最后的"," String userIdsSub = userIds.substring(0, userIds.length() - 1); // 创建List存放userIds ArrayList<String> userIdsList = new ArrayList<>(); for (String userId : userIdsSub.split(",")){ userIdsList.add(userId.trim()); } // System.out.println(userIdsList); return userService.deleteUserByIdList(userIdsList); } // 根据 userId 更新 User @RequestMapping("/updateUserById") public Integer updateUserById(User user){ return userService.updateUserById(user); } }
-
浏览器测试功能
-
安装node.js, 使用提供好的vue素材。本人使用VScode运行,此笔记不涉及vue技术,因此不做idea构建vue项目和vue具体细节内容的记录。
-
查看版本编号
node -v npm –v
node.js的安装是为了使当前的计算机使用vue的框架,预安装的工具。有点类似于运行java程序时必须安装JDK一样的道理。
-
构建项目
使用命令行进入到当前要运行的vue的项目的目录下,运行以下命令进行项目搭建.
- 进入到当前项目的目录下
npm i element -ui -S
下载elementUI的框架npm install
//打包项目npm install --save vue-axios
//下载跨域访问组件axios
-
设计好的vue项目访问服务器的端口号为8082,但本人使用tomca启动时idea报不能采用该端口进行发布,因此进入vue项目目录下的 /config/index.js 文件中对target进行修改,将端口号改为8080
-
使用idea配置好tomcat启动后端服务器,端口号8080(如果先启动vue项目,vue项目会占用8080端口号,先启动tomcat再启动vue项目,vue项目将自动分配至8081端口,本人对vue不是很了解,目前说不清楚原因,所以就不在此暴露自己的无知了哈哈,等后面在好好学习一下吧,加油!)
-
点击“查看”–>“终端”调出终端,由于该项目设置dev方式启动,因此输入以下命令启动项目
npm run dev
启动后终端显示:
使用该网址进入vue项目主页:
-
点击UserHome进入操作界面
-
分页查询功能
-
条件分页查询功能
-
添加用户功能
-
删除用户功能
-
编辑(更新)信息功能
-
批量删除功能
-
-