1. 程式人生 > >Spring MVC:從零開始

Spring MVC:從零開始

前言:之前做的專案包括網上一些教程都是集很多配置和功能一起,有時候使用起來就比較亂。週末抽空從零搭建專案,一步步加新功能,也是讓自己對spring配置有個更全面的瞭解。主要是對流程和配置的介紹,具體業務功能就比較省略。

一、搭建Spring MVC專案

這裡是初步搭建完成的專案架構:

這裡寫圖片描述

說到maven,這裡推薦阿里雲的映象地址,如果不在公司或者公司沒有私服的情況下,可以使用,下載賊快。

<mirror>
  <id>alimaven</id>
  <name>aliyun maven</name>
  <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
  <mirrorOf>central</mirrorOf>        
</mirror>

1、Maven配置:
引入spring有關的包,這裡我們暫時只用到spring-core和spring-webmvc和json包

 <spring.version>4.3.3.RELEASE</spring.version>

<!--spring配置 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
     <!--json配置 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${json.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${json.version}</version>
    </dependency>

2、Spring配置

spring肯定掃不了配置檔案,spring-core.xml,放在resources目錄下

    <?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-3.0.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">


<!-- 啟用spring mvc 註解 -->
<mvc:annotation-driven />
<!-- 開啟註解掃描-->
<context:component-scan base-package="com.tan.self" />

<!-- json配置-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
        </list>
    </property>
</bean>

<!-- viewResolver配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
     <property name="suffix" value=".jsp"/>
</bean>
</beans>
  • < mvc:annotation-driven/> 會自動註冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個bean,是spring MVC為@Controllers分發請求所必須的
  • < context:component-scan base-package=”com.tan.self” />用於開啟註解掃描
  • RequestMappingHandlerAdapter配置,配置json轉換,用於spring中的@Responsebody註解,可以將返回值轉換為json,注意,這裡是spring4.x版本所用的配置,如果是低版本的話,用的是AnnotationMethodHandlerAdapter
  • viewResolver配置,配置requestMapping返回頁面的字首和字尾

引用spring官方的說明:

< context:annotation-config> declares support for general annotations such as @Required, @Autowired, @PostConstruct, and so on.
< mvc:annotation-driven /> is actually rather pointless. It declares explicit support for annotation-driven MVC controllers ([email protected], @Controller, etc), even though support for those is the default behaviour.

使用< context:component-scan/>後,該配置項其實也包含了自動注入上述processor的功能,即可將< context:annotation-config/>省去。

3、web.xml配置

  • CharacterEncodingFilter字元過濾器,用於設定專案編碼
  • ContextLoaderListener用於啟動Web容器時,自動裝配ApplicationContext的配置資訊
  • DispatcherServlet用於路由分發
  • classpath:指定為我們配置的spring-core.xml,若不予配置的話,預設是/WEB-INF/applicationContext.xml

    <!-- 字元編碼過濾器-->
        <filter>
            <filter-name>characterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    <!-- contextLoaderListener配置  啟動Web容器時,自動裝配ApplicationContext的配置資訊-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-core.xml</param-value>
    </context-param>
    
    <!-- dispatcherServlet配置-->
    <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-core.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

4、示例程式碼

ApiController:

@Controller
@ResponseBody
@RequestMapping("api")
public class ApiController {

@RequestMapping("getJson")
public RestResponse getApiJson() {

    RestResponse restResponse = new RestResponse();
    restResponse.setCode(200);
    restResponse.setMsg("操作成功");
    logger.info("獲取json資料介面");
    return restResponse;
}

}

WebController:

@Controller
@RequestMapping("web")
public class WebController {

@RequestMapping("index")
public String webTest() {
    return "index";
}

RestResponse:

public class RestResponse {

private int code;
private String msg;
private Object data;

public int getCode() {
    return code;
}

public void setCode(int code) {
    this.code = code;
}

public String getMsg() {
    return msg;
}

public void setMsg(String msg) {
    this.msg = msg;
}

public Object getData() {
    return data;
}

public void setData(Object data) {
    this.data = data;
}

}
index.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<html>
歡迎光臨
</html>

二、專案配置Jetty啟動

專案配置和基礎程式碼都已完畢,現在需要的是將web專案部署跑起來。一般而言,會使用tomcat作為伺服器,進行部署,這裡我們推薦Jetty,Jetty是一款輕量級的伺服器,可以以外掛的形式進行安裝,非常便捷。

1、引入jetty外掛

修改pom,增加外掛引入:

<build>
    <plugins>
        <!--jetty -->
        <plugin>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>7.6.14.v20131031</version>
            <configuration>
                <connectors>
                    <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
                        <port>80</port>
                    </connector>
                </connectors>
                <stopKey>shutdown</stopKey>
                <stopPort>9090</stopPort>
            </configuration>
        </plugin>
        <!--編譯版本 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
            </configuration>
        </plugin>
    </plugins>
</build>

這裡配置了兩個plugin,一個是jetty-maven-plugin,可指定port為啟動埠,一個是maven-compiler-plugin,指定編譯版本,避免不同電腦不同環境下編譯版本的差異(筆者的idea之前用於開發的時候,某專案編譯打包版本一直是source1.5,必須每次在專案配置裡面進行更改,非常繁瑣,這裡配置了source,就可以完美解決這種問題)

2、jetty啟動

用jetty啟動web專案也很方便,以idea為例,在Run–>Edit Configurations中新增Maven啟動方式,配置如下:

這裡寫圖片描述

執行之:控制檯列印如下,啟動成功。

這裡寫圖片描述

{
code: 200,
msg: "操作成功",
data: null
}
歡迎光臨

三、整合Log4j2日誌

專案搭建完畢後,筆者就集成了log4j的日誌,但用的是slf4j和log4j1.x的版本,然後在log4j官網上看到:

On August 5, 2015 the Logging Services Project Management Committee announced that Log4j 1.x had reached end of life. For complete text of the announcement please see the Apache Blog. Users of Log4j 1 are recommended to upgrade to Apache Log4j 2.

原來log4j1.x版本自從15年起就已經不再維護了,官方也一直主推2.x版本,而且和以前方式也不大一樣,於是改為Log4j2。

1、引入依賴

這裡我們還是通過slf4j來使用log4j2,slf4j是一個介面工具類,通過它可以方便的切換log4j、logback等不同日誌實現,推薦這種方式。

    <slf4j.version>1.7.7</slf4j.version>
    <log4j.version>2.5</log4j.version>
  <!--slf4j log4j2配置 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency> <!-- 橋接:告訴Slf4j使用Log4j2 -->
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j.version}</version>
    </dependency>

2、log4j2配置

在resources目錄下新建log4j2.xml檔案,這是官方預設的路徑和檔名。

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="error" monitorInterval="600">
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </Console>

    <RollingFile name="RollingFile" fileName="/data/logs/web.log"
                 filePattern="/data/logs/$${date:yyyy-MM}/web-%d{MM-dd-yyyy}-%i.log.gz">
        <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
        <Policies>
            <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
        </Policies>
    </RollingFile>
</appenders>

<loggers>
    <root level="info">
        <appender-ref ref="RollingFile"/>
        <appender-ref ref="Console"/>
    </root>
</loggers>
</configuration>

具體的配置和Log4j1.x有點不太一樣,但大同小異,這裡我們主要介紹monitorInterval=”600”這個屬性,之前我們的日誌配置檔案如果修改日誌級別或者其他,需要重新啟動專案,尤其對於已經上線的專案,非常不友好,而log4j配置裡面新增的這一屬性就是可以在不啟動專案的情況下修改配置,monitorInterval是指log4j多久去重新讀取一下配置,單位為秒,這裡就是十分鐘檢測一次。