pom.xml引用包配置:
<?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.example</groupId> <artifactId>spring-mvc-sumup</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.28</version> </dependency> <!--aop依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.28</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>5.3.28</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.3.28</version> </dependency> <dependency> <groupId>aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.4</version> </dependency> <!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!--druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.18</version> </dependency> <!--mybatis核心依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.13</version> </dependency> <!--mybatis spring适配--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.1.1</version> </dependency> <!--mybatis mapper生成插件--> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.4.2</version> </dependency> <!--===============================================================================--> <!--数据验证依赖包: https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.2.5.Final</version> </dependency> <!-- json支持 https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.5</version> </dependency> <!-- 文件上传https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.5</version> </dependency> </dependencies> </project>View Code
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_3_1.xsd" version="3.1"> <!--default servlet处理静态资源--> <!-- <servlet-mapping>--> <!-- <servlet-name>default</servlet-name>--> <!-- <url-pattern>*.js</url-pattern>--> <!-- </servlet-mapping>--> <!-- <servlet-mapping>--> <!-- <servlet-name>default</servlet-name>--> <!-- <url-pattern>*.css</url-pattern>--> <!-- </servlet-mapping>--> <!-- <servlet-mapping>--> <!-- <servlet-name>default</servlet-name>--> <!-- <url-pattern>*.eot</url-pattern>--> <!-- </servlet-mapping>--> <!-- <servlet-mapping>--> <!-- <servlet-name>default</servlet-name>--> <!-- <url-pattern>*.svg</url-pattern>--> <!-- </servlet-mapping>--> <!-- <servlet-mapping>--> <!-- <servlet-name>default</servlet-name>--> <!-- <url-pattern>*.ttf</url-pattern>--> <!-- </servlet-mapping>--> <!-- <servlet-mapping>--> <!-- <servlet-name>default</servlet-name>--> <!-- <url-pattern>*.woff</url-pattern>--> <!-- </servlet-mapping>--> <!-- <servlet-mapping>--> <!-- <servlet-name>default</servlet-name>--> <!-- <url-pattern>*.woff2</url-pattern>--> <!-- </servlet-mapping>--> <!--配置springmvc--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--配置spring--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <!--配置编码:如果配置了多个过滤器,那么字符编码过滤器一定要在最前面,否则失效--> <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> <!-- <servlet-name>dispatcherServlet</servlet-name>--> <url-pattern>/*</url-pattern> </filter-mapping> <!--处理html 不支持 put delete--> <filter> <filter-name>hiddenFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenFilter</filter-name> <!--<servlet-name>dispatcherServlet</servlet-name>--> <url-pattern>/*</url-pattern> </filter-mapping> <!--过滤jsp 不处理put delete 的自定义过滤器,只能过滤 FORWARD--> <filter> <filter-name>restFilter</filter-name> <filter-class>com.mvc.filter.RestFilter</filter-class> </filter> <filter-mapping> <filter-name>restFilter</filter-name> <url-pattern>/*</url-pattern> <!--注意:只过滤转发--> <dispatcher>FORWARD</dispatcher> </filter-mapping> </web-app>View Code
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/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"> <!--设置springmvc 扫描路径--> <context:component-scan base-package="com.mvc.controler"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!--默认视图解析器-配上前缀和后缀,简化逻辑视图名称 (视图模板?)--> <!-- org.springframework.web.servlet.DispatcherServlet 同一目录的 .properties 里 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"> <property name="prefix" value="/WEB-INF/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--视图控制器 (立即访问) path:映射路径 view-name:访问名称 也会走 viewResolver 注意:1.使用了这个标签后必须配置 <mvc:annotation-driven /> 否则会造成所有的@Controller注解无法解析,导致404错误 2.如果请求存在处理器,则这个标签对应的请求处理将不起作用。因为请求是先去找处理器处理,如果找不到才会去找这个标签配置 --> <!-- <mvc:view-controller path="/" view-name="main"></mvc:view-controller>--> <!-- 保证静态资源和动态请求都能够访问 --> <mvc:annotation-driven></mvc:annotation-driven> <!--访闻静态资源 此配置表示 我们自己配置的请求由controller来处理,但是不能请求的处理交由tomcat来处理 静态资源可以访问,但是动态请求无法访问 --> <mvc:default-servlet-handler/> <!-- 当配置了类型转换器,需要配置FormattingConversionServiceFactoryBean才能同时支持格式化和类型转换--> <mvc:annotation-driven conversion-service="conversionServiceName"></mvc:annotation-driven> <bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="conversionServiceName"> <property name="converters"> <set> <bean class="com.mvc.converter.MyDateConverter" id="converter"></bean> </set> </property> </bean> <!--基于CommonsMultipartResolver 文件上传解析器--> <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"> <!--设置编码格式--> <property name="defaultEncoding" value="utf-8"></property> <!--文件上传最大字节数--> <property name="maxUploadSize" value="#{1024*1024}"></property> </bean> <!--配置拦截器--> <mvc:interceptors> <!--直接配置一个bean会拦截springmvc的所有请求--> <bean class="com.mvc.interceptor.MyInterceptor"></bean> <!-- 如果不是所有的请求都要拦截,可以加一个<mvc:interceptor>--> <mvc:interceptor> <!--需要拦截请求--> <mvc:mapping path="/**"/> <!--不需要拦截的请求 (只会拦截get请求)--> <mvc:exclude-mapping path="/charpter07/logion"/> <!--放行静态资源文件夹(重要)--> <mvc:exclude-mapping path="/static/**"/> <bean class="com.mvc.interceptor.CheckLogionInterceptor" id="logionInterceptor"></bean> </mvc:interceptor> <!--国际化三:配置拦截器进行 请求参数 ?locale=zh_CN 必须携带locale参数--> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean> </mvc:interceptors> <!--设置国际化支持,配置国际化资源文件 id="messageSource“不能乱取名--> <bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource"> <!--setBaseNames()--> <property name="basenames"> <array> <value>i18n.logion</value> </array> </property> </bean> <!-- 使用SessionLocaleResolver,保持local状态,会从session中获取local对象 id="localeResolver"只能叫localeResolver,为了覆盖springmvc默认AcceptHeaderLocaleResolver 不配制的话默认使用的是 AcceptHeaderLocaleResolver,会从请求头里获取“Aceept-Language” 国际化二:SessionLocaleResolver 替换默认的 AcceptHeaderLocaleResolver --> <bean class="org.springframework.web.servlet.i18n.SessionLocaleResolver" id="localeResolver"></bean> </beans>View Code
spring.xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" 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 http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd"> <context:component-scan base-package="com.mvc"> <!-- 排除springmvc 扫描的部分--> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!--加载本地配置--> <context:property-placeholder location="classpath:db.properties"></context:property-placeholder> <!--连接池--> <bean class="com.alibaba.druid.pool.DruidDataSource" id="druidDataSource"> <property name="username" value="${mysql.username}"></property> <property name="password" value="${mysql.password}"></property> <property name="url" value="${mysql.url}"></property> <property name="driverClassName" value="${mysql.driverclassname}"></property> </bean> <!--配置事务--> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager"> <property name="dataSource" ref="druidDataSource"></property> </bean> <tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven> <!--配置mybatise--> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionFactory"> <property name="dataSource" ref="druidDataSource"></property> <property name="mapperLocations" value="classpath:com/mvc/mapper/*.xml"></property> <property name="configLocation" value="classpath:mybatise.xml"></property> </bean> <!--将mapper 交给mybatise 管理--> <mybatis:scan base-package="com.mvc.mapper"/> </beans>View Code
mybatise.xml 配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 如果需要一些 setting 设置,可以放在这里--> </configuration>
mybatis-jenerator.xml 参考:https://www.cnblogs.com/ruber/p/17557519.html
db.propertise 配置
mysql.username=root mysql.password=123456 mysql.url=jdbc:mysql://localhost:3306/mytest mysql.driverclassname=com.mysql.cj.jdbc.Driver
工程结构示意图:
以下是一些比较重要的工程代码:
自定义转换器:MyDateConverter.java
/** * @authour cyf * 2023/7/18 17:21 * 配置自定义转换器,支持 yyyy-MM-dd 和 yyyy/MM/dd 两种格式的输入 */ public class MyDateConverter implements Converter<String, Date> { @Override public Date convert(String source) { if(StringUtils.hasLength(source)){ try { if(source.split("/").length==3){ return new SimpleDateFormat("yyyy/MM/dd").parse(source); }else if(source.split("-").length == 3){ return new SimpleDateFormat("yyyy-MM-dd").parse(source); }else{ throw new RuntimeException("[日期格式不满足]:"+source); } } catch (ParseException e) { throw new RuntimeException(e); } }else{ return null; } } }View Code
自定义一个过滤器: RestFilter.java
/** * @authour cyf * 2023/7/17 22:59 * 自定义一个过滤器,将request.method改回POST */ public class RestFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(wrapRequest((HttpServletRequest) servletRequest), servletResponse); } private static HttpServletRequestWrapper wrapRequest(HttpServletRequest request) { return new HttpServletRequestWrapper(request) { @Override public String getMethod() { return "POST"; } }; } }View Code
拦截器接口说明及简单登录拦截器:MyInterceptor.java CheckLogionInterceptor.java
/** * @authour cyf * 2023/7/17 13:06 * 拦截器:各接口说明 */ public class MyInterceptor implements HandlerInterceptor { /** * @param request 可以在方法请求进来之前更改request中的属性值 * @param response * @param handler 封装了当前处理方法的信息 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //在请求映射到对应的处理方法映射,实现类才是HandlerMethod //如果是视图控制器,实现类是 ParameterizableViewController if(handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; String methodName = handlerMethod.getMethod().getName(); String className = handlerMethod.getBeanType().getSimpleName(); MethodParameter[] methodParameters = handlerMethod.getMethodParameters(); System.out.println("------类:[" + className + "]----方法[" + methodName + "] 参数:[" + Arrays.toString(methodParameters) + "]前执行---------------"); } return true;//返回false 会终止后面的执行 } /** * preHandle返回false 不会执行该方法 * 在请求之后,在视图渲染之前执行 * 当处理方法出现异常则不会执行(所以记录异常不能放在此方法) * @param request * @param response 可以在方法执行后去更改response中的信息 * @param handler 封装了当前处理方法的信息 * @param modelAndView 封装了 model 和 view,所以当请求结束后可以修改model中的数据或者新增model数据,有可以修改view的跳转 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("--------------方法执行后渲染前执行------------------"); } /** * preHandle返回false 不会执行该方法 * 是在视图渲染之后执行 ,相当于try catch finally 中的finally */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("--------------方法执行后渲染后执行------------------"); } }View Code
/** * @authour cyf * 2023/7/17 16:22 * 登录拦截器 */ public class CheckLogionInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //此处判断需要放行的静态资源 //String requestURI = request.getRequestURI(); //if(requestURI.endsWith(".js") || requestURI.endsWith(".css") || requestURI.endsWith(".js") || // requestURI.endsWith(".eot") || requestURI.endsWith(".svg") || requestURI.endsWith(".ttf") || // requestURI.endsWith(".woff") || requestURI.endsWith(".woff2") //){ // System.out.println("放行静态资源"); // return true; //} HttpSession session = request.getSession(); Object username = session.getAttribute("havaLogion"); //如果没有登录重定向到 logion 页面 if(!StringUtils.hasLength((String) username)){ String contextPath = request.getContextPath(); //重定向 response.sendRedirect(contextPath+"/charpter07/logion"); //会直接转发到post方法 //request.getRequestDispatcher("/charpter07/logion").forward(request, response); return false; } return true; } }View Code
注意:com.mvc.mapper 包路径和资源文件夹结构要保持一致,这样maven才会讲mapper和接口合并到一起。 也可以直接生成在包下面
resource下的 i18n 存放的是多语言资源
重要的一些配置:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <% pageContext.setAttribute("basepath", request.getContextPath()); %> <html> <head> <title>Title</title> <link href="${basepath}/static/layui/css/layui.css" type="text/css" rel="stylesheet"> <script src="${basepath}/static/layui/layui.js" type="text/javascript"></script> <script src="${basepath}/static/jquery/jquery-3.7.0.min.js"></script> </head> <body> <pre id="preid">等待数据回执。。。</pre> <button id="btnid" type="button" class="layui-btn">查询数据</button> </body> <script> $(function () { //jquery 加载后 $("#btnid").click(function () { //添加click事件回调 // alert("btn 测试"); $.ajax({ //ajax 发送post 请求 url: "${basepath}/ssmcontroler/check", type: "post", dataType: "json", contentType: "application/json;charset=utf-8",//指定返回数据格式,否则中文乱码 success: function(data) { $("#preid").text(data); } }) }); }); </script> </html>