springmvc+logback项目的日志搭建

一、重写HTMLLayout

两个自定义类:LzhHTMLLayoutBaseLzhHTMLLayout

LzhHTMLLayoutBase代码如下:

package top.liaozhenghan.logback.study.layout;

import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.liaozhenghan.util.dateutil.DateStyle;
import com.liaozhenghan.util.dateutil.DateUtil;

import ch.qos.logback.core.Context;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.LayoutBase;
import ch.qos.logback.core.html.CssBuilder;
import ch.qos.logback.core.pattern.Converter;
import ch.qos.logback.core.pattern.ConverterUtil;
import ch.qos.logback.core.pattern.parser.Node;
import ch.qos.logback.core.pattern.parser.Parser;
import ch.qos.logback.core.spi.ScanException;

public abstract class LzhHTMLLayoutBase<E> extends LayoutBase<E>{

    protected String pattern;

    protected Converter<E> head;

    protected String title = "Logback Log Messages";

    // It is the responsibility of derived classes to set
    // this variable in their constructor to a default value.
    protected CssBuilder cssBuilder;

    // counter keeping track of the rows output
    protected long counter = 0;

    /**
     * Set the <b>ConversionPattern </b> option. This is the string which controls
     * formatting and consists of a mix of literal content and conversion
     * specifiers.
     */
    public void setPattern(String conversionPattern) {
        pattern = conversionPattern;
    }

    /**
     * Returns the value of the <b>ConversionPattern </b> option.
     */
    public String getPattern() {
        return pattern;
    }

    public CssBuilder getCssBuilder() {
        return cssBuilder;
    }

    public void setCssBuilder(CssBuilder cssBuilder) {
        this.cssBuilder = cssBuilder;
    }

    /**
     * Parses the pattern and creates the Converter linked list.
     */
    @Override
    public void start() {
        int errorCount = 0;

        try {
            Parser<E> p = new Parser<E>(pattern);
            p.setContext(getContext());
            Node t = p.parse();
            this.head = p.compile(t, getEffectiveConverterMap());
            ConverterUtil.startConverters(this.head);
        } catch (ScanException ex) {
            addError("Incorrect pattern found", ex);
            errorCount++;
        }

        if (errorCount == 0) {
            super.started = true;
        }
    }

    protected abstract Map<String, String> getDefaultConverterMap();

    /**
     * Returns a map where the default converter map is merged with the map
     * contained in the context.
     */
    public Map<String, String> getEffectiveConverterMap() {
        Map<String, String> effectiveMap = new HashMap<String, String>();

        // add the least specific map fist
        Map<String, String> defaultMap = getDefaultConverterMap();
        if (defaultMap != null) {
            effectiveMap.putAll(defaultMap);
        }

        // contextMap is more specific than the default map
        Context context = getContext();
        if (context != null) {
            @SuppressWarnings("unchecked")
            Map<String, String> contextMap = (Map<String, String>) context.getObject(CoreConstants.PATTERN_RULE_REGISTRY);
            if (contextMap != null) {
                effectiveMap.putAll(contextMap);
            }
        }
        return effectiveMap;
    }

    /**
     * The <b>Title </b> option takes a String value. This option sets the
     * document title of the generated HTML document.
     *
     * <p>
     * Defaults to ‘Logback Log Messages‘.
     */
    public void setTitle(String title) {
        this.title = title;
    }

    /**
     * Returns the current value of the <b>Title </b> option.
     */
    public String getTitle() {
        return title;
    }

    /**
     * Returns the content type output by this layout, i.e "text/html".
     */
    @Override
    public String getContentType() {
        return "text/html";
    }

    /**
     * Returns appropriate HTML headers.
     */
    @Override
    public String getFileHeader() {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"");
        sbuf.append(" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
        sbuf.append(LINE_SEPARATOR);
        sbuf.append("<html>");
        sbuf.append(LINE_SEPARATOR);
        sbuf.append("  <head>");
        sbuf.append(LINE_SEPARATOR);
        sbuf.append("    <title>");
        sbuf.append(title);
        sbuf.append("</title>");
        sbuf.append(LINE_SEPARATOR);

        cssBuilder.addCss(sbuf);

        sbuf.append(LINE_SEPARATOR);
        sbuf.append("  </head>");
        sbuf.append(LINE_SEPARATOR);
        sbuf.append("<body>");
        sbuf.append(LINE_SEPARATOR);

        return sbuf.toString();
    }

