服务器启动阶段处理
分析服务器启动阶段都都需要初始化什么?
1.初始化Spring容器
- 组件扫描包下的类纳入IOC容器管理
- 创建视图解析器对象
- 创建所有的拦截器对象
- 扫描这和包下的所有类org.myspringmvc.web.servlet.mvc.method.annotation,全部实例化,纳入IoC容器管理
Spring容器:ApplicationContext
SpringWeb容器:WebApplicationContext
组件扫描
springmvc.xml文件
<?xml version="1.0" encoding="utf-8" ?><beans><!--拦截器视图解析器组件扫描--><component-scan base-package="org.springmvc.oa.controller"/>
<!-- 视图解析器--><bean class="org.springmvc.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀--><property name="prefix"><value>/WEB-INF/jsp/</value></property>
<!-- 后缀--><property name="suffix"><value>.jsp</value></property></bean><!-- 拦截器--><interceptors><bean class="org.springmvc.oa.interceptors.Interceptor1"></bean><bean class="org.springmvc.oa.interceptors.Interceptor2"></bean></interceptors>
</beans>
添加解析XML文件的依赖
<!--dom4j-->
<dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version>
</dependency>
<!--jaxen-->
<dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1.6</version>
</dependency>
ApplicationContext
public class ApplicationContext {private Map<String, Object> beanMap = new HashMap<>();public ApplicationContext(String xmlPath) throws Exception {// 组件扫描SAXReader saxReader = new SAXReader();Document document = saxReader.read(new File(xmlPath));Element componentScanElement = (Element)document.selectSingleNode("/beans/context:component-scan");String basePackage = componentScanElement.attributeValue("base-package");System.out.println("组件扫描:" + basePackage);componentScan(basePackage);System.out.println("Spring Web容器当下状态:" + beanMap);}private void componentScan(String basePackage) throws Exception{String dirPath = Thread.currentThread().getContextClassLoader().getResource(basePackage.replace(".", "/")).getPath();File file = new File(URLDecoder.decode(dirPath));if(file.isDirectory()){File[] files = file.listFiles();for (File classFile : files){if(classFile.getName().endsWith(".class")){String className = basePackage + "." + classFile.getName().substring(0, classFile.getName().lastIndexOf("."));Class<?> clazz = Class.forName(className);Constructor<?> defaultCon = clazz.getDeclaredConstructor();Object bean = defaultCon.newInstance();beanMap.put(firstCharLowerCase(clazz.getSimpleName()), bean);}}}}private String firstCharLowerCase(String simpleName) {return simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);}public Object getBean(String beanName){return beanMap.get(beanName);}
}
组件扫描的beanMap结果
WebApplicationContext
package org.springmvc.web.context;import jakarta.servlet.ServletContext;
import org.dom4j.DocumentException;
import org.springmvc.context.ApplicationContext;import java.lang.reflect.InvocationTargetException;public class WebApplicationContext extends ApplicationContext {private ServletContext servletContext;private String springMvcConfigPath;public WebApplicationContext() {}public WebApplicationContext(ServletContext servletContext, String springMvcConfigPath) throws DocumentException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {super(springMvcConfigPath);this.servletContext = servletContext;this.springMvcConfigPath = springMvcConfigPath;}/*** 获取* @return servletContext*/public ServletContext getServletContext() {return servletContext;}/*** 设置* @param servletContext*/public void setServletContext(ServletContext servletContext) {this.servletContext = servletContext;}/*** 获取* @return springMvcConfigPath*/public String getSpringMvcConfigPath() {return springMvcConfigPath;}/*** 设置* @param springMvcConfigPath*/public void setSpringMvcConfigPath(String springMvcConfigPath) {this.springMvcConfigPath = springMvcConfigPath;}public String toString() {return "WebApplicationContext{servletContext = " + servletContext + ", springMvcConfigPath = " + springMvcConfigPath + "}";}
}
创建视图解析器对象
InternalResourceViewResolver
内部资源视图解析器
package org.springmvc.web.servlet.view;import org.springmvc.web.servlet.View;
import org.springmvc.web.servlet.ViewResolver;import java.util.Locale;/*内部资源解析器*/
public class InternalResourceViewResolver implements ViewResolver {String prefix;String suffix;public InternalResourceViewResolver() {}public InternalResourceViewResolver(String prefix, String suffix) {this.prefix = prefix;this.suffix = suffix;}/*将逻辑试图名字 转换为物理视图名称 并以View对象返回*/@Overridepublic View resolveViewName(String viewName, Locale locale) throws Exception {return new InternalResourceView("text/html;charset-UTF-8", prefix+viewName+suffix);}/*** 获取* @return prefix*/public String getPrefix() {return prefix;}/*** 设置* @param prefix*/public void setPrefix(String prefix) {this.prefix = prefix;}/*** 获取* @return suffix*/public String getSuffix() {return suffix;}/*** 设置* @param suffix*/public void setSuffix(String suffix) {this.suffix = suffix;}public String toString() {return "InternalResourceViewResolver{prefix = " + prefix + ", suffix = " + suffix + "}";}/*** 获取* @return suffix*//*** 获取* @return prefix*/}
创建视图解析器对象
private void createViewResolver(Element viewResolverElement) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {String viewResolverClassName=viewResolverElement.attributeValue("class");System.out.println("视图解析器类名"+viewResolverClassName);Class clazz= Class.forName(viewResolverClassName);Object bean = clazz.newInstance();//bean节点下子节点propertyList<Element> propertyElements=viewResolverElement.elements(Constant.PROPERTY_TAG_NAME);for(Element propertyElement:propertyElements){//获取属性名String fieldName=propertyElement.attributeValue(Constant.PROPERTY_NAME);String value=propertyElement.element(Constant.PROPERTY_VALUE).getTextTrim();//将属性名转为set方法String setMethodName=fieldNameToSetMethod(fieldName);//通过反射机制调用set方法Method setMethod = clazz.getDeclaredMethod(setMethodName,String.class);setMethod.invoke(bean,value);}beanMap.put(Constant.VIEW_RESOLVER, bean);}
创建拦截器对象
private void createInteceptor(Element interceptorElement) throws ClassNotFoundException, InstantiationException, IllegalAccessException {List<Element> interceptorElements=interceptorElement.elements("bean");List<HandlerInterceptor> interceptors=new ArrayList<>();for(Element interceptor:interceptorElements){Class<?> clazz=Class.forName(interceptor.attributeValue("class"));Object bean=clazz.newInstance();interceptors.add((HandlerInterceptor)bean);}beanMap.put(Constant.INTERCEPROTS,interceptors);}
2.初始化HandlerMapping和初始化HandlerAdapter
初始化annotation包下所有类的实例
private void createHandlerMapping(String defaultPackage,Map<RequestMappingInfo, HandlerMethod>map) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//System.out.println(defaultPackage);// 将这个包下所有的类实例化:org.myspringmvc.web.servlet.mvc.method.annotation//获取绝对路径String dirPath=Thread.currentThread().getContextClassLoader().getResource(defaultPackage.replace('.', '/')).getPath();File file=new File(URLDecoder.decode(dirPath));//获取里面所有的子文件if(file.isDirectory()){File[] files = file.listFiles();for(File classFile : files){if(classFile.getName().endsWith(Constant.SUFFER_CLASS)){//全类名String className=defaultPackage+"."+classFile.getName().substring(0,classFile.getName().lastIndexOf("."));Class<?>clazz=Class.forName(className);if(HandlerMapping.class.isAssignableFrom(clazz)){Constructor<?>defaultCon= clazz.getDeclaredConstructor(Map.class);Object bean=defaultCon.newInstance(map);beanMap.put(Constant.HANDLER_MAPPING, bean);}if(HandlerAdapter.class.isAssignableFrom(clazz)){Constructor<?>defaultCon= clazz.getDeclaredConstructor();Object bean=defaultCon.newInstance();beanMap.put(Constant.HANDLER_ADAPTER, bean);}}}}}
2.初始化Servlet对象
DispatchServlet init()
public void init(){//找到springmvc.xml文件/*<init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param>*///根据以上配置springmvc.xml文件//获取SpringConfig对象(Servlet配置信息对象 该对象由web容器自动创建 并且将其传递给init方法// )ServletConfig servletConfig = this.getServletConfig();String contextConfigLocation = servletConfig.getInitParameter(Constant.CONTEXT_CONFIG_LOCATION);String springMvcXmlPath=getSpringMvcXmlPath(contextConfigLocation);System.out.println("Spring MVC配置文件路径解析完成:" + springMvcXmlPath);//初始化Spring Web容器WebApplicationContext webApplicationContext = null;try {webApplicationContext = new WebApplicationContext(this.getServletContext(), springMvcXmlPath);} catch (DocumentException e) {throw new RuntimeException(e);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}this.getServletContext().setAttribute(Constant.WEB_APPLICATION_CONTEXT, webApplicationContext);//初始化HandlerMappingthis.handlerMapping=(HandlerMapping)webApplicationContext.getBean(Constant.HANDLER_MAPPING);//初始化HandlerAdapterthis.handlerAdapter=(HandlerAdapter)webApplicationContext.getBean(Constant.HANDLER_ADAPTER);//初始化试图解析器this.viewResolver=(ViewResolver)webApplicationContext.getBean(Constant.VIEW_RESOLVER);}private String getSpringMvcXmlPath(String contextConfigLocation) {if(contextConfigLocation.startsWith(Constant.CLASSPATH)){String path=contextConfigLocation.substring(Constant.CLASSPATH.length()).trim();//类路径中找String springMvcXmlPath=Thread.currentThread().getContextClassLoader().getResource(path).getPath();// 对路径解码,防止路径中有 % 等字符。return URLDecoder.decode(springMvcXmlPath, Charset.defaultCharset());}return null;}
doDispath方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {try {doDispatch(req, resp);} catch (Exception e) {throw new RuntimeException(e);}}/*** 处理请求的核心方法* @param request* @param response* @throws ServletException* @throws IOException*/private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {//访问浏览器才能断点到这//请求对象获取对应的处理器执行连对象HandlerExecutionChain mappedHandler=handlerMapping.getHandler(request);//获取处理器适配器对象HandlerAdapter adapter = this.handlerAdapter;//3.执行拦截器中的preHandle方法if(!mappedHandler.applyPreHandle(request,response)){return;//false的话}//4.执行处理器方法 返回ModelAndViewModelAndView mv=adapter.handle(request,response,mappedHandler.getHandler());System.out.println("处理器执行连对象:"+mappedHandler);//5.执行拦截器中postHanldermappedHandler.applyPostHandle(request,response,mv);//6.试图解析器 逻辑试图名称转为物理视图名称View view=viewResolver.resolveViewName(mv.getView().toString(),request.getLocale());view.render(mv.getModel(),request,response);//执行拦截器渲染之后的afterCompletetion方法mappedHandler.triggerAfterCompletion(request,response,null);}
根据请求获取处理器执行链
HandlerExecutionChain mappedHandler=handlerMapping.getHandler(request);
HandlerMapping
public interface HandlerMapping {/*** ClassName: HandlerMapping* Description: 主要是通过请求获取对应的处理器执行链。* Datetime: 2024/4/2 8:50* Author: 老杜@动力节点* Version: 1.0*/HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
HandlerMethod
package org.springmvc.web.method;import java.lang.reflect.Method;/*处理器方法 controller*/
public class HandlerMethod {/*处理器对象*/private Object handler;/*** 要执行的方法*/private Method method;public HandlerMethod() {}public HandlerMethod(Object handler, Method method) {this.handler = handler;this.method = method;}/*** 获取* @return handler*/public Object getHandler() {return handler;}/*** 设置* @param handler*/public void setHandler(Object handler) {this.handler = handler;}/*** 获取* @return method*/public Method getMethod() {return method;}/*** 设置* @param method*/public void setMethod(Method method) {this.method = method;}public String toString() {return "HandlerMethod{handler = " + handler + ", method = " + method + "}";}
}
RequestMappingInfo
package org.springmvc.web.servlet;import java.util.Objects;public class RequestMappingInfo {private String requestURI;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;RequestMappingInfo that = (RequestMappingInfo) o;return Objects.equals(requestURI, that.requestURI) && Objects.equals(method, that.method);}@Overridepublic int hashCode() {return Objects.hash(requestURI, method);}//GET POST PUT DELETEprivate String method;public RequestMappingInfo() {}public RequestMappingInfo(String requestURI, String method) {this.requestURI = requestURI;this.method = method;}/*** 获取* @return requestURI*/public String getRequestURI() {return requestURI;}/*** 设置* @param requestURI*/public void setRequestURI(String requestURI) {this.requestURI = requestURI;}/*** 获取* @return method*/public String getMethod() {return method;}/*** 设置* @param method*/public void setMethod(String method) {this.method = method;}public String toString() {return "RequestMappingInfo{requestURI = " + requestURI + ", method = " + method + "}";}
}
RequestMappingHandlerMapping
package org.springmvc.web.servlet.mvc.method.annotation;import jakarta.servlet.http.HttpServletRequest;
import org.springmvc.web.constant.Constant;
import org.springmvc.web.context.WebApplicationContext;
import org.springmvc.web.method.HandlerMethod;
import org.springmvc.web.servlet.*;import java.util.List;
import java.util.Map;/*处理器映射器 专门为 @RequestMapping 注解的类服务的处理器映射器通过前端提交的请求 来底层映射要执行的HandlerMethod*/
public class RequestMappingHandlerMapping implements HandlerMapping {private Map<RequestMappingInfo, HandlerMethod> map;/*创建HandlerMapping对象时 给map赋值*/public RequestMappingHandlerMapping(Map<RequestMappingInfo, HandlerMethod> map) {this.map = map;}@Overridepublic HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {//通过request对象 获取请求路径,请求方式 封装程RequestMappingInfoRequestMappingInfo requestMappingInfo=new RequestMappingInfo(request.getServletPath(),request.getMethod());//******************必须重写 如果补充写 key是对象 对于相同请求创建多个对象 可能认为是不同的HandlerExecutionChain handlerExecutionChain =new HandlerExecutionChain();//给执行连设置handlerMethodhandlerExecutionChain.setHandler(map.get(requestMappingInfo));//给执行连设置拦截器//通过Spring容器WebApplicationContext webApplicationContext=(WebApplicationContext)request.getServletContext().getAttribute(Constant.WEB_APPLICATION_CONTEXT);List<HandlerInterceptor> interceptors=(List<HandlerInterceptor>)webApplicationContext.getBean(Constant.INTERCEPROTS);handlerExecutionChain.setInterceptors(interceptors);return handlerExecutionChain;}
}
处理器执行链对象
注意:
public RequestMappingHandlerMapping(Map<RequestMappingInfo, HandlerMethod> map) {
this.map = map;
}包扫描的时候初始化RequestMappingHandlerMapping时 要传入Map对象 所以包扫描要改为下面的代码
private Map<RequestMappingInfo, HandlerMethod> componentScan(String basePackage) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Map<RequestMappingInfo, HandlerMethod>handlerMethodMap=new HashMap<>();//获取绝对路径String dirPath=Thread.currentThread().getContextClassLoader().getResource(basePackage.replace(".","/")).getPath();File file=new File(URLDecoder.decode(dirPath));//封装为文件//获取里面所有的子文件if(file.isDirectory()){File[] files = file.listFiles();for(File classFile:files){if(classFile.getName().endsWith(Constant.SUFFER_CLASS)){String className=basePackage+"."+classFile.getName().substring(0,classFile.getName().lastIndexOf("."));Class<?> clazz = Class.forName(className);Constructor<?>defaultCon= clazz.getDeclaredConstructor();//System.out.println("简单类名"+clazz.getSimpleName());Object bean=defaultCon.newInstance();beanMap.put(firstCharLowerCase(clazz.getSimpleName()), bean);//UserController 默认beanName 首字母小写//获取类上面的注解 @Controller注解包围if(clazz.isAnnotationPresent(Controller.class)){//被Controller注解包裹//获取类中所有的方法Method []methods=clazz.getDeclaredMethods();for(Method method:methods){//如果该注解被RequestMapping注解包裹if(method.isAnnotationPresent(RequestMapping.class)){RequestMapping requestMapping=method.getAnnotation(RequestMapping.class);String requestURI=requestMapping.value()[0];String requestMethod=requestMapping.method().toString();// GETRequestMappingInfo requestMappingInfo=new RequestMappingInfo(requestURI,requestMethod);HandlerMethod handlerMethod=new HandlerMethod();//请求的方法handlerMethod.setHandler(bean);handlerMethod.setMethod(method);handlerMethodMap.put(requestMappingInfo,handlerMethod);}}}}}}
执行拦截器的中preHandler方法
public boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i <interceptors.size() ; i++) {HandlerInterceptor handlerInterceptor = interceptors.get(i);boolean result=handlerInterceptor.preHandle(request,response,handler);if(!result){//执行拦截器的AfterCompletiontriggerAfterCompletion(request,response,handler);return false;}}return true;}
.执行处理器方法 返回ModelAndView
public interface HandlerAdapter {ModelAndView handle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception;
}public class RequestMappingHandlerAdapter implements HandlerAdapter {@Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//需要调用处理器方法HandlerMethod handlerMethod = (HandlerMethod)handler;//获取控制器Object controller=handlerMethod.getHandler();//获取调用的方法Method method=handlerMethod.getMethod();ModelMap modelMap=new ModelMap();//通过反射机制调用String viewName=(String)method.invoke(controller,modelMap);//自己写的目前需要 Controller指定ModelMap//还有一个特殊要求 要求返回逻辑试图名称ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName(viewName);modelAndView.setModel(modelMap);return modelAndView;}
}package org.springmvc.ui;import java.util.LinkedHashMap;public class ModelMap extends LinkedHashMap<String, Object> {public ModelMap() {}public ModelMap addAttribute(String name, String value) {this.put(name,value);return this;}
}package org.springmvc.oa.controller;import org.springmvc.stereotype.Controller;
import org.springmvc.ui.ModelMap;
import org.springmvc.web.bind.annotation.RequestMapping;
import org.springmvc.web.bind.annotation.RequestMethod;@Controller
public class UserController {@RequestMapping(value ="/index", method = RequestMethod.GET)public String index(ModelMap modelMap){modelMap.put("name","liwu");return "index";}
}
执行拦截器中postHanlder
public void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {for(int i=interceptors.size()-1;i>=0;i--){HandlerInterceptor handlerInterceptor = interceptors.get(i);handlerInterceptor.postHandle(request,response,handler,mv);}}
视图解析器 逻辑试图名称转为物理视图名称
public interface ViewResolver {/*解析逻辑视图名称,返回视图对象*/View resolveViewName(String viewName, Locale locale) throws Exception;}public View resolveViewName(String viewName, Locale locale) throws Exception {return new InternalResourceView("text/html;charset-UTF-8", prefix+viewName+suffix);}public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {//设置响应类型response.setContentType(contentType);//将model数据存储到request域中//默认情况下跳转到视图以转发方式model.forEach((key,value)->{request.setAttribute(key,value);});request.getRequestDispatcher(path).forward(request,response);}
执行拦截器渲染之后的afterCompletetion方法
public void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {for(int i=interceptors.size()-1;i>=0;i--){HandlerInterceptor handlerInterceptor = interceptors.get(i);handlerInterceptor.afterCompletion(request, response,handler, (Exception) o);}}
SSM整合
引入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.springmvc</groupId><artifactId>ssm-annotation</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><dependencies><!--springmvc--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.1.4</version></dependency><!--spring jdbc--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.1.4</version></dependency><!--mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.15</version></dependency><!--mybatis spring--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.3</version></dependency><!--mysql驱动--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.3.0</version></dependency><!--德鲁伊连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.22</version></dependency><!--jackson--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.17.0</version></dependency><!--servlet api--><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId><version>6.0.0</version><scope>provided</scope></dependency><!--logback--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.5.3</version></dependency><!--thymeleaf和spring6的整合依赖--><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring6</artifactId><version>3.1.2.RELEASE</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope></dependency></dependencies><properties><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>
创建包结构
创建webapp目录
Spring整合Mybatis
编写mybatis.properties
mybatis.driverClassName=com.mysql.cj.jdbc.Driver
mybatis.url=jdbc:mysql://localhost:3306/db03?useSSL=false&allowPublicKeyRetrieval=true
mybatis.username=root
mybatis.password=123456
mybatis.mapperLocations=classpath*:com/gao/ssm/dao/*Mapper.xml
MybatisProperties
package com.gao.ssm.dao;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;@Component
@PropertySource("classpath:mybatis.properties")
public class MybatisProperties {@Value("${mybatis.driverClassName}")private String driverClassName;@Value("${mybatis.url}")private String url;@Value("${mybatis.username}")private String username;@Value("${mybatis.password}")private String password;@Value("${mybatis.mapperLocations}")private String mapperLocations;public MybatisProperties() {}public MybatisProperties(String driverClassName, String url, String username, String password, String mapperLocations) {this.driverClassName = driverClassName;this.url = url;this.username = username;this.password = password;this.mapperLocations = mapperLocations;}/*** 获取* @return driverClassName*/public String getDriverClassName() {return driverClassName;}/*** 设置* @param driverClassName*/public void setDriverClassName(String driverClassName) {this.driverClassName = driverClassName;}/*** 获取* @return url*/public String getUrl() {return url;}/*** 设置* @param url*/public void setUrl(String url) {this.url = url;}/*** 获取* @return username*/public String getUsername() {return username;}/*** 设置* @param username*/public void setUsername(String username) {this.username = username;}/*** 获取* @return password*/public String getPassword() {return password;}/*** 设置* @param password*/public void setPassword(String password) {this.password = password;}/*** 获取* @return mapperLocations*/public String getMapperLocations() {return mapperLocations;}/*** 设置* @param mapperLocations*/public void setMapperLocations(String mapperLocations) {this.mapperLocations = mapperLocations;}public String toString() {return "MybatisProperties{driverClassName = " + driverClassName + ", url = " + url + ", username = " + username + ", password = " + password + ", mapperLocations = " + mapperLocations + "}";}
}
MybatisConfig
package com.gao.ssm.config;import com.alibaba.druid.pool.DruidDataSource;
import com.gao.ssm.dao.MybatisProperties;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;
import java.io.IOException;@Configuration
@ComponentScan("com.gao.ssm.dao")
@MapperScan("com.gao.ssm.dao")
public class MybatisConfig {@Autowiredprivate MybatisProperties mybatisProperties;@Beanpublic DataSource dataSource(){DruidDataSource dataSource=new DruidDataSource();dataSource.setUsername(mybatisProperties.getUsername());dataSource.setPassword(mybatisProperties.getPassword());dataSource.setUrl(mybatisProperties.getUrl());dataSource.setDriverClassName(mybatisProperties.getDriverClassName());return dataSource;}@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws IOException {SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);ResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();Resource[]resources=resolver.getResources(mybatisProperties.getMapperLocations());sqlSessionFactoryBean.setMapperLocations(resources);return sqlSessionFactoryBean;}@Beanpublic PlatformTransactionManager platformTransactionManager(DataSource dataSource){DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
}
SpringConfig
package com.gao.ssm.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;@Configuration
@ComponentScan("com.gao.ssm.service")
@EnableTransactionManagement
@Import({MybatisConfig.class})
public class SpringConfig {
}
Spring整合Spring MVC
package com.gao.ssm.config;import jakarta.servlet.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;@Configuration
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {/*配置Spring的配置文件*/@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[0];}/*SpringMVC配置文件*/@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}/*配置DispatcherServlet的映射规则,即url-pattern*/@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}/*** Spring的配置* @return*/@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();characterEncodingFilter.setEncoding("UTF-8");characterEncodingFilter.setForceRequestEncoding(true);characterEncodingFilter.setForceResponseEncoding(true);//!--隐藏的HTTP请求方式过滤器 字符编码过滤器之后-->HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};}}
SpringMvcConfig
package com.gao.ssm.config;import com.gao.ssm.interceptor.MyInterceptor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.thymeleaf.spring6.SpringTemplateEngine;
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring6.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;import java.util.List;
import java.util.Properties;@Configuration
@ComponentScan("com.gao.ssm.handler")
@Import({SpringConfig.class})
@EnableWebMvc
//开启注解驱动
public class SpringMvcConfig implements WebMvcConfigurer {@Overridepublic void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {SimpleMappingExceptionResolver simpleHandlerExceptionResolver=new SimpleMappingExceptionResolver();Properties prop = new Properties();prop.setProperty("java.lang.Exception", "tip");simpleHandlerExceptionResolver.setExceptionMappings(prop);simpleHandlerExceptionResolver.setExceptionAttribute("e");resolvers.add(simpleHandlerExceptionResolver);}@Beanpublic ThymeleafViewResolver getViewResolver(SpringTemplateEngine springTemplateEngine) {ThymeleafViewResolver resolver = new ThymeleafViewResolver();resolver.setTemplateEngine(springTemplateEngine);resolver.setCharacterEncoding("UTF-8");resolver.setOrder(1);return resolver;}@Beanpublic SpringTemplateEngine templateEngine(ITemplateResolver iTemplateResolver) {SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(iTemplateResolver);return templateEngine;}public void addInterceptors(InterceptorRegistry registry) {MyInterceptor myInterceptor = new MyInterceptor();registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/test");}@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/index").setViewName("index");}@Beanpublic ITemplateResolver templateResolver(ApplicationContext applicationContext) {SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();resolver.setApplicationContext(applicationContext);resolver.setPrefix("/WEB-INF/thymeleaf/");resolver.setSuffix(".html");resolver.setTemplateMode(TemplateMode.HTML);resolver.setCharacterEncoding("UTF-8");resolver.setCacheable(false);//开发时关闭缓存,改动即可生效return resolver;}@Override//开启静态资源处理public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}
}
添加事务控制
@Configuration
@ComponentScan("com.gao.ssm.service")
@EnableTransactionManagement
@Import({MybatisConfig.class})
public class SpringConfig {
}@Transactional()
@Service
public class EmpServiceImpl implements EmpService{
pojo类编写
package com.gao.ssm.bean;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDate;
import java.time.LocalDateTime;/*** 员工实体类*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {private Integer id; //IDprivate String username; //用户名private String password; //密码private String name; //姓名private Short gender; //性别 , 1 男, 2 女private String image; //图像urlprivate Short job; //职位 , 1 班主任 , 2 讲师 , 3 学工主管 , 4 教研主管 , 5 咨询师private LocalDate entrydate; //入职日期private Integer deptId; //部门IDprivate LocalDateTime createTime; //创建时间private LocalDateTime updateTime; //修改时间
}
dao编写
package com.gao.ssm.dao;import com.gao.ssm.bean.Emp;
import org.apache.ibatis.annotations.Mapper;import java.util.List;
public interface EmpDao {List<Emp> listAll();Emp listOne(Emp emp);void add(Emp emp);
}
service编写
package com.gao.ssm.service;import com.gao.ssm.bean.Emp;import java.util.List;public interface EmpService{public void register(Emp emp);public List<Emp> listAll();}
package com.gao.ssm.service;import com.gao.ssm.bean.Emp;
import com.gao.ssm.dao.EmpDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Transactional()
@Service
public class EmpServiceImpl implements EmpService{@Autowiredprivate EmpDao empDao;@Overridepublic void register(Emp emp) {empDao.add(emp);}@Overridepublic List<Emp> listAll() {return empDao.listAll();}
}
handler编写
package com.gao.ssm.handler;import com.gao.ssm.bean.Emp;
import com.gao.ssm.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/emp")
public class EmpController {@Autowiredprivate EmpService empService;@RequestMapping("/list")public String list(){return empService.listAll().toString();}
}
EmpMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//MyBatis//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.gao.ssm.dao.EmpDao"><!-- 查询所有员工 --><select id="listAll" resultType="com.gao.ssm.bean.Emp">SELECT * FROM emp</select><!-- 根据 ID 查询单个员工 --><select id="listOne" resultType="com.gao.ssm.bean.Emp" parameterType="java.lang.Integer">SELECT * FROM emp WHERE id = #{id}</select><!-- 添加员工,返回主键 ID --><insert id="add" parameterType="com.gao.ssm.bean.Emp" useGeneratedKeys="true" keyProperty="id">INSERT INTO emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)VALUES (#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})</insert></mapper>
测试
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>ssm整合</title><!--引入vue--><script th:src="@{/static/js/vue3.4.21.js}"></script><!--引入axios--><script th:src="@{/static/js/axios.min.js}"></script>
</head>
<body>
<div id="app"><button @click="getMessage">查询所有用户</button><h1>{{message}}</h1>
</div>
<script th:inline="javascript">Vue.createApp({data(){return {message : '很多信息'}},methods : {async getMessage(){console.log("------------查询")let response = await axios.get("/ssm/emp/list")console.log(response)this.message = response.data}}}).mount("#app")
</script>
</body>
</html>