配置
请求映射
@RequestMapping
获取请求参数
get、pos中文乱码
像请求域共享数据
会话域、应用域共享数据
页面仅跳转,使用视图控制器
Restful
处理静态资源
处理ajax请求 前后交互
@RequestMapping获取前端发送请求,请求体携带的参数
@RestController
文件上传与下载
拦截器
Springmvc常用组件
整合ssm
配置Springmvc
pom
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
webapp目录
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
<servlet>
<servlet-name>Springmvc</servlet-name>
<!-- DispatcherServlet 初始化的时候加载springmvc的配置文件 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 设置springmvc配置文件的位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Springmvc.xml</param-value>
</init-param>
<!-- 将DispatcherServlet初始化的时间,提前到服务器启动时进行初始化 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<!-- 控制器的<servlet-name>-->
<servlet-name>Springmvc</servlet-name>
<!--
设置springMVC的核心控制器所能处理的请求的请求路径
/所匹配的请求可以是/login或.html或.js或.css方式的请求路径
但是/不能匹配.jsp请求路径的请求
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
配置springmvc配置文件
<?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.qwq.Controller"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 视图渲染 页面跳转-->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
</beans>
目录结构
请求映射
package com.qwq.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
// 请求映射 / = http://localhost:8080/SpringMvc/
@RequestMapping("/")
public String protal(){
// /WEB-INF/templates/index.html
return "index";
}
@RequestMapping("/hello")
public String Hello(){
return "Hello";
}
}
@RequestMapping
@RequestMapping标识一个类:设置映射请求的请求路径的初始信息
@RequestMapping标识一个方法:设置映射请求请求路径的具体信息
package com.qwq.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("Test")
public class HelloWordController {
// http://localhost:8080/SpringMvc/Test/hello
@RequestMapping("hello")
public String qyq(){
return "Hello";
}
}
value属性
package com.qwq.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/Test")
public class HelloWordController {
// http://localhost:8080/SpringMvc/Test/hello
// http://localhost:8080/SpringMvc/Test/word
// 注解的value属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求
@RequestMapping({"/hello","/word"})
public String qyq(){
return "Hello";
}
}
设置请求方式
@RequestMapping(value = {"/hello","/word"},
// 设置请求方式
method = {RequestMethod.GET,RequestMethod.POST})
ant风格路径
// ? 代表任意单个字符 不包括?本身 http://localhost:8080/SpringMvc/a6a/bbb/ccc
@RequestMapping("/a?a/bbb/ccc")
public String TestAnt(){
return "Hello";
}
// *可以输入任意字符不包含? / http://localhost:8080/SpringMvc/a11122222222221aa/bbb/ccc
@RequestMapping("/a*a/bbb/ccc")
public String TestAnt1(){
return "Hello";
}
// **任意层数任意目录,前后不能有任意字符 localhost:8080/SpringMvc/a1/11/11aa/bbb/ccc
@RequestMapping("/**/bbb/ccc")
public String TestAnt2(){
return "Hello";
}
获取请求参数
@RequestMapping("/test/rest/{username}/{id}")
// <a th:href="@{/test/rest/admin/1}">测试springmvc7</a><br/>
public String testRest(@PathVariable("username") String username , @PathVariable("id") Integer id){
System.out.println("username的值是"+username+"---"+"id的值是"+id);
// username的值是admin---id的值是1
return "Hello";
}
获取请求参数
@RequestMapping("/param/servletAPI")
// 1.Servlet获取参数 设置HttpServletRequest httpServletRequest的形参,
// 通过httpServletRequest.getParameter("参数");获取参数
public String getApi(HttpServletRequest httpServletRequest){
String username = httpServletRequest.getParameter("username");
String password = httpServletRequest.getParameter("password");
System.out.println("username的值是:"+username+"password的值是:"+password);
return "Hello";
}
@RequestMapping("/param")
// 请求参数的形参和请求参数的名字一致时,可以直接获取到
// <input type="text" name="username"><br>
// <input type="password" name="password">
public String param( String username, Integer password){
System.out.println("username的值是:"+username+"password的值是:"+password);
return "Hello";
}
@RequestMapping("/param")
// @RequestParam 将请求参数与形参绑定
// value = "username" 设置形参绑定参数名字
// required = true 如果不传递username的值,系统会直接报错
// defaultValue = "hello" 如果没有传递username的值,会使用hello默认值
public String param2(@RequestParam(value = "username",required = true , defaultValue = "hello") String name, Integer password){
System.out.println("username的值是:"+name+"password的值是:"+password);
return "Hello";
}
获取请求头、cookie
@RequestMapping("/param2")
// @RequestHeader 将请求参数与请求头绑定,获取该请求头的值
// required = true 如果没有请求头Referer的信息,则会报错
// defaultValue 设置请求头的默认值
public String param3(@RequestHeader(value = "Referer",required = true ,defaultValue = "hello") String Referer , String username, Integer password){
System.out.println("請求頭的信息是:"+Referer);
System.out.println("username的值是:"+username+"password的值是:"+password);
return "Hello";
}
@RequestMapping("/param3")
// @CookieValue("JSESSIONID") 获取cook的值
public String param4(@CookieValue("JSESSIONID") String jsessionid , String username, Integer password){
System.out.println("JSESSIONID的值是:"+jsessionid);
return "Hello";
}
Pojo获取请求参数
@RequestMapping("/param4")
// user中的成员变量要和传递参数一致
// private String username; <input type="text" name="username">
// private String password; <input type="password" name="password">
public String pojo(User user){
System.out.println("JUser的值是:"+user);
return "Hello";
}
Get、Post乱码
Get
Post
<!--编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
像请求域共享数据
package com.qwq.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Controller
public class ScopeController {
/**
* 通过ModelAndView像请求域共享数据
*/
@RequestMapping("test01/01")
public ModelAndView test1(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("a1","hello,ModelAndView");
modelAndView.setViewName("Hello");
return modelAndView;
}
/**
* 通过ModelAndView像请求域共享数据
*/
@RequestMapping("test01/02")
public String test2(HttpServletRequest request){
request.setAttribute("a1","hello,HttpServletRequest");
return "Hello";
}
@RequestMapping("test01/03")
public String test3(Model model){
model.addAttribute("a1","hello,model");
return "Hello";
}
@RequestMapping("test01/04")
public String test4(Map<String,Object> map){
map.put("a1","hello,Map");
return "Hello";
}
}
会话域、请求域
@RequestMapping("session/01")
// Session是浏览器开启到浏览器关闭的过程 <p th:text="${session.a1}"></p>
public String test5(HttpSession session){
session.setAttribute("a1","hello,session");
return "Hello";
}
@RequestMapping("servletContext/01")
// 服务器开启到浏览器关闭的过程 <p th:text="${application.a1}"></p>
public String test6(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("a1","Hello,servletContext");
return "Hello";
}
重定向视图
// 重定向
@RequestMapping("test/redirect")
public String testredirect(){
// http://localhost:8080/SpringMvc/servletContext/01
return "redirect:/servletContext/01";
}
页面仅跳转,使用视图控制器
RESTful
- delete、put的请求方式需要设置
<!--webxml 1.设置处理请求对象的过滤器-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<form th:action="@{user}" method="post">
<!-- 2.更改请求方式-->
<input type="hidden" name="_method" value="put">
<input type="submit" value="put">
</form>
<form th:action="@{user/1}" method="post">
<!-- 2.更改请求方式-->
<input type="hidden" name="_method" value="delete">
<input type="submit" value="delete">
</form>
/**
* 浏览器只能设置get\post请求,如果设置put、delete请求的话,
* 需要再配置文件配置过滤器,HiddenHttpMethodFilter,需要设置 name="_method" value="put"
* <input type="hidden" name="_method" value="put">
* @return
*/
@RequestMapping(value = "/user" , method = RequestMethod.PUT)
public String PutUser(){
System.out.println("PUT------------");
return "succer" ;
}
@RequestMapping(value = "/user/{id}" , method = RequestMethod.DELETE)
public String DeleteUser(@PathVariable Integer id){
System.out.println("delete:"+id);
return "succer" ;
}
处理静态资源
<!-- springmvc配置文佳 配置默认的servlet处理静态资源
当前web.xml和tomcat的web.xml配置的DispatcherServlet,浏览器发送请求会被DispatcherServlet处理,
DispatcherServlet无法解析静态资源,
配置 <mvc:default-servlet-handler /> ,浏览器所有请求交由DispatcherServlet处理
配置 <mvc:default-servlet-handler /> <mvc:annotation-driven /> 所有的请求先交由DispatcherServlet处理,
无法处理的再交由DefaultServlet处理-->
<mvc:default-servlet-handler />
<!-- 开启mvc注解驱动 -->
<mvc:annotation-driven />
SpringMvc处理请求 (前后端交互)
<input type="button" value="测试SpringMVC处理ajax" @click="testAjax()"><br>
<script type="text/javascript">
var vue = new Vue({
el:"#app",
methods:{
testAjax(){
axios.post(
"/SpringMVC/test/ajax?id=1001",
// {username:"admin",password:"123456"}
).then(response=>{
console.log(response.data);
});
},
</script type="text/javascript">
@RequestMapping("/test/ajax")
public void test01(Integer id ,HttpServletRequest request , HttpServletResponse response) throws IOException {
System.out.println("id的值为:"+id);
// HttpServletRequest request 用于接收前端发送的数据
String id1 = request.getParameter("id");
System.out.println("request-id:"+id1);
// HttpServletResponse用于发送数据到浏览器
response.getWriter().write("hello,axios");
}
@RequestMapping 获取请求体的参数 前端传递的参数
// @RequestMapping将json赋值给对象
@RequestMapping("/test/RequestBody/json")
/**
* @RequestBody 获取请求体中的内容(json)
* 1.导入jackson依赖
* 2.springmvc配置文件中,要配置 <mvc:annotation-driven />
* 3.@RequestBody 获取请求体内的json数据,将json数据转化为对象
*/
public void test02(@RequestBody User user , HttpServletResponse response) throws IOException {
System.out.println(user);
}
//@RequestMapping将请求体的参数赋值给Map 集合
@RequestMapping("/test/RequestBody/json")
public void test03(@RequestBody Map<String,Object> map, HttpServletResponse response) throws IOException {
// {username=admin, password=123456, age=23, gender=男}
System.out.println(map);
}
@RequestMapping 响应数据至前端
@RequestMapping("/test/ResponseBody/json") // {kay:value,key,value}
@ResponseBody // 使用@ResponseBody注解响应浏览器json的数据
public User testResponseBody(){
User user = new User(1,"wang","123",20,"男");
// {"id":1,"username":"wang","password":"123","age":20,"gender":"男"}
return user;
}
@RequestMapping("/test/ResponseBody/json") // Map{key:{value},key:{value}}
@ResponseBody // 使用@ResponseBody注解响应浏览器json的数据
public Map<String,Object> testResponseBodyMap(){
User user = new User(1,"wang","123",20,"男");
User user2 = new User(2,"wang","123",20,"男");
HashMap<String,Object> hashMap = new HashMap<String, Object>();
hashMap.put("1001",user);
hashMap.put("1002",user2);
// {"1002":{"id":2,"username":"wang","password":"123","age":20,"gender":"男"},
// "1001":{"id":1,"username":"wang","password":"123","age":20,"gender":"男"}}
return hashMap;
}
@RequestMapping("/test/ResponseBody/json")
@ResponseBody // 使用@ResponseBody注解响应浏览器json的数据 List [{},{}]
public List<User> testResponseBodyList(){
User user = new User(1,"wang","123",20,"男");
User user2 = new User(2,"wang","123",20,"男");
List<User> users = new ArrayList<User>();
users.add(user);
users.add(user2);
// [{"id":1,"username":"wang","password":"123","age":20,"gender":"男"},
// {"id":2,"username":"wang","password":"123","age":20,"gender":"男"}]
return users;
}
@RequestMapping
复合注解,加在类上
@RequestMapping = @Controller + @ResponseBody
文件上传与下载
// 文件下载
@RequestMapping("/test/down")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws
IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("img");
// img + /或\(自动匹配) + 1.jpg
realPath = realPath + File.separator + "1.jpg";
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(bytes, headers,statusCode);
//关闭输入流
is.close();
return responseEntity;
}
/**
* 上传 必须为post enctype="multipart/form-data" 二进制的方式传输数据
* <form th:action="@{/test/up}" method="post" enctype="multipart/form-data">
*/
@RequestMapping("/test/up")
// <input type="file" name="photo"> photo就说对应的文件 需要配置文件上传解析器
public String testUp(MultipartFile photo, HttpSession session) throws
IOException {
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//处理文件重名问题
// 获取文件后缀名
String hzName = fileName.substring(fileName.lastIndexOf("."));
// 使用uuid + 后缀名称
fileName = UUID.randomUUID().toString() + hzName;
//获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
if(!file.exists()){
file.mkdir();
}
// war包 (target)
// D:\daima\springmvc03\target\springmvc03-1.0-SNAPSHOT\photo\52fe7529-807b-4555-a256-ad11f9625009.bmp
String finalPath = photoPath + File.separator + fileName;
System.out.println("上传文件:"+finalPath);
//实现上传功能
photo.transferTo(new File(finalPath));
return "success";
}
文件上传配置文件解析器
<!-- 配置文件解析器 id必须为multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
Pom文件加入依赖
<!-- 文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
拦截器
过滤器:浏览器和目标资源进行过滤 —>请求
配置拦截器
<bean id="interceptor01" class="com.qwq.interceptor.interceptor01"></bean>
<!-- 配置拦截器-->
<mvc:interceptors>
<!-- <bean class="com.qwq.interceptor.interceptor01" />-->
<!-- 1. <ref bean="interceptor01" />-->
<mvc:interceptor>
<mvc:mapping path="/**"/> <!--拦截某一个资源-->
<mvc:exclude-mapping path="/test/interceptor"/> <!--排除某一个资源-->
<ref bean="interceptor01" />
</mvc:interceptor>
</mvc:interceptors>
实现接口
public class interceptor01 implements HandlerInterceptor {
/**
* preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返
* 回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法
* postHandle:控制器方法执行之后执行postHandle()
* afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行afterCompletion(
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("1111111111111111111111111执行");
// falue 为拦截状态 true 为放行
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("2222222222222222222222222执行");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("3333333333333333333333333执行");
}
}
多个拦截器执行顺序
先配置的拦截器1方法->preHandle
后配置的拦截器1方法->preHandle
后配置的拦截器2方法->postHandle
先配置的拦截器2方法->postHandle
后配置的拦截器3方法->afterCompletion
先配置的拦截器1方法->afterCompletion
preHandle为false
当第一个拦截器preHandle为false,postHandle、afterCompletion方法不会执行,第二个拦截器也不会执行
当第二个拦截器preHandle为false,第一个拦截器会执行preHandle、afterCompletion
异常解析器
xml
<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
properties的键表示处理器方法执行过程中出现的异常
properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
error:出现异常跳转的界面
-->
<prop key="java.lang.ArithmeticException">error</prop></props>
</property>
<!--
exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享
-->
<property name="exceptionAttribute" value="ex"></property>
</bean>
注解
package com.qwq.abnormal;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
// 将当前类标识为异常处理的组件
@ControllerAdvice
public class abnormalTest {
@ExceptionHandler
public ModelAndView ExceptionHandlerTest(Exception e){
ModelAndView mv =new ModelAndView();
mv.addObject("prompt","抱歉,当前页面出现问题,请记住操作步骤提示开发人员");
mv.addObject("ex",e);
mv.setViewName("error");
return mv;
}
}
Springmvc组件
DispatcherServlet:前端控制器,不需要工程师开发,由框架提供,处理请求响应的
作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求
HandlerMapping:处理器映射器,不需要工程师开发,由框架提供(处理请求与方法的映射关系)
作用:根据请求的url、method等信息查找Handler,即控制器方法
Handler:处理器,需要工程师开发 -> Controller
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理
HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供 (匹配到方法,处理方法)
作用:通过HandlerAdapter对处理器(控制器方法)进行执行
ViewResolver:视图解析器,不需要工程师开发,由框架提供 (解析视图)
作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、
RedirectView
View:视图
作用:将模型数据通过页面展示给用户
DispatcherServlet初始化过程
初始化匹配 九大适配器
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
springmvc的执行过程
1.用户向服务器发送请求,请求被Springmvc的DispacherServlet捕获
2.DispacherServlet对请求进行解析,得到请求支援标识符,判断请求是否存在
请求不存在:交由默认的serlet进行处理,处理不了的话,页面 404
当前请求存在:
1.根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及
Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回。
2.DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
3.如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法
4.提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。
在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
5.HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定
的响应信息
6.数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
7.数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
8. 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
9.Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
10.此时将开始执行拦截器的postHandle(…)方法【逆向】。
11.根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行
HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model
和View,来渲染视图。
12.渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。
13.将渲染结果返回给客户端
整合ssm
监听器
在服务器启动时,加载spring的配置文件,获取spring的ioc容器
Controller 交给 springmvc 进行处理
servlet 交给 spring 进行处理
web.xml设置
<!--配置监听器,在服务器启动时,加载spring的配置文件-->
<listener>
<!--在服务器启动时加载Spring的配置文件-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- spring的配置文件-->
<param-value>classpath:Spring.xml</param-value>
</context-param>
导入依赖
<packaging>war</packaging>
<!-- spring的依赖-->
<properties>
<spring.version>5.3.1</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</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-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--mybatis和spring的整合包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
配置springmvc文件
web.xml
<!--1.编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--1.设置处理请求方式的过滤器-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
<servlet>
<servlet-name>Springmvc</servlet-name>
<!-- DispatcherServlet 初始化的时候加载springmvc的配置文件 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 设置springmvc配置文件的位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Springmvc.xml</param-value>
</init-param>
<!-- 将DispatcherServlet初始化的时间,提前到服务器启动时进行初始化 -->
<load-on-startup>1</load-on-startup>
</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>
<!-- 设置spring配置文件自定义位置和名称-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Spring.xml</param-value>
</context-param>
配置springmvc文件
<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.qwq.controller"> </context:component-scan>
<!-- 配置Thymeleaf视图解析器 视图渲染 页面跳转-->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 请求视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 请求视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<!-- 无法处理的再交由DefaultServlet处理 需要注解驱动标签&-->
<mvc:default-servlet-handler />
<!-- 开启mvc注解驱动 -->
<mvc:annotation-driven />
<!-- 控制页面跳转 设置视图控制器,要开启mvc的注解驱动 需要注解驱动标签-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!-- 配置文件上传解析器-->
<bean id="mult" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
</beans>
spring配置文件
<?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"
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 扫描组件-->
<context:component-scan base-package="com.qwq">
<!-- 排除扫描-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 指定properties文件的位置-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!-- 数据源 -->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" >
<property name="driverClassName" value="${jdbc.driver}"/>
<!-- 连接数据库的url字符串-->
<property name="url" value="${jdbc.url}"/>
<!-- 访问数据库的用户名-->
<property name="username" value="${jdbc.user}"/>
<!-- 访问数据库的密码-->
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 1.配置事物管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 配置数据源-->
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!-- 2.开启事物注解驱动
使用@Transactional注解标识的方法或类中所有的方法进行事物的管理
transaction-manager="transactionManager" 设置事务管理器的Id
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置用于创建SqlSessionFactory的工厂bean 简化创建sql域对象的步骤 -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 设置MyBatis配置文件的路径(可以不设置) -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 设置数据源 -->
<property name="dataSource" ref="druidDataSource"></property>
<!-- 设置类型别名所对应的包 -->
<property name="typeAliasesPackage" value="com.qwq.pojo"></property>
</bean>
<!-- 配置mapper扫描,可以将指定包下,创建sqlsession实现对象,交给容器处理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.qwq.mapper"></property>
</bean>
</beans>
mybatis配置文件
mybatis-config
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--将下划线映射为驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<plugins>
<!--配置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
分页
/**
* 分页
* @param pageNum servlet
* @return
*/
public PageInfo<emp> SelectPage(Integer pageNum) {
//开启分页
PageHelper.startPage(pageNum,4);
List<emp> emps = empmapper.selectEmp();
// 获取分页相关数据
PageInfo<emp> page = new PageInfo<emp>(emps,5);
return page;
}
controller
@RequestMapping(value = "/employee/page/{pageNum}")
public ModelAndView SelectPageEmp(ModelAndView mv,@PathVariable Integer pageNum){
PageInfo<emp> empPageInfo = employeeServiceI.SelectPage(pageNum);
mv.addObject("page",empPageInfo);
mv.setViewName("employee_list");
return mv;
}
<a th:href="@{/employee/page/1}">分页查询员工的</a>
<div style="text-align: center;">
<a th:if="${page.hasPreviousPage}" th:href="@{/employee/page/1}">首页</a>
<a th:if="${page.hasPreviousPage}" th:href="@{'/employee/page/'+${page.prePage}}">上一页</a>
<span th:each="num : ${page.navigatepageNums}">
<a th:if="${page.pageNum == num}" style="color: red;" th:href="@{'/employee/page/'+${num}}" th:text="'['+${num}+']'"></a>
<a th:if="${page.pageNum != num}" th:href="@{'/employee/page/'+${num}}" th:text="${num}"></a>
</span>
<a th:if="${page.hasNextPage}" th:href="@{'/employee/page/'+${page.nextPage}}">下一页</a>
<a th:if="${page.hasNextPage}" th:href="@{'/employee/page/'+${page.pages}}">末页</a>
</div>