    public String getPresentationHeader() {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append("<hr/>");
        sbuf.append(LINE_SEPARATOR);
        sbuf.append("<p><span style=‘color:red;‘>日志启动时间:</span> ");
        sbuf.append(DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD_HH_MM_SS_CN));
        sbuf.append("</p><p></p>");
        sbuf.append(LINE_SEPARATOR);
        sbuf.append(LINE_SEPARATOR);
        sbuf.append("<table cellspacing=\"0\">");
        sbuf.append(LINE_SEPARATOR);

        buildHeaderRowForTable(sbuf);

        return sbuf.toString();
    }

    private void buildHeaderRowForTable(StringBuilder sbuf) {
        Converter c = head;
        String name;
        sbuf.append("<tr class=\"header\">");
        sbuf.append(LINE_SEPARATOR);
        while (c != null) {
            name = computeConverterName(c);
            if (name == null) {
                c = c.getNext();
                continue;
            }
            sbuf.append("<td class=\"");
            sbuf.append(name);
            sbuf.append("\">");
            sbuf.append(filterTableTitleName(name));
            sbuf.append("</td>");
            sbuf.append(LINE_SEPARATOR);
            c = c.getNext();
        }
        sbuf.append("</tr>");
        sbuf.append(LINE_SEPARATOR);
    }

    private String filterTableTitleName(String name) {

        String str = name.toLowerCase();
        if ("level".equals(str)) {
            name = "级别";
        } else if ("date".equals(str)) {
            name = "执行时间";
        } else if ("callerdata".equals(str)) {
            name = "所在行";
        } else if ("message".equals(str)) {
            name = "信息";
        }

        return name;
    }

    public String getPresentationFooter() {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append("</table>");
        return sbuf.toString();
    }

    /**
     * Returns the appropriate HTML footers.
     */
    @Override
    public String getFileFooter() {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append(LINE_SEPARATOR);
        sbuf.append("</body></html>");
        return sbuf.toString();
    }

    protected void startNewTableIfLimitReached(StringBuilder sbuf) {
        if (this.counter >= CoreConstants.TABLE_ROW_LIMIT) {
            counter = 0;
            sbuf.append("</table>");
            sbuf.append(LINE_SEPARATOR);
            sbuf.append("<p></p>");
            sbuf.append("<table cellspacing=\"0\">");
            sbuf.append(LINE_SEPARATOR);
            buildHeaderRowForTable(sbuf);
        }
    }

    protected String computeConverterName(Converter c) {

        String name = null;

        String className = c.getClass().getSimpleName();
        int index = className.indexOf("Converter");
        if (index == -1) {
            name = className;
        } else {
            name = className.substring(0, index);
        }

        return name;
    }

}

LzhHTMLLayout代码如下:

package top.liaozhenghan.logback.study.layout;

import static ch.qos.logback.core.CoreConstants.LINE_SEPARATOR;

import java.util.Map;

import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.html.DefaultCssBuilder;
import ch.qos.logback.classic.html.DefaultThrowableRenderer;
import ch.qos.logback.classic.pattern.MDCConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.helpers.Transform;
import ch.qos.logback.core.html.IThrowableRenderer;
import ch.qos.logback.core.pattern.Converter;

public class LzhHTMLLayout extends LzhHTMLLayoutBase<ILoggingEvent>{

    /**
     * Default pattern string for log output.
     */
    static final String DEFAULT_CONVERSION_PATTERN = "%date{HH:mm:ss}%level%caller{1}%msg";

    IThrowableRenderer<ILoggingEvent> throwableRenderer;

    /**
     * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN.
     *
     * The default pattern just produces the application supplied message.
     */
    public LzhHTMLLayout() {
        pattern = DEFAULT_CONVERSION_PATTERN;
        throwableRenderer = new DefaultThrowableRenderer();
        cssBuilder = new DefaultCssBuilder();
    }

    @Override
    public void start() {
        int errorCount = 0;
        if (throwableRenderer == null) {
            addError("ThrowableRender cannot be null.");
            errorCount++;
        }
        if (errorCount == 0) {
            super.start();
        }
    }

    protected Map<String, String> getDefaultConverterMap() {
        return PatternLayout.defaultConverterMap;
    }

