SpringMVC复习——B站
目录
- 1 常识
- 1.1 回顾jsp/servlet
- 2 springmvc
- 2.1 QuickStart(原理讲解,实际中不使用该步骤)
- 2.2 QuickStart
- 2.3 总结
- 3 controller详解
- 3.1 实现接口
- 3.2 注解方式
- 3.3 RESTful风格
- 3.4 结果跳转方式
- 3.5 请求参数
- 3.6 返回结果
- 4 乱码问题
- 4.1 servlet过滤器
- 4.2 spring过滤器
- 4.3 其他方法
- 5 JSON(@RestController)
- 6 SSM整合
- 7 Ajax
- 8 拦截器
- 8.1 拦截器Demo:登录拦截
- 9 文件上传
1 常识
ssm:spring+springmvc+mybatis MVC三层架构
MVC:将业务逻辑、显示、数据分离
模型model(dao,service,负责底层数据库的连接和增删改查操作)
视图view(jsp/html,展示数据)
控制器controller(servlet,获取请求和返回响应)
POJO:实体类,包含这个实体的所有属性
VO:视图层对象,用于转化请求中的参数到对象中去,仅仅包含view层所需属性,相当于POJO的精简版
DTO:数据传输对象,用于存储service层所需的参数
接下来的学习方向:springmvc-vue-springboot-springcloud-linux
重点:springmvc的执行流程!!!
springmvc优点:
1 方便利用spring其他功能
2 自动绑定输入,正确转换数据类型
3 内置校验器
4 多种视图技术
5 使用xml配置文件
1.1 回顾jsp/servlet
转发和重定向:
转发的特点:
1.地址栏不发生变化,显示的是上一个页面的地址
2.请求次数:只有1次请求
3.根目录:http://localhost:8080/项目地址/,包含了项目的访问地址
4.请求域中数据不会丢失
转发使用:request.getRequestDispatcher("/地址").forward(request, response);
重定向的特点:
地址栏:显示新的地址
请求次数:2次
根目录:http://localhost:8080/ 没有项目的名字
请求域中的数据会丢失,因为是2次请求
结论:如果要保留请求域中的数据,使用转发,否则使用重定向。无论转发或重定向后续的代码都会执行。
- 新建空白Maven工程,并添加框架支持:JaveWeb
- 导入相关依赖
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version><scope>provided</scope></dependency>
- 创建一个servlet类
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取前端参数String method = req.getParameter("method");if("add".equals(method)){req.getSession().setAttribute("msg","do add");}if("delete".equals(method)){req.getSession().setAttribute("msg","do delete");}// 调用业务// 转发或重定向req.getRequestDispatcher("/WEB-INF/jsp/doMethod.jsp").forward(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);} }
- 创建对应页面
注意:如果需要保证用户不可见,需要放在WEB-INF下面<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Title</title> </head> <body> ${msg} </body> </html>
- 配置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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><display-name>Welcome to Tomcat</display-name><description>Welcome to Tomcat</description><servlet><servlet-name>hello</servlet-name><servlet-class>com.xiaopi3.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping><session-config><session-timeout>15</session-timeout></session-config> </web-app>
2 springmvc
简单易学,高效,基于请求和响应,约定优于配置
功能强大,支持RESTful风格,数据验证,格式化,本地化,主题
围绕DispatcherServlet设计,可以将请求发送给不同的处理器(spring2.5后使用java5可以使用注解controller声明方式)
以请求为驱动
2.1 QuickStart(原理讲解,实际中不使用该步骤)
可能遇到的问题:
1.控制台输出显示缺少jar包(典型的,缺少请求分发器)
2 查看idea的项目结构中的artifact中的WEB-INF下是否有lib库,没有则手动添加,并导入所有jar包
3 重启tomcat
执行步骤:
- 浏览器发送请求给DispatcherServlet
- DispatcherServlet接收请求,给HandlerMapping去解析请求,寻找对应的HandlerExecution
- 找到HandlerExecution后,返回给DispatcherServlet,DispatcherServlet再去调用HandlerAdapter去执行该HandlerExecution,HandlerExecution中包装的就是Controller层的控制器类,执行过程中控制层会调用业务层,最终返回一个ModelAndView给HandlerAdapter
- HandlerAdapter拿到ModelAndView给DispatcherServlet,DispatcherServlet调用视图解析器ViewResolver,解析出数据和目标视图页面
- 跳转到终页面并插入数据
步骤:
1 编写跳转视图myhello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><body>${msg}</body>
</html>
2 配置web.xml,装在请求分发器,地址映射,初始化配置(加载springmvc的配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0">
<!--核心配置:请求分发器--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 绑定spring配置文件--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param>
<!-- 启动级别:1,表示tomcat服务后就启动--><load-on-startup>1</load-on-startup></servlet>
<!--请求映射:注意!这里/和/*有区别!前者只匹配请求,后者匹配请求+jsp页面--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>
注意:请求映射里的/和/*区别很大!
/
:只转发给请求分发器动作请求,不转发文件请求
/*
:转发所有请求
由于请求分发器会自动拼接动作请求,并且最后加上jsp后缀,所以使用/*
会导致无限循环!
如果是过滤器,url-pattern必须为/*
才行
如果想看过滤器过滤了什么请求:String url = ((HttpServletRequest) request).getRequestURI();
3 配置springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 装配处理器映射器,bean名称映射器会去在beans中寻找匹配的bean名字--><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 装配处理器适配器--><bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 视图解析器:即模板引擎,可替换的有Thymeleaf,Freemarker--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!-- 前缀--><property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀--><property name="suffix" value=".jsp"/></bean><bean id="/hello" class="com.xiaopi3.controller.HelloController"/></beans>
注意:如果采用的是实现接口的方式实现控制器,则处理器映射器和处理器控制器不用显示写,默认有。
4 配置controller类
public class HelloController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {ModelAndView mv = new ModelAndView();// 业务代码String result = "hahahah";mv.addObject("msg",result);// 视图跳转mv.setViewName("myhello");// 会被视图解析器拼接成/WEB-INF/myhello.jspreturn mv;}
}
5 启动tomcat部署项目,请求/hello地址发现显示正常
2.2 QuickStart
注意:可以添加一下打包过滤文件:
<build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources>
</build>
https://www.cnblogs.com/dflmg/p/6393416.html
步骤:
- 配置web.xml(基本不用变,每次写都直接copy即可),同上节一样
- 配置springmvc-servlet.xml (注意,最好不要加中文注释!有可能报编码异常!!)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd
"><!-- 包扫描可以实现启用注解(annotation-config),并且可以实现自动装配bean--><context:component-scan base-package="com.xiaopi3.controller"/>
<!-- 过滤静态资源请求,交由web容器默认servlet去处理--><mvc:default-servlet-handler/>
<!-- mvc注解驱动:注入处理器映射器和处理器适配器,注解方式,可以不显示写--><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>
- 新建控制器类:
com.xiaopi3.controller
下,该类包含控制器和映射器注解!!
@Controller // 注意:该控制器注解会被视图解析器解析,如果是@RestController则直接返回到前端,不解析!!
@RequestMapping("/to") // 一级地址
public class HelloController {// 二级地址@RequestMapping("/hello")public String hello(Model model){// 封装数据model.addAttribute("msg","my first annotation springmvc!");return "hello"; // 会被视图解析器处理,该字符串会作为视图名称}
}
- 新建jsp页面(对应于return字符串中的,被视图解析器组合后为:
/WEB-INF/jsp/hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
${msg}
</body>
</html>
注意:如果碰到包找不到的报错,看一下上一节开头的提示
注意:@Controller
和@RestController
的区别:前者注解会被视图解析器解析,后者则直接返回到前端,不解析!!
2.3 总结
springmvc中必备三大项:处理器映射器,处理器适配器,视图解析器,其中,前两者被:annotation-driver
干掉了,只需配置最后一个,并开启注解驱动!
3 controller详解
控制器可以通过两种方式实现:通过实现接口Controller返回ModelAndView(不推荐),通过注解!
负责解析用户请求,并处理成模型
3.1 实现接口
配置springmvc-servlet.xml,该方式无需显示装配处理器映射器和处理器控制器
配置控制器映射类+视图解析器即可!
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/>
</bean>
<bean id="/hello" class="com.xiaopi3.controller.HelloController"/>
编写控制器
public class HelloController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {ModelAndView mv = new ModelAndView();String result = "hahahah";mv.addObject("msg",result);mv.setViewName("myhello");// 会被视图解析器拼接成/WEB-INF/myhello.jspreturn mv;}
}
总结:该方法以及不推荐使用,因为一个类只能映射一个请求,当请求过多,需要写很多类
3.2 注解方式
配置springmvc-servlet.xml (注意,最好不要加中文注释!有可能报编码异常!!)
配置扫描包+视图解析器即可
<context:component-scan base-package="com.xiaopi3.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/>
</bean>
新建控制器类:com.xiaopi3.controller
下,该类包含控制器和映射器注解!!
加上@Controller@RequestMapping即可
@Controller // 注意:该控制器注解会被视图解析器解析,如果是@RestController则直接返回到前端,不解析!!
@RequestMapping("/to") // 一级地址
public class HelloController {// 二级地址@RequestMapping("/hello")public String hello(Model model){// 封装数据model.addAttribute("msg","my first annotation springmvc!");return "hello"; // 会被视图解析器处理,该字符串会作为视图名称}
}
3.3 RESTful风格
一种资源定位和操作的风格,简洁、高效、安全
所有参数传递都采用/
进行分割,类似于下面这种:
采用不同的请求方式来区分
对应的Controller类如下:
原始风格:
@RequestMapping("/add")
public String add(int a,int b,Model model){int res = a+b;model.addAttribute("msg","结果为:"+res);return "hello";
}
请求地址:/add?a=1&b=2
RESTful风格:
@RequestMapping("/add/{a}/{b}")
public String add2(@PathVariable int a,@PathVariable int b,Model model){int res = a+b;model.addAttribute("msg","结果为:"+res);return "hello";
}
请求地址:/add/4/6
改动两个地方:1. 地址栏通过{x}
获取变量x的值;2. 参数列表通过@PathVariable
绑定地址变量即可
同时可以指定请求方式:@RequestMapping(path="/add/{a}/{b}",method=RequestMethod.GET)
同时上面这种请求又可以简化:@GetMapping("/add/{a}/{b}")
,POST|DELETE|PUT|PATCH都有这种简化
3.4 结果跳转方式
1 使用ModelAndView对象,可以设置view名称,跳转到指定页面,经过视图解析器
2 使用servlet api:request重定向和resp转发,方法内依旧能获取req和res(不推荐),不经过视图解析器
3 使用springmvc转发和重定向,不经过视图解析器,底层依旧是servlet api,(可以去掉视图解析器配置)需要写全jsp文件路径名称!
// servlet api 重定向
@RequestMapping("/add")
public String add2(HttpServletRequest req, HttpServletResponse resp){req.getRequestDispatcher("WEB-INF/jsp/test.jsp").forward(req,resp);
}
// servlet api 转发
@RequestMapping("/add")
public String add2(HttpServletRequest req, HttpServletResponse resp){resp.sendRedirect("/index.jsp");
}
// springmvc 重定向
@RequestMapping("/add1")
public String add2(){return "redirect:/index.jsp";
}
// springmvc 转发
@RequestMapping("/add2")
public String add2(){return "/index.jsp";
}
// springmvc 转发
@RequestMapping("/add3")
public String add2(){return "forward:/index.jsp";
}
注意:重定向无法访问WEB-INF
下的文件
注意:重定向无法携带原请求的参数,但是可以在指定重定向到哪个url前,在其中添加新参数,新参数会显示在重定向的url后面
注意:转发会携带原参数,但无法携带新数据(实测Spring的Model无法携带)
请求转发地址栏不会发生改变、只发送一次请求、能携带原有的参数,但只可以在同一个服务器中进行转发。
传统的重定向请求地址会改变(两次请求)、不能传递参数,但是利用SpringMVC的重定向可以携带和传递参数。重定向相比于请求转发可以跨服,但是不能直接重定向访问WEB-INF下的资源(可重定向后再进行一次请求转发)。
3.5 请求参数
url中参数名和controller的方法形参一致即可获取请求参数!
// 请求url为:/hello?name=pp&age=2&id=435
@RequestMapping("/hello")
public String a(String name,int age,String id){}
如果参数名称不一致,可以通过@RequestParam("xxx")
显式映射url的参数
// 请求url为:/hello?username=pp&age=2&id=435
@RequestMapping("/hello")
public String a(@RequestParam("username")String name,int age,String id){}
可以将请求参数封装称一个实体,只要url请求参数能和实体中的属性名对应即可!没对应的为null
// 请求url为:/hello?name=pp&age=2&id=435
// User类中有name age id属性
@RequestMapping("/hello")
public String a(User user){}
3.6 返回结果
返回结果到前端有三种方式:
Model:只有几种方法用来存储数据(主要)
ModelMap:继承LinkedMap,还有自身的一些方法
ModelAndView:存储数据,可以设置跳转视图
4 乱码问题
实践中往往通过POST方式从网页上传递过来的数据有中文乱码问题,而GET方式没有这个问题,解决方法有两种,servlet过滤器,或者使用spring写好的过滤器
4.1 servlet过滤器
解决方式:
- 使用servlet过滤器进行过滤请求
EncodingFilter.java
public class EncodingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");chain.doFilter(request,response);}
}
- 注册该过滤器
web.xml
<filter><filter-name>encodingfilter</filter-name><filter-class>com.xiaopi3.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping><filter-name>encodingfilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
注意:此时url为/*
即拦截所有的请求,无论是路径还是文件,因为在返回视图时是一个jsp页面,同样需要捕获到该请求页面并转码,而/
过滤该请求,只捕获动作,返回时的请求就不会被处理了,我们需要保证请求和响应的编码一致才行
4.2 spring过滤器
<filter><filter-name>springencoding</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping><filter-name>springencoding</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
spring提供一个编码的过滤器,可以解决乱码问题,可能某些情况下对GET支持不好
4.3 其他方法
- 修改tomcat配置文件,设置编码格式:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
5 JSON(@RestController)
html中的script不能自闭合,必须成对出现
轻量级的数据传输格式,使用字符串表示,常用的包有:Jackson、fastjson、gson等
可以将对象转换成字符串,可以从字符串中恢复对象
注意:一般而言,Controller里返回的字符串会通过请求分发器去找视图解析器解析,但是如果想直接返回该字符串给前端的化,必须添加注解:@ResponseBody
注意:如果json中出现乱码,可以配置RequestMapping中的属性:
@RequestMapping(value="j",produces="application/json;charset=utf-8")
@ResponseBody
public String fun1(){}
由于在注解中配置方式,需要每个注解都配置,比较烦,可以在springmvc-servlet.xml中进行配置:
<mvc:annotation-driven><mvc:message-converters><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/><bean class="org.springframework.http.converter.FormHttpMessageConverter"/><bean class="org.springframework.http.converter.StringHttpMessageConverter"><constructor-arg name="defaultCharset" value="UTF-8"/></bean></mvc:message-converters>
</mvc:annotation-driven>
需要导入jackson包:
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.5</version>
</dependency>
再次返回json字符串则显示正常:
@RestController
public class JsonController {@RequestMapping("/j1")public String fun1(){JSONObject json =new JSONObject();json.put("name","小皮3");json.put("age",19);return json.toString();}
}
6 SSM整合
环境:IDEA、MySQL5.7、Tomcat9、Maven3.6
- 导入依赖
pom.xml
<dependencies><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.2</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.0</version></dependency><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency><!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl --><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version></dependency><!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.5</version></dependency><!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.5</version></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version><scope>provided</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.75</version></dependency>
</dependencies><build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources>
</build>
- 配置三个配置文件:spring核心配置文件,数据库properties,mybatis配置文件
db.properties
# 注意,一定要写jdbc.driver而不是driver,要不然有可能会报错!!
jdbc.driver=com.mysql.jdbc.Driver
# 如果是mysql8+,需要添加时区:&serverTimezone=Asia/Shanghai
jdbc.url=jdbc:mysql://localhost:3306/ooo?useSSL=false&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
mybatis-config.xml,其他交给spring去管理了
<?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><typeAliases><package name="com.xiaopi3.pojo"/></typeAliases></configuration>
applicationContext.xml,通过引入其他配置文件来配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://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>
第一个:spring-dao配置
配置一下spring和数据库相关的配置
连接池:
- dbcp:半自动化操作,不能自动连接
- c3p0:自动化操作(自动加载配置文件,自动设置到对象中)
- druid
- hikari
spring-dao.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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd
"><context:property-placeholder location="classpath:db.properties"/><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="maxPoolSize" value="30"/><property name="minPoolSize" value="10"/><property name="autoCommitOnClose" value="false"/><property name="checkoutTimeout" value="10000"/><property name="acquireRetryAttempts" value="2"/></bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="configLocation" value="classpath:mybatis-config.xml"/></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><property name="basePackage" value="com.xiaopi3.dao"/></bean></beans>
配置文件分为几部分:
1 外部properties文件读取
2 c3p0连接池配置
3 sqlSessionFactory注入
4 使用Mapper扫描器对包进行扫描,并注入sqlSessionFactory,该类属于mybatis与spring整合的包
spring-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:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd
"><context:component-scan base-package="com.xiaopi3.service"/><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean></beans>
该配置文件分为两部分:
1 包扫描
2 配置spring事务管理器
spring-mvc.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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd
"><mvc:annotation-driven/><mvc:default-servlet-handler/><context:component-scan base-package="com.xiaopi3.controller"/><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean>
</beans>
该配置文件分为4个部分:
1 注解驱动,mvc注入映射器和适配器
2 静态资源过滤
3 包扫描
4 视图解析器
- 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><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>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><session-config><session-timeout>15</session-timeout></session-config>
</web-app>
该配置文件主要做了两件事:
1 配置请求分发器,并注入spring总配置文件(因为时web项目,需要在这里读取总配置文件),设置spring即刻启动
2 配置启用spring编码过滤器
至此配置工作结束,开始业务工作!
对于POJO类可以采用lombok注释
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private int id;private String name;private int age;private int salary;
}
对于dao下的接口采用mybatis的方式:
public interface UserMapper {int addUser(User user);int deleteUserById(int id);int updateUser(User user);User findUser(int id);List<User> findAllUser();
}
<?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.xiaopi3.dao.UserMapper"><insert id="addUser" parameterType="user">insert into `user` values(null,#{name},#{age},#{salary})</insert><delete id="deleteUserById">delete from `user` where id=#{id}</delete><update id="updateUser" parameterType="user">update `user` set name=#{name},age=#{age},salary=#{salary} where id=#{id}</update><select id="findUser" resultType="user">select * from `user` where id=#{id}</select><select id="findAllUser" resultType="user">select * from `user`</select></mapper>
对于控制层controller采用注解方式:
@Controller
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/findAll")public String findAllUser(Model model){List<User> allUser = userService.findAllUser();model.addAttribute("users", JSON.toJSONString(allUser));return "users";}@RequestMapping("/find")public String find(int id,Model model){User user = userService.findUser(id);ArrayList<User> users = new ArrayList<>();users.add(user);model.addAttribute("users", JSON.toJSONString(users));return "users";}
}
- 启动tomcat,注意在tomcat的lib下导入需要的jar包,访问请求地址:
/user/findAll
,完毕
7 Ajax
掌握异步请求方式
<script>
function getValue(){$.post({url:"地址",data:{数据},success:function(data,status,xhr){}})
}
</script>
注意:回调函数中:data为返回值,status为:(“success”、“notmodified”、“error”、“timeout”、“parsererror”)中的一种,xhr为XMLHttpRequest对象
注意:post中可以不传递{}
对象,直接传参:$.post(url,bodyData,function(responseData){})
动过标签获取input组件的value值:
txt=$("input").val();
通过id获取某个组件:$("#id")
ajax入口函数:$(function(){入口})
,写在入口中的表达式会依次执行
ajax设置组件css:$("#id").css("color":"green")
使用Ajax动态获取数据时建议后台使用@RestController
来传递数据
@RestController
public class TestRestController {@RequestMapping("/doRest")public List<Map<String,Integer>> doRest(int num){List<Map<String, Integer>> maps = new ArrayList<>();for (int i = 0; i < num; i++) {Map<String, Integer> map = new HashMap<>();map.put("index",i);map.put("value",i*456/222);maps.add(map);}return maps;}
}
注意:如果报:org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type ...
这种错误,表示没有找到json转换器,需要修改两个地方:
- 修改spring-mvc.xml,加上json转换器
<mvc:annotation-driven><mvc:message-converters><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/><bean class="org.springframework.http.converter.FormHttpMessageConverter"/><bean class="org.springframework.http.converter.StringHttpMessageConverter"><constructor-arg name="defaultCharset" value="UTF-8"/></bean></mvc:message-converters>
</mvc:annotation-driven>
- 添加jackson依赖
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.5</version>
</dependency>
- 在项目目录结构中将依赖jar包添到对应artifact的
/WEB-INF/lib/
下,重启tomcat即可!
8 拦截器
拦截器类似于servlet过滤器,与过滤器区别是:拦截器是AOP思想的应用
过滤器:任何java web工程都可以使用,配置了url-pattern为/*
后可以进行资源过滤
拦截器:springmvc特有的,只拦截映射器中的请求,不拦截静态资源
定义拦截器:实现HandlerInterceptor
接口
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("请求处理前");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("请求处理后");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("请求完成清理资源");}
}
注意:重写的三个方法中,最重要的是第一个方法,如果返回值为false则请求被拦截!否则放行。
在srping-mvc.xml中配置拦截器:
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.xiaopi3.config.MyInterceptor"/></mvc:interceptor>
</mvc:interceptors>
注意:path为/**
指拦截/
下所有请求以及子请求!!
启动tomcat请求任意controller映射,返回结果:
请求处理前
执行业务逻辑代码----------
请求处理后
请求完成清理资源
8.1 拦截器Demo:登录拦截
环境:SpringMVC环境
- 首先编写页面:主页:index.jsp、展示页:users.jsp、登录页:login.jsp
主页:
<a href="${pageContext.request.contextPath}/user/findAll">进入用户展示页面</a>
<a href="${pageContext.request.contextPath}/goLogin">登录</a>用户展示页:
<a href="${pageContext.request.contextPath}/logout">注销</a>
<h1>用户展示</h1>登录页:
<form action="${pageContext.request.contextPath}/login" method="post">用户名:<input type="text" name="username"/>密码:<input type="password" name="password"/><input type="submit" value="提交">
</form>
- 编写登录拦截器
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("请求处理前");String uri = request.getRequestURI();System.out.println(uri);if(uri.contains("login")||uri.contains("goLogin")){return true;}if("true".equals(request.getSession().getAttribute("login"))){return true;}response.sendRedirect("/goLogin");return false;}
}
注意:这里注意三点:1. 用户访问登陆页面不需要拦截;2. 用户登陆页面请求登录不需要拦截;3. 已经登录后不需要拦截
- 注册拦截器到spring-mvc.xml
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.xiaopi3.config.MyInterceptor"/></mvc:interceptor>
</mvc:interceptors>
注意:可以在path中定义多级路径达到过滤部分路径不拦截的目的
- 编写controller
@Controller
public class LoginController {@RequestMapping("/goLogin")public String goLogin(){return "login";}@PostMapping("/login")public String login(HttpSession httpSession,String username,String password){if("xiaopi3".equals(username)&&"123456".equals(password)){httpSession.setAttribute("login","true");return "users";}return "login";}@RequestMapping("/logout")public String logout(HttpSession httpSession){httpSession.removeAttribute("login");return "redirect:/goLogin";}
}
- 启动tomcat测试效果:登录后可以进入内容展示页面,否则会跳转到登陆页面,注销后会跳转到登陆页面,并且需要登陆才能进入内容页。
9 文件上传
springmvc处理文件上传需要MultipartResolver
前端表单要求:为了能上传文件,必须将表单的method设置称POST,并将enctype设置为multipart/form-data,浏览器会以二进制流的方式来处理表单数据。apche发布的Commons FileUpload组件是Servlet/jsp最佳选择
- 导包
注意:Springmvc将Commons FileUpload封装成了MultipartResolver,所以如果需要文件上传,下面两个包都需要
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope>
</dependency>
- 配置MultipartResolve
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- must be same with jsp pageEncoding : default ISO-8859-1--><property name="defaultEncoding" value="utf-8"/>
<!-- unit:Byte 10M=10*1024*1024Byte--><property name="maxUploadSize" value="10485760"/><property name="maxInMemorySize" value="4096"/>
</bean>
注意:该id要求必须为:multipartResolver
- 配置Controller
@Controller
public class UploadController {@RequestMapping("/upload")public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest httpServletRequest) throws IOException {// 获取文件名String uploadFileName = file.getOriginalFilename();// 如果文件名为空,则赋值默认:uploadif("".equals(uploadFileName)){return "users";}System.out.println("上传文件名:"+uploadFileName);// 上传路径String _path = httpServletRequest.getSession().getServletContext().getRealPath("/upload");System.out.println(_path);File path = new File(_path);if(!path.exists()){path.mkdir();}File _file = new File(path,uploadFileName);if(_file.exists()){String[] split = uploadFileName.split("\\.");uploadFileName = split[0] + UUID.randomUUID()+"."+split[1];_file = new File(path,uploadFileName);}InputStream inputStream = file.getInputStream();FileOutputStream fileOutputStream = new FileOutputStream(_file);int len=0;byte[] array = new byte[1024];while((len=inputStream.read(array))!=-1){fileOutputStream.write(array,0,len);}inputStream.close();fileOutputStream.close();return "users";}@RequestMapping("/upload2")public String upload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest httpServletRequest) throws IOException {// 获取文件名String uploadFileName = file.getOriginalFilename();// 如果文件名为空,则赋值默认:uploadif("".equals(uploadFileName)){return "users";}System.out.println("上传文件名:"+uploadFileName);// 上传路径String _path = httpServletRequest.getSession().getServletContext().getRealPath("/upload");System.out.println(_path);File path = new File(_path);if(!path.exists()){path.mkdir();}File _file = new File(path,uploadFileName);if(_file.exists()){String[] split = uploadFileName.split("\\.");uploadFileName = split[0] + UUID.randomUUID()+"."+split[1];_file = new File(path,uploadFileName);}// 通过CommonsMultipartFile方法直接写文件file.transferTo(_file);return "users";}
}
注意:两种方法的效果一样,不同之处在于IO流部分,第二种方式使用Springmvc包装好的方法transferTo
进行文件写出。当没有选择文件之间点上传时,文件名为空,所以可以依此判断进行跳转。如果使用RestController可以使用ajax进行异步请求。
特别注意:参数输入部分:@RequestParam("file") CommonsMultipartFile file
必须带上注解进行指定,否则报空指针异常!!
SpringMVC复习——B站相关推荐
- 基于sqlserver的数据库复习
20220711 -20220724 数据库复习 + B站视频(基于sqlserver) 边看视频边随手记录的,可读性可能不太高,自用吧. 一. 1.为何要连接到数据库:数据库软件不是数据库,我们只是 ...
- 【记vue项目中的踩坑日记】一杯茶一包烟,一个bug搞一天
昨天在复习B站coderwhy老师的项目时,偶然发现了一个问题,弄了半天,最后才发现问题出在哪. 封装完底部的导航栏之后实现路由跳转出现了问题,在浏览器中既不报错,也不输出内容,路由跳转也没有用 整了 ...
- redis发布订阅与集群
本系列根据狂神说Redis写下笔记以供复习 B站狂神说Redis!:https://www.bilibili.com/video/BV1S54y1R7SB 发布订阅 Redis 发布订阅(pub/su ...
- 《如何在大学里脱颖而出(How to Win at College)》读书笔记
<如何在大学里脱颖而出(How to Win at College)>读书笔记 图书简介 中文版: 英文版: 作者卡尔·纽波特(Cal Newport)于 2004 年6月以优等生荣誉学会 ...
- 中科大凌青老师凸优化课程——目录
视频链接: 中科大-凸优化_哔哩哔哩_bilibili 课程对应目录: 1-2:推荐书目,引言,常见例子,优化问题分类,发展史 3-4:仿射/凸/凸锥 + 集/组合/包 5-6:几种重要的凸集:超平面 ...
- 2019年末逆向复习系列之淘宝M站Sign参数逆向分析
郑重声明:本项目的所有代码和相关文章, 仅用于经验技术交流分享,禁止将相关技术应用到不正当途径,因为滥用技术产生的风险与本人无关. 这篇文章是<2019年末逆向复习系列>的第一篇:< ...
- b站尚硅谷springmvc学习视频:springmvc文档
文章目录 一.SpringMVC简介 (b站尚硅谷springmvc学习视频:springmvc文档) 1.什么是MVC 2.什么是SpringMVC 3.SpringMVC的特点 二.HelloWo ...
- 【脱产二站上岸】上海交大819复习经验总结
笔者来自通信考研小马哥23上交819全程班学员 本科西南某985,成绩排名中下(面试被老师疯狂吐槽),一战本校,初试分数差10来分被刷.21年12月考完数学和专业课出来就知道考不上了,分数一出就下决心 ...
- SpringMVC总复习
SpringMVC课堂笔记1.SpringMVC概述 SpringMVC概念 SpringMVC 也叫 Spring web mvc.是 Spring内置的一个MVC框架,在 Spring3.0 后发 ...
- 一篇复习一下Spring和SpringMVC基本概念
什么是Spring,为什么你要学习spring? 你第一次接触spring框架是在什么时候?相信很多人和我一样,第一次了解spring都不是做项目的时候用到,而是在网上看到或者是听到过一个叫做spri ...
最新文章
- 安装Ruby和Rails运行环境
- 数据为什么要可视化?如何可视化?
- Android系统的体系结构、开发语言及源码结构
- 下载bilibli网站视频
- 秒杀系统 mysql_秒杀系统-介绍
- Linux下SHELL的PS1变量简介
- python学习--面向过程程序设计实例
- git生成SSH密钥提示ssh文件不存在-已解决
- BZOJ1431 : MLand
- 拓端tecdat|WinBUGS对多元随机波动率模型:贝叶斯估计与模型比较
- Rust:Programming Rust:所有权
- 如何让WPS像word一样使用快捷键打开MathType
- 内存映射文件原理(转载)
- CDH6.0.1环境Hadoop集群性能测试
- 十七点学完安全知识超级详细了解进程和病毒知识 转载
- nodejs实现分解质因数的算法
- 2022/10/10-10/15周报
- 一、在GPU上执行运算
- Keil无法跳转到(go to definition)函数定义的地方,而是出现Browser
- 买笔记本电脑的13个重要的验机步骤
热门文章
- AutoIt 脚本流行编辑工具
- python 计算置信区间,Python求解正态分布置信区间
- the old reader使用分享
- ZOJ 3551 Bloodsucker(概率)
- 《丑奴儿书博山道中壁》
- 教你制作QQ空间超高连通率背景音乐链接。
- 在d盘创建文件夹,里面有aaa.txt/bbb.txt/ccc.txt,然后遍历出aaa文件夹下的文件(新手用于记录每天的作业)...
- 枕头Python 3
- mac电脑显示器分辨率显示异常
- php论坛整合,phpcms+ucenter+discuz论坛整合教程