idea 搭建springmvc项目,配置web.xml

我爱海鲸 2022-12-28 16:17:57 暂无标签

简介配置web.xml

1、搭建项目,请参考:idea搭建web maven项目

 

2、在web.xml中配置Spring以及SpringMVC等配置,如图:

  <!-- Spring beans 配置文件所在目录 -->

  <context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:applicationContext.xml</param-value>

  </context-param>

 

  <!-- spring mvc 配置 -->

  <servlet>

    <servlet-name>spring</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

  </servlet>

  <servlet-mapping>

    <servlet-name>spring</servlet-name>

    <url-pattern>/</url-pattern>

 

  </servlet-mapping>

 

<!-- 默认加载方式

       默认加载必须规范:

       * 文件命名:servlet-name-servlet.xml====springmvc-servlet.xml

       * 路径规范:必须在WEB-INF目录下面

 

   -->

可以修改配置文件名称,在.DispatcherServlet</servlet-class>后面,如:

   <init-param>

   <param-name>contextConfigLocation</param-name>

   <param-value>classpath:config/springmvc.xml</param-value>   

   </init-param>

undefined

 

这里解释一下   /    和  /*   

/   指的是匹配/login    /hello    等没有后缀的   不会匹配.jsp等资源

/*   指的是匹配所有的资源  css、jsp、html等等

 

3、配置Encoding 编码,如图:

 <!-- Encoding -->

  <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>

    <init-param>

      <param-name>forceEncoding</param-name>

      <param-value>true</param-value>

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>encodingFilter</filter-name>

    <url-pattern>/*</url-pattern>

 

  </filter-mapping>

undefined

4、配置访问的默认路径,如图:

undefined

2022-03-31

start:

完整的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">

  <display-name>Archetype Created Web Application</display-name>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <filter>
    <filter-name>characterEncoding</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>characterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- Spring beans 配置文件所在目录 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <!-- spring mvc 配置 -->
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!-- Encoding -->
  <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>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- druid -->
  <servlet>
    <servlet-name>DruidStatServlet</servlet-name>
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
    <init-param>
      <param-name>loginUsername</param-name>
      <param-value>druid</param-value>
    </init-param>
    <init-param>
      <param-name>loginPassword</param-name>
      <param-value>druid</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>DruidStatServlet</servlet-name>
    <url-pattern>/sys/druid/*</url-pattern>
  </servlet-mapping>
  <filter>
    <filter-name>DruidWebStatFilter</filter-name>
    <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
    <init-param>
      <param-name>exclusions</param-name>
      <param-value>*.js,*.css,*.jpg,*.png,*.ico,*.gif,/sys/druid/*</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>DruidWebStatFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

<!--  <login-config>-->
<!--    &lt;!&ndash; Authorization setting for SSL &ndash;&gt;-->
<!--    <auth-method>CLIENT-CERT</auth-method>-->
<!--    <realm-name>Client Cert Users-only Area</realm-name>-->
<!--  </login-config>-->
<!--  <security-constraint>-->
<!--    &lt;!&ndash; Authorization setting for SSL &ndash;&gt;-->
<!--    <web-resource-collection >-->
<!--      <web-resource-name >SSL</web-resource-name>-->
<!--      <url-pattern>/*</url-pattern>-->
<!--    </web-resource-collection>-->
<!--    <user-data-constraint>-->
<!--      <transport-guarantee>CONFIDENTIAL</transport-guarantee>-->
<!--    </user-data-constraint>-->
<!--  </security-constraint>-->

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

end

2022-04-01

start:

1、完整的项目截图

2、配置文件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" 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.alibaba.com/schema/stat http://www.alibaba.com/schema/stat.xsd
 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:component-scan base-package="xyz.haijin.shiro">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="locations">
            <list>
                <value>classpath:settings.properties</value>
            </list>
        </property>
    </bean>


    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="${db.driverClassName}" />
        <property name="url" value="${db.url}" />
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />
        <property name="initialSize" value="3" />
        <property name="minIdle" value="3" />
        <property name="maxActive" value="20" />
        <property name="maxWait" value="60000" />
        <property name="filters" value="stat,wall" />
    </bean>

    <bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <property name="globalConfig" ref="globalConfig"/> <!--  非必须  -->
        <property name="dataSource" ref="dataSource" />
        <property name="typeAliasesPackage" value="xyz.haijin.wallpaperserver.entity" />
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
    </bean>

    <bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
        <property name="dbConfig" ref="dbConfig"/> <!--  非必须  -->
    </bean>

    <bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
        <property name="selectStrategy" value="NOT_EMPTY"></property>
    </bean>


    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="xyz.haijin.wallpaperserver.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean" />
    </bean>

    <!-- tx -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <!--    &lt;!&ndash; druid &ndash;&gt;-->
    <bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
        <property name="slowSqlMillis" value="3000" />
        <property name="logSlowSql" value="true" />
        <property name="mergeSql" value="true" />
    </bean>
    <bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
        <property name="dbType" value="mysql" />
    </bean>

</beans>

3、配置文件logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 打印mp sql语句 -->
    <logger name="xyz.haijin.wallpaperserver.mapper" level="DEBUG" />
    <!-- TRACE < DEBUG < INFO < WARN < ERROR -->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>

</configuration>

4、配置文件mybatis-config.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>

    <settings>
        <setting name="safeRowBoundsEnabled" value="true"/>
        <setting name="cacheEnabled" value="false" />
        <setting name="useGeneratedKeys" value="true" />
        <!-- 打印查询语句 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING -->
        <setting name="logImpl" value="SLF4J" />
    </settings>


    <plugins>
<!-- 3.4.0以下 -->
        <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
            <property name="dialect" value="mysql" />
            <property name="pageSqlId" value="ByPage" />
        </plugin>
<!-- 3.4.0以上 -->
        <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
            <property name="@page" value="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor"/>
            <property name="page:dbType" value="mysql"/>
        </plugin>
        <plugin interceptor="xyz.haijin.wallpaperserver.interceptor.SqlStatementInterceptor">
            <property name="someProperty" value="100"/>
        </plugin>
    </plugins>

</configuration>

5、配置文件settings.properties:

db.driverClassName=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/wallpaper?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Hongkong&autoReconnect=true&failOverReadOnly=false
db.username=root
db.password=123456

6、配置文件springmvc.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/mvc
 http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:annotation-config />

    <!-- 启动注解驱动的spring mvc 功能 -->
    <mvc:annotation-driven/>
    <!--    校验配置-->
        <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
            <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
            <property name="validationMessageSource" ref="messageSource" />
        </bean>

        <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
            <property name="basenames">
                <list>
<!--                    <value>classpath:messages</value>-->
<!--                    <value>classpath:xyz/haijin/wallpaperserver/ValidationMessages</value>-->
                </list>
            </property>
            <property name="useCodeAsDefaultMessage" value="false" />
            <property name="defaultEncoding" value="UTF-8" />
            <property name="cacheSeconds" value="60" />
        </bean>

    <mvc:resources mapping="/**" location="xyz/haijin/wallpaperserver" />

    <!-- 启动包扫描功能 -->
    <context:component-scan base-package="xyz.haijin.wallpaperserver" />

    <!-- thymeleaf 模板解析器 -->
        <bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
            <property name="prefix" value="/WEB-INF/user/" />
            <property name="suffix" value=".html" />
            <property name="templateMode" value="HTML" />
            <property name="cacheable" value="false" />
            <property name="characterEncoding" value="UTF-8"/>
        </bean>

        <bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
            <property name="templateResolver" ref="templateResolver" />
        </bean>

        <!--    视图解析器-->
        <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
            <property name="templateEngine" ref="templateEngine" />
            <property name="characterEncoding" value="UTF-8"/>
        </bean>

    <!--配置拦截器, 多个拦截器,顺序执行 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
            <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
            <mvc:mapping path="/**" />
            <bean class="xyz.haijin.wallpaperserver.interceptor.StartAndEndHandlerInterceptor"></bean>
        </mvc:interceptor>

    </mvc:interceptors>


</beans>

7、打印接口前后执行的时间拦截器

StartAndEndHandlerInterceptor:
package xyz.haijin.wallpaperserver.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Author liuhaijin
 * @Date 2022/4/1
 */
@Slf4j
public class StartAndEndHandlerInterceptor extends HandlerInterceptorAdapter {
    /**
     * springMVC拦截器
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        log.info("start time is "+ sdf.format(new Date()) + " ; request url is " + request.getRequestURI() + "  : " + request.getMethod());
        return true;
    }

    /**
     * This implementation is empty.
     */
    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        log.info("end time is "+ sdf.format(new Date()) + " ; request url is " + request.getRequestURI() + "  : " + request.getMethod());
    }
}

8、打印sql的执行时间拦截器

SqlStatementInterceptor:
package xyz.haijin.wallpaperserver.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.util.CollectionUtils;

import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.regex.Matcher;

/**
 * 数据库操作性能拦截器,记录耗时
 * @Author liuhaijin
 * @Date 2022/4/1
 */
@Intercepts(value = {
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
                RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
                RowBounds.class, ResultHandler.class})})
@Slf4j
public class SqlStatementInterceptor implements Interceptor {

    private Properties properties;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object returnValue;
        long start = System.currentTimeMillis();
        returnValue = invocation.proceed();
        long end = System.currentTimeMillis();
        long time = end - start;
        try {
            final Object[] args = invocation.getArgs();
            //获取原始的ms
            MappedStatement ms = (MappedStatement) args[0];
            Object parameter = null;
            //获取参数,if语句成立,表示sql语句有参数,参数格式是map形式
            if (invocation.getArgs().length > 1) {
                parameter = invocation.getArgs()[1];
            }
            // 获取到节点的id,即sql语句的id
            String sqlId = ms.getId();
            // BoundSql就是封装myBatis最终产生的sql类
            BoundSql boundSql = ms.getBoundSql(parameter);
            // 获取节点的配置
            Configuration configuration = ms.getConfiguration();
            // 获取到最终的sql语句
            String sql = getSql(configuration, boundSql, sqlId, time);
            log.debug(sql);
        } catch (Exception e) {
            log.error("拦截sql处理出差" + e.getMessage());
            e.printStackTrace();
        }
        return returnValue;
    }

    // 封装了一下sql语句,使得结果返回完整xml路径下的sql语句节点id + sql语句
    public static String getSql(Configuration configuration, BoundSql boundSql, String sqlId, long time) {
        String sql = showSql(configuration, boundSql);
        StringBuilder str = new StringBuilder(100);
        str.append("\n\n============================begin================================\n\n");
        str.append(sqlId);
        str.append(":耗时【");
        str.append(time);
        str.append("】毫秒\n\n");
        str.append(sql);
        str.append("\n\n============================end================================\n\n");
        return str.toString();
    }

    /*<br>    *如果参数是String,则添加单引号, 如果是日期,则转换为时间格式器并加单引号; 对参数是null和不是null的情况作了处理<br>  */
    private static String getParameterValue(Object obj) {
        String value = null;
        if (obj instanceof String) {
            value = "'" + obj.toString() + "'";
        } else if (obj instanceof Date) {
            Date date = (Date) obj;
            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
            value = "'" + formatter.format(date) + "'";
        } else {
            if (obj != null) {
                value = obj.toString();
            } else {
                value = "";
            }

        }
        return value;
    }

    // 进行?的替换
    public static String showSql(Configuration configuration, BoundSql boundSql) {
        Object parameterObject = boundSql.getParameterObject();  // 获取参数
        List<ParameterMapping> parameterMappings = boundSql
                .getParameterMappings();
        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");  // sql语句中多个空格都用一个空格代替
        if (!CollectionUtils.isEmpty(parameterMappings) && parameterObject != null) {
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); // 获取类型处理器注册器,类型处理器的功能是进行java类型和数据库类型的转换<br>       // 如果根据parameterObject.getClass()可以找到对应的类型,则替换
            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(parameterObject)));

            } else {
                MetaObject metaObject = configuration.newMetaObject(parameterObject);// MetaObject主要是封装了originalObject对象,提供了get和set的方法用于获取和设置originalObject的属性值,主要支持对JavaBean、Collection、Map三种类型对象的操作
                for (ParameterMapping parameterMapping : parameterMappings) {
                    String propertyName = parameterMapping.getProperty();
                    if (metaObject.hasGetter(propertyName)) {
                        Object obj = metaObject.getValue(propertyName);
                        sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));
                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
                        Object obj = boundSql.getAdditionalParameter(propertyName);  // 该分支是动态sql
                        sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));
                    } else {
                        sql = sql.replaceFirst("\\?", "缺失");
                    }//打印出缺失,提醒该参数缺失并防止错位
                }
            }
        }
        return sql;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}

end

你好:我的2025