    public String doLayout(ILoggingEvent event) {
        StringBuilder buf = new StringBuilder();
        startNewTableIfLimitReached(buf);

        boolean odd = true;
        if (((counter++) & 1) == 0) {
            odd = false;
        }

        String level = event.getLevel().toString().toLowerCase();

        buf.append(LINE_SEPARATOR);
        buf.append("<tr class=\"");
        buf.append(level);
        if (odd) {
            buf.append(" odd\">");
        } else {
            buf.append(" even\">");
        }
        buf.append(LINE_SEPARATOR);

        Converter<ILoggingEvent> c = head;
        while (c != null) {
            appendEventToBuffer(buf, c, event);
            c = c.getNext();
        }
        buf.append("</tr>");
        buf.append(LINE_SEPARATOR);

        if (event.getThrowableProxy() != null) {
            throwableRenderer.render(buf, event);
        }
        return buf.toString();
    }

    private void appendEventToBuffer(StringBuilder buf, Converter<ILoggingEvent> c, ILoggingEvent event) {
        buf.append("<td class=\"");
        buf.append(computeConverterName(c));
        buf.append("\">");
        buf.append(Transform.escapeTags(c.convert(event)));
        buf.append("</td>");
        buf.append(LINE_SEPARATOR);
    }

    public IThrowableRenderer getThrowableRenderer() {
        return throwableRenderer;
    }

    public void setThrowableRenderer(IThrowableRenderer<ILoggingEvent> throwableRenderer) {
        this.throwableRenderer = throwableRenderer;
    }

    @Override
    protected String computeConverterName(Converter c) {
        if (c instanceof MDCConverter) {
            MDCConverter mc = (MDCConverter) c;
            String key = mc.getFirstOption();
            if (key != null) {
                return key;
            } else {
                return "MDC";
            }
        } else {
            return super.computeConverterName(c);
        }
    }
}

二、logback.xml配置


<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="3 seconds">
    <!-- 定义变量 -->
    <if condition=‘p("os.name").contains("Windows")‘>
        <then>
            <property name="LOG_PATH" value="c:/logs" />
        </then>
    </if>
    <if condition=‘p("os.name").contains("Linux")‘>
        <then>
            <property name="LOG_PATH" value="logs" />
        </then>
    </if>
    <property name="APP_NAME" value="study" />
    <property name="LOG_ROOT_LEVEL" value="debug" />
    <property name="maxHistory" value="30" />

    <contextName>${APP_NAME}</contextName>

    <appender name="STDOUT"
        class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                <!-- 设置日志输出格式 -->
                [%-5level] %d{yyyy-MM-dd HH:mm:ss} [%thread] %logger{36} - %m%n
            </pattern>
        </encoder>
    </appender>

    <!-- 按照每天生成日志文件 -->
    <appender name="FILE_ERROR"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APP_NAME}/ERROR.log</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="top.liaozhenghan.logback.study.layout.LzhHTMLLayout"/>
        </encoder>
        <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}/ERROR.%d.log
            </FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE_WARN"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APP_NAME}/WARN.log</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="top.liaozhenghan.logback.study.layout.LzhHTMLLayout"/>
        </encoder>
        <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}/WARN.%d.log
            </FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE_INFO"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APP_NAME}/INFO.log</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="top.liaozhenghan.logback.study.layout.LzhHTMLLayout"/>
        </encoder>
        <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}/INFO.%d.log
            </FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE_DEBUG"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APP_NAME}/DEBUG.log</file>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="top.liaozhenghan.logback.study.layout.LzhHTMLLayout"/>
        </encoder>
        <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_PATH}/${APP_NAME}/DEBUG.%d.log
            </FileNamePattern>
            <MaxHistory>${maxHistory}</MaxHistory>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <root level="${LOG_ROOT_LEVEL}">
        <!-- 控制台输出 -->
        <appender-ref ref="STDOUT" />
        <!-- 文件输出 -->
        <appender-ref ref="FILE_ERROR" />
        <appender-ref ref="FILE_WARN" />
        <appender-ref ref="FILE_INFO" />
        <appender-ref ref="FILE_DEBUG" />
    </root>
</configuration>

logback.xml


三、查看日志的jsp页面

用了三个页面:登录页面loglogin.jsp,日志级别选择页面logselect.jsp,日志显示页面log.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>日志系统登录</title>
    <meta charset="UTF-8">
    <!-- meta信息,可维护 -->
    <meta name="format-detection" content="telephone=no">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="apple-touch-fullscreen" content="yes">

</head>
<body style="width: 100%;">

    <form action="" method="post">
        <p>密码:</p><input name="password"><br>
        <input type="submit" value="登录日志系统">
    </form>
</body>
</html>

loglogin.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>日志记录</title>
    <meta charset="UTF-8">
    <!-- meta信息,可维护 -->
    <meta name="format-detection" content="telephone=no">
    <meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="apple-touch-fullscreen" content="yes">
    <script src="js/jquery.min.js" type="text/javascript"></script>

    <style type="text/css">
        .lzh_div td{
        }
    </style>

</head>
<body style="width: 100%;">

    <form action="" method="post">
        <input id="date" type="date" name="date">
        <select id="levels" name="level">
            <!-- <option value="TRACE">TRACE</option> -->
            <option value="DEBUG">DEBUG</option>
            <option value="INFO">INFO</option>
            <option value="WARN">WARN</option>
            <option value="ERROR">ERROR</option>
        </select>
        <input type="submit" value="查看日志">
    </form>
    <script type="text/javascript">
        var level = "${level}";
        var date = "${date}";
        $("#levels").val(level);
        $("#date").val(date);
    </script>
    <div class="lzh_div" style="width: 100%;">${html}</div>
</body>
</html>

logselect.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
${html}

log.jsp

四、LogController.java

package top.liaozhenghan.logback.study.controller;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.liaozhenghan.util.dateutil.DateStyle;
import com.liaozhenghan.util.dateutil.DateUtil;
import com.liaozhenghan.util.httputil.SrcUtil;

@Controller
public class LogController {

    final static Logger LOG = LoggerFactory.getLogger(LogController.class);
    final static String LOG_LOGIN = "LOG_LOGIN";

    @RequestMapping(value="/log")
    public String log(HttpServletRequest request, Model model) {

        String date = request.getParameter("date");
        String level = request.getParameter("level");
        String password = request.getParameter("password");
        String html = null;

        // 判断是否登录
        Object login = request.getSession().getAttribute(LOG_LOGIN);
        if (login == null) {
            String PASSWORD = "baofa2018";

            if (PASSWORD.equals(password)) {
                request.getSession().setAttribute(LOG_LOGIN, LOG_LOGIN);
            } else {
                return "logs/loglogin";
            }
        }

        // 1.判断参数是否为空
        if (StringUtils.isEmpty(level) && StringUtils.isEmpty(date)) {
            date = DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD);
            level = "ERROR";
            model.addAttribute("date", date);
            model.addAttribute("level", level);
            return "logs/logselect";
        }

        // 2.判断路径
        String filepath = "c:/logs/study/";
        String osName = System.getProperty("os.name");
        if (StringUtils.isEmpty(osName)) {
            html = "系统错误";
            model.addAttribute("date", date);
            model.addAttribute("level", level);
            model.addAttribute("html", html);
            return "logs/logselect";
        } else if (osName.contains("Window")) {
            filepath = "c:/logs/study/";
        } else if (osName.contains("Linux")) {
            filepath = "logs/study/";
        } else {
            html = "未识别的操作系统:" + osName;
            model.addAttribute("date", date);
            model.addAttribute("level", level);
            model.addAttribute("html", html);
            return "logs/logselect";
        }

        if (StringUtils.isNotEmpty(date) && !DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD).equals(date)) {
            filepath += level + "." + date + ".log";
        } else {
            filepath += level + ".log";
            date = DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD);
        }

        File file = new File(filepath);
        html = "无日志记录";
        if (file.exists()) {
            try {
                html = FileUtils.readFileToString(file, "UTF-8");
            } catch (IOException e) {
                LOG.error(DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD_HH_MM_SS)
                        + "【文件名】" + filepath, e);
            }
        }

        LOG.debug("测试");
        LOG.info("测试");
        LOG.warn("测试");
        LOG.error("测试");

        model.addAttribute("html", html);
        model.addAttribute("date", date);
        model.addAttribute("level", level);
        return "logs/log";
    }
}

注:logback.xml在tomcat环境下的日志目录可改为:

<property name="LOG_PATH" value="${catalina.base}/logs" />

在java代码中获取文件目录改为:

String catalina_base = System.getProperty("catalina.base");
String filepath = catalina_base + "/logs/study/";

原文地址:https://www.cnblogs.com/liaozhenghan/p/9642207.html

时间: 2024-10-11 21:56:37

springmvc+logback项目的日志搭建的相关文章

springmvc+logback项目日志配置

最近在做项目的时候用到logback作为项目日志,而抛弃了log4j.具体为什么用logback,我总结了以下几点: 1.log4j和logback的创作者是同一个人,logback是log4j的升级版,是对log4j核心的一个封装. 2.性能提升,在某些特定场景上执行速度提升10倍以上,同时初始化内存更小 3.扩展文档,丰富的并且详细的文档和不断的更新,可在官网上查看 4.Filters(过滤器),过滤器的使用又是logback的一大特色,在使用log4j的时候,当我们遇到问题时,我们需要降低

IDEA中maven搭建Spring+SpringMVC+mybatis项目

一.介绍 使用IDEA搭建maven web项目,整合框架Spring+SpringMVC+mybatis 项目结构图: 二.搭建 1.新建maven项目 2.创建项目结构(如上图) 3.配置pom.xml 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation=

rapid-framework脚手架快速搭建springMVC框架项目

rapid-framework介绍:   一个类似ruby on rails的java web快速开发脚手架,本着不重复发明轮子的原则,框架只是将零散的struts(struts2)+spring+hibernate各个组件组装好在一起,并对struts及struts2进行改造,提供零配置编程,并内置一个强大的代码生成器及模板文件,可以生成java的hibernat model,dao,manager,struts+struts2 action类,可以生成jsp的增删改查及列表页面.  整个项目

从头开始基于Maven搭建SpringMVC+Mybatis项目(2)

接上文内容,本节介绍Maven的聚合和继承. 从头阅读传送门 互联网时代,软件正在变得越来越复杂,开发人员通常会对软件划分模块,以获得清晰的设计.良好的分工及更高的可重用性.Maven的聚合特性能把多个模块聚合在一起构建,并促进各子模块通过继承父模块的pom配置来保持配置的一致.为了演示这些特性,本文的示例划分为数据持久层petstore-persist和petstore-web两个模块. 下面来介绍创建项目的过程,首先创建父模块perstore-parent. File -> New ->

基于Maven搭建SpringMVC+Mybatis项目(4)

从高考,到程序员      CSDN日报20170620--<找一个好工作,谈一份好薪水>      6 月书讯 | 最受欢迎的 SQL 入门书重磅升级 从头开始基于Maven搭建SpringMVC+Mybatis项目(4) 标签:               mavenmybatisspring mvc分页JAVA 2016-07-27 16:53             4598人阅读             评论(0)             收藏              举报 本文章

基于Maven搭建SpringMVC+Mybatis项目(2)

从头开始基于Maven搭建SpringMVC+Mybatis项目(2) 标签:               JAVAmavenmybatisspring mvc 版权声明:欢迎转载, 转载请保留原文链接. 接上文内容,本节介绍Maven的聚合和继承. 从头阅读传送门 互联网时代,软件正在变得越来越复杂,开发人员通常会对软件划分模块,以获得清晰的设计.良好的分工及更高的可重用性.Maven的聚合特性能把多个模块聚合在一起构建,并促进各子模块通过继承父模块的pom配置来保持配置的一致.为了演示这些特

基于Maven搭建SpringMVC+Mybatis项目(3)

| 从高考,到程序员      CSDN日报20170620--<找一个好工作,谈一份好薪水>      6 月书讯 | 最受欢迎的 SQL 入门书重磅升级 从头开始基于Maven搭建SpringMVC+Mybatis项目(3) 标签:               JAVAmavenspring mvcmybatis 2016-07-26 10:06             42087人阅读             评论(2)             收藏              举报 本文

解决:springmvc maven 项目搭建完后没有src目录

前言:在搭建springmvc maven项目中遇到的问题做总结,比如搭建后没有src,同时这里也解决了搭建后maven导入很慢的问题. 问题: 1.发现创建出来的maven项目没有src文件 ,而且maven导入很慢 解决办法: 在新建项目的这个时候(如下图),点击加号,在name的输入框中填写archetypeCatalog,在value的输入框中填写internal,点击确定: 然后在所选择maven配置文件setting.xml里面加入以下代码,保存后回到 IDEA. <mirror>

通过IntelliJ IDEA创建maven+springmvc+mybatis项目

第一个springmvc+mybatis项目,通过学习极客学院视频(视频案例通过eclipse搭建,网址为http://www.jikexueyuan.com/course/1430.html),发现在IntelliJ IDEA编译器下不能正常运行,通过摸索后正常.记录下几个关键改动: 1.pom.xml文件需要加载对javax.servlet.http.HttpServletRequest的支持, 1 <dependency> 2 <groupId>javax.servlet&l