1. 程式人生 > 其它 >2.spring-手寫1.0

2.spring-手寫1.0

資料:https://gitee.com/chuanqi1995/java

配置

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">
    <parent>
        <artifactId>java-spring</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>java-spring-1.0</artifactId>
    <packaging>war</packaging>

    <properties>
        <!-- dependency versions -->
        <servlet.api.version>2.4</servlet.api.version>
    </properties>


    <dependencies>
        <!-- requied start -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>${servlet.api.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- requied end -->
    </dependencies>

    <build>
        <finalName>${artifactId}</finalName>
        <resources>
            <resource>
                <directory>${basedir}/src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
            <resource>
                <directory>${basedir}/src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                    <exclude>**/*.class</exclude>
                </excludes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>UTF-8</encoding>
                    <compilerArguments>
                        <verbose/>
                        <bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
                    </compilerArguments>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.5</version>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <!-- here the phase you need -->
                        <phase>validate</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <encoding>UTF-8</encoding>
                            <outputDirectory>${basedir}/target/classes</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>src/main/resources</directory>
                                    <includes>
                                        <include>**/*.*</include>
                                    </includes>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.26</version>
                <configuration>
                    <webDefaultXml>src/main/resources/webdefault.xml</webDefaultXml>
                    <contextPath>/</contextPath>
                    <connectors>
                        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                            <port>8080</port>
                        </connector>
                    </connectors>
                    <scanIntervalSeconds>0</scanIntervalSeconds>
                    <scanTargetPatterns>
                        <scanTargetPattern>
                            <directory>src/main/webapp</directory>
                            <includes>
                                <include>**/*.xml</include>
                                <include>**/*.properties</include>
                            </includes>
                        </scanTargetPattern>
                    </scanTargetPatterns>
                    <systemProperties>
                        <systemProperty>
                            <name>
                                javax.xml.parsers.DocumentBuilderFactory
                            </name>
                            <value>
                                com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
                            </value>
                        </systemProperty>
                        <systemProperty>
                            <name>
                                javax.xml.parsers.SAXParserFactory
                            </name>
                            <value>
                                com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
                            </value>
                        </systemProperty>
                        <systemProperty>
                            <name>
                                javax.xml.transform.TransformerFactory
                            </name>
                            <value>
                                com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
                            </value>
                        </systemProperty>
                        <systemProperty>
                            <name>org.eclipse.jetty.util.URI.charset</name>
                            <value>UTF-8</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                    <webResources>
                        <resource>
                            <!-- this is relative to the pom.xml directory -->
                            <directory>src/main/resources/</directory>
                            <targetPath>WEB-INF/classes</targetPath>
                            <includes>
                                <include>**/*.*</include>
                            </includes>
                            <!-- <excludes>
                                <exclude>**/local</exclude>
                                <exclude>**/test</exclude>
                                <exclude>**/product</exclude>
                            </excludes> -->
                            <filtering>true</filtering>
                        </resource>
                        <resource>
                            <!-- this is relative to the pom.xml directory -->
                            <directory>src/main/resources</directory>
                            <targetPath>WEB-INF/classes</targetPath>
                            <filtering>true</filtering>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.zeroturnaround</groupId>
                <artifactId>javarebel-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>generate-rebel-xml</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <version>1.0.5</version>
            </plugin>

        </plugins>
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.zeroturnaround
                                        </groupId>
                                        <artifactId>
                                            javarebel-maven-plugin
                                        </artifactId>
                                        <versionRange>
                                            [1.0.5,)
                                        </versionRange>
                                        <goals>
                                            <goal>generate</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

webdefault.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!-- ===================================================================== -->
<!-- This file contains the default descriptor for web applications.       -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- The intent of this descriptor is to include jetty specific or common  -->
<!-- configuration for all webapps.   If a context has a webdefault.xml    -->
<!-- descriptor, it is applied before the contexts own web.xml file        -->
<!--                                                                       -->
<!-- A context may be assigned a default descriptor by:                    -->
<!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
<!--  + Passed an arg to addWebApplications                                -->
<!--                                                                       -->
<!-- This file is used both as the resource within the jetty.jar (which is -->
<!-- used as the default if no explicit defaults descriptor is set) and it -->
<!-- is copied to the etc directory of the Jetty distro and explicitly     -->
<!-- by the jetty.xml file.                                                -->
<!--                                                                       -->
<!-- ===================================================================== -->
<web-app 
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
   metadata-complete="true"
   version="2.5"> 

  <description>
    Default web.xml file.  
    This file is applied to a Web application before it's own WEB_INF/web.xml file
  </description>


  <!-- ==================================================================== -->
  <!-- Context params to control Session Cookies                            -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- UNCOMMENT TO ACTIVATE
  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
    <param-value>127.0.0.1</param-value>
  </context-param>

  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
    <param-value>/</param-value>
  </context-param>

  <context-param>
    <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
    <param-value>-1</param-value>
  </context-param>
  -->

  <context-param>
    <param-name>org.mortbay.jetty.webapp.NoTLDJarPattern</param-name>
    <param-value>start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar</param-value>
  </context-param>
            


  <!-- ==================================================================== -->
  <!-- The default servlet.                                                 -->
  <!-- This servlet, normally mapped to /, provides the handling for static -->
  <!-- content, OPTIONS and TRACE methods for the context.                  -->
  <!-- The following initParameters are supported:                          -->
  <!--                                                                      -->
  <!--   acceptRanges     If true, range requests and responses are         -->
  <!--                    supported                                         -->
  <!--                                                                      -->
  <!--   dirAllowed       If true, directory listings are returned if no    -->
  <!--                    welcome file is found. Else 403 Forbidden.        -->
  <!--                                                                      -->
  <!--   welcomeServlets  If true, attempt to dispatch to welcome files     -->
  <!--                    that are servlets, if no matching static          --> 
  <!--                    resources can be found.                           -->
  <!--                                                                      -->
  <!--   redirectWelcome  If true, redirect welcome file requests           -->
  <!--                    else use request dispatcher forwards              -->
  <!--                                                                      -->
  <!--   gzip             If set to true, then static content will be served--> 
  <!--                    as gzip content encoded if a matching resource is -->
  <!--                    found ending with ".gz"                           -->
  <!--                                                                      -->
  <!--   resoureBase      Can be set to replace the context resource base   -->
  <!--                                                                      -->
  <!--   relativeResourceBase                                               -->
  <!--                    Set with a pathname relative to the base of the   -->
  <!--                    servlet context root. Useful for only serving     -->
  <!--                    static content from only specific subdirectories. -->
  <!--                                                                      -->
  <!--   useFileMappedBuffer                                                -->
  <!--                    If set to true (the default), a  memory mapped    -->
  <!--                    file buffer will be used to serve static content  -->
  <!--                    when using an NIO connector. Setting this value   -->
  <!--                    to false means that a direct buffer will be used  -->
  <!--                    instead. If you are having trouble with Windows   -->
  <!--                    file locking, set this to false.                  -->
  <!--                                                                      -->
  <!--  cacheControl      If set, all static content will have this value   -->
  <!--                    set as the cache-control header.                  -->
  <!--                                                                      -->
  <!--  maxCacheSize      Maximum size of the static resource cache         -->
  <!--                                                                      -->
  <!--  maxCachedFileSize Maximum size of any single file in the cache      -->
  <!--                                                                      -->
  <!--  maxCachedFiles    Maximum number of files in the cache              -->
  <!--                                                                      -->
  <!--  cacheType         "nio", "bio" or "both" to determine the type(s)   -->
  <!--                    of resource cache. A bio cached buffer may be used-->
  <!--                    by nio but is not as efficient as a nio buffer.   -->
  <!--                    An nio cached buffer may not be used by bio.      -->
  <!--                                                                      -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
    <init-param>
      <param-name>acceptRanges</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>dirAllowed</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>welcomeServlets</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>redirectWelcome</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>maxCacheSize</param-name>
      <param-value>256000000</param-value>
    </init-param>
    <init-param>
      <param-name>maxCachedFileSize</param-name>
      <param-value>10000000</param-value>
    </init-param>
    <init-param>
      <param-name>maxCachedFiles</param-name>
      <param-value>1000</param-value>
    </init-param>
    <init-param>
      <param-name>cacheType</param-name>
      <param-value>both</param-value>
    </init-param>
    <init-param>
      <param-name>gzip</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>useFileMappedBuffer</param-name>
      <param-value>false</param-value>
    </init-param>  
    <!--
    <init-param>
      <param-name>cacheControl</param-name>
      <param-value>max-age=3600,public</param-value>
    </init-param>
    -->
    <load-on-startup>0</load-on-startup>
  </servlet> 

  <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
  

  <!-- ==================================================================== -->
  <!-- JSP Servlet                                                          -->
  <!-- This is the jasper JSP servlet from the jakarta project              -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->
  <!-- used by Glassfish to support JSP pages.  Traditionally, this servlet -->
  <!-- is mapped to URL patterh "*.jsp".  This servlet supports the         -->
  <!-- following initialization parameters (default values are in square    -->
  <!-- brackets):                                                           -->
  <!--                                                                      -->
  <!--   checkInterval       If development is false and reloading is true, -->
  <!--                       background compiles are enabled. checkInterval -->
  <!--                       is the time in seconds between checks to see   -->
  <!--                       if a JSP page needs to be recompiled. [300]    -->
  <!--                                                                      -->
  <!--   compiler            Which compiler Ant should use to compile JSP   -->
  <!--                       pages.  See the Ant documenation for more      -->
  <!--                       information. [javac]                           -->
  <!--                                                                      -->
  <!--   classdebuginfo      Should the class file be compiled with         -->
  <!--                       debugging information?  [true]                 -->
  <!--                                                                      -->
  <!--   classpath           What class path should I use while compiling   -->
  <!--                       generated servlets?  [Created dynamically      -->
  <!--                       based on the current web application]          -->
  <!--                       Set to ? to make the container explicitly set  -->
  <!--                       this parameter.                                -->
  <!--                                                                      -->
  <!--   development         Is Jasper used in development mode (will check -->
  <!--                       for JSP modification on every access)?  [true] -->
  <!--                                                                      -->
  <!--   enablePooling       Determines whether tag handler pooling is      -->
  <!--                       enabled  [true]                                -->
  <!--                                                                      -->
  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->
  <!--                       a separate JVM is used for JSP page compiles   -->
  <!--                       from the one Tomcat is running in. [true]      -->
  <!--                                                                      -->
  <!--   ieClassId           The class-id value to be sent to Internet      -->
  <!--                       Explorer when using <jsp:plugin> tags.         -->
  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->
  <!--                                                                      -->
  <!--   javaEncoding        Java file encoding to use for generating java  -->
  <!--                       source files. [UTF-8]                          -->
  <!--                                                                      -->
  <!--   keepgenerated       Should we keep the generated Java source code  -->
  <!--                       for each page instead of deleting it? [true]   -->
  <!--                                                                      -->
  <!--   logVerbosityLevel   The level of detailed messages to be produced  -->
  <!--                       by this servlet.  Increasing levels cause the  -->
  <!--                       generation of more messages.  Valid values are -->
  <!--                       FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
  <!--                       [WARNING]                                      -->
  <!--                                                                      -->
  <!--   mappedfile          Should we generate static content with one     -->
  <!--                       print statement per input line, to ease        -->
  <!--                       debugging?  [false]                            -->
  <!--                                                                      -->
  <!--                                                                      -->
  <!--   reloading           Should Jasper check for modified JSPs?  [true] -->
  <!--                                                                      -->
  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->
  <!--                       debugging be suppressed?  [false]              -->
  <!--                                                                      -->
  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->
  <!--                       dumped to a file? [false]                      -->
  <!--                       False if suppressSmap is true                  -->
  <!--                                                                      -->
  <!--   scratchdir          What scratch directory should we use when      -->
  <!--                       compiling JSP pages?  [default work directory  -->
  <!--                       for the current web application]               -->
  <!--                                                                      -->
  <!--   tagpoolMaxSize      The maximum tag handler pool size  [5]         -->
  <!--                                                                      -->
  <!--   xpoweredBy          Determines whether X-Powered-By response       -->
  <!--                       header is added by generated servlet  [false]  -->
  <!--                                                                      -->
  <!-- If you wish to use Jikes to compile JSP pages:                       -->
  <!--   Set the init parameter "compiler" to "jikes".  Define              -->
  <!--   the property "-Dbuild.compiler.emacs=true" when starting Jetty     -->
  <!--   to cause Jikes to emit error messages in a format compatible with  -->
  <!--   Jasper.                                                            -->
  <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->
  <!--   try setting the init parameter "javaEncoding" to "ISO-8859-1".     -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <servlet id="jsp">
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
        <param-name>logVerbosityLevel</param-name>
        <param-value>DEBUG</param-value>
    </init-param>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <!--  
    <init-param>
        <param-name>classpath</param-name>
        <param-value>?</param-value>
    </init-param>
    -->
    <load-on-startup>0</load-on-startup>
  </servlet>

  <servlet-mapping> 
    <servlet-name>jsp</servlet-name> 
    <url-pattern>*.jsp</url-pattern> 
    <url-pattern>*.jspf</url-pattern>
    <url-pattern>*.jspx</url-pattern>
    <url-pattern>*.xsp</url-pattern>
    <url-pattern>*.JSP</url-pattern> 
    <url-pattern>*.JSPF</url-pattern>
    <url-pattern>*.JSPX</url-pattern>
    <url-pattern>*.XSP</url-pattern>
  </servlet-mapping>
  
  <!-- ==================================================================== -->
  <!-- Dynamic Servlet Invoker.                                             -->
  <!-- This servlet invokes anonymous servlets that have not been defined   -->
  <!-- in the web.xml or by other means. The first element of the pathInfo  -->
  <!-- of a request passed to the envoker is treated as a servlet name for  -->
  <!-- an existing servlet, or as a class name of a new servlet.            -->
  <!-- This servlet is normally mapped to /servlet/*                        -->
  <!-- This servlet support the following initParams:                       -->
  <!--                                                                      -->
  <!--  nonContextServlets       If false, the invoker can only load        -->
  <!--                           servlets from the contexts classloader.    -->
  <!--                           This is false by default and setting this  -->
  <!--                           to true may have security implications.    -->
  <!--                                                                      -->
  <!--  verbose                  If true, log dynamic loads                 -->
  <!--                                                                      -->
  <!--  *                        All other parameters are copied to the     -->
  <!--                           each dynamic servlet as init parameters    -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- Uncomment for dynamic invocation
  <servlet>
    <servlet-name>invoker</servlet-name>
    <servlet-class>org.mortbay.jetty.servlet.Invoker</servlet-class>
    <init-param>
      <param-name>verbose</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>nonContextServlets</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>dynamicParam</param-name>
      <param-value>anyValue</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
  </servlet>

  <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
  -->



  <!-- ==================================================================== -->
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config>

  <!-- ==================================================================== -->
  <!-- Default MIME mappings                                                -->
  <!-- The default MIME mappings are provided by the mime.properties        -->
  <!-- resource in the org.mortbay.jetty.jar file.  Additional or modified  -->
  <!-- mappings may be specified here                                       -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
  <!-- UNCOMMENT TO ACTIVATE
  <mime-mapping>
    <extension>mysuffix</extension>
    <mime-type>mymime/type</mime-type>
  </mime-mapping>
  -->

  <!-- ==================================================================== -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <!-- ==================================================================== -->
  <locale-encoding-mapping-list>
    <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>     
    <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
    <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>   
  </locale-encoding-mapping-list>
  
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Disable TRACE</web-resource-name>
      <url-pattern>/</url-pattern>
      <http-method>TRACE</http-method>
    </web-resource-collection>
    <auth-constraint/>
  </security-constraint>
  
</web-app>

application.properties

scanPackage=com.demo.spring

web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>sucqmvc</servlet-name>
        <servlet-class>com.mvcframework.v2.servlet.SDispatchServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>application.properties</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>sucqmvc</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

業務程式碼

controller

package com.demo.spring.action;

import com.demo.spring.service.IDemoService;
import com.mvcframework.annotation.SAutowired;
import com.mvcframework.annotation.SController;
import com.mvcframework.annotation.SRequestMapping;
import com.mvcframework.annotation.SRequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


//雖然,用法一樣,但是沒有功能
@SController
@SRequestMapping("/demo")
public class DemoAction {

   @SAutowired
   private IDemoService demoService;

   @SRequestMapping("/query")
   public void query(HttpServletRequest req, HttpServletResponse resp,
                 @SRequestParam("name") String name){
      String result = demoService.get(name);
//    String result = "My name is " + name;
      try {
         resp.getWriter().write(result);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   @SRequestMapping("/add")
   public void add(HttpServletRequest req, HttpServletResponse resp,
               @SRequestParam("a") Integer a, @SRequestParam("b") Integer b){
      try {
         resp.getWriter().write(a + "+" + b + "=" + (a + b));
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   @SRequestMapping("/sub")
   public void add(HttpServletRequest req, HttpServletResponse resp,
               @SRequestParam("a") Double a, @SRequestParam("b") Double b){
      try {
         resp.getWriter().write(a + "-" + b + "=" + (a - b));
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   @SRequestMapping("/remove")
   public String  remove(@SRequestParam("id") Integer id){
      return "" + id;
   }


}
package com.demo.spring.action;


//沒加註解,控制權不反轉,自己管自己
public class TestAction {
}
package com.demo.spring.action;

import com.demo.spring.service.IDemoService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//沒加註解,控制權不反轉,自己管自己
public class TwoAction {
   
   private IDemoService demoService;

   public void edit(HttpServletRequest req,HttpServletResponse resp,
                String name){
      String result = demoService.get(name);
      try {
         resp.getWriter().write(result);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
   
}

entity

package com.demo.spring.entity;

public class Test {

    public static void main(String[] args) {
        String simpleName = Test.class.getSimpleName();
        System.out.println(simpleName);
    }
}

service

package com.demo.spring.service;


public interface IDemoService {
   
   String get(String name);
   
}
package com.demo.spring.service.impl;

import com.demo.spring.service.IDemoService;
import com.mvcframework.annotation.SService;

/**
 * 核心業務邏輯
 */
@SService
public class DemoService implements IDemoService {

   public String get(String name) {
      return "My name is " + name + ",from service.";
   }

}

spring程式碼

註解

package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SAutowired {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SController {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SRequestMapping {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SRequestParam {
    String value() default "";
}
package com.mvcframework.annotation;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SService {
    String value() default "";
}

servlet

package com.mvcframework.v2.servlet;

import com.mvcframework.annotation.*;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
import java.io.File;


public class SDispatchServlet extends HttpServlet {
    private Properties contextConfig = new Properties();

    //享元模式,快取
    private List<String> classNames = new ArrayList<String>();

    //IoC容器,key預設是類名首字母小寫,value就是對應的例項物件
    private Map<String,Object> ioc = new HashMap<String,Object>();

    private Map<String,Method> handlerMapping = new HashMap<String, Method>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //6、委派,根據URL去找到一個對應的Method並通過response返回
        try {
            doDispatch(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
            resp.getWriter().write("500 Exception,Detail : " + Arrays.toString(e.getStackTrace()));
        }

    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        String url = req.getRequestURI();
        String contextPath = req.getContextPath();
        url = url.replaceAll(contextPath,"").replaceAll("/+","/");

        if(!this.handlerMapping.containsKey(url)){
            resp.getWriter().write("404 Not Found!!!");
            return;
        }

        Map<String,String[]> params = req.getParameterMap();

        Method method = this.handlerMapping.get(url);


        //獲取形參列表
        Class<?> [] parameterTypes = method.getParameterTypes();
        Object [] paramValues = new Object[parameterTypes.length];

        for (int i = 0; i < parameterTypes.length; i++) {
            Class paramterType = parameterTypes[i];
            if(paramterType == HttpServletRequest.class){
                paramValues[i] = req;
            }else if(paramterType == HttpServletResponse.class){
                paramValues[i] = resp;
            }else if(paramterType == String.class){
                //通過執行時的狀態去拿到你
                Annotation[] [] pa = method.getParameterAnnotations();
                for (int j = 0; j < pa.length ; j ++) {
                    for(Annotation a : pa[i]){
                        if(a instanceof SRequestParam){
                            String paramName = ((SRequestParam) a).value();
                            if(!"".equals(paramName.trim())){
                               String value = Arrays.toString(params.get(paramName))
                                       .replaceAll("\\[|\\]","")
                                       .replaceAll("\\s+",",");
                                paramValues[i] = value;
                            }
                        }
                    }
                }

            }
        }


        //暫時硬編碼
        String beanName = toLowerFirstCase(method.getDeclaringClass().getSimpleName());
        //賦值實參列表
        method.invoke(ioc.get(beanName),paramValues);

    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        //1、載入配置檔案
        doLoadConfig(config.getInitParameter("contextConfigLocation"));

        //2、掃描相關的類
        doScanner(contextConfig.getProperty("scanPackage"));

        //==============IoC部分==============
        //3、初始化IoC容器,將掃描到的相關的類例項化,儲存到IcC容器中
        doInstance();

        //AOP,新生成的代理物件

        //==============DI部分==============
        //4、完成依賴注入
        doAutowired();

        //==============MVC部分==============
        //5、初始化HandlerMapping
        doInitHandlerMapping();

        System.out.println("S Spring framework is init.");
    }

    private void doInitHandlerMapping() {
        if(ioc.isEmpty()){ return;}

        for (Map.Entry<String,Object> entry : ioc.entrySet()) {
            Class<?> clazz = entry.getValue().getClass();

            if(!clazz.isAnnotationPresent(SController.class)){ continue; }


            //相當於提取 class上配置的url
            String baseUrl = "";
            if(clazz.isAnnotationPresent(SRequestMapping.class)){
                SRequestMapping requestMapping = clazz.getAnnotation(SRequestMapping.class);
                baseUrl = requestMapping.value();
            }

            //只獲取public的方法
            for (Method method : clazz.getMethods()) {
                if(!method.isAnnotationPresent(SRequestMapping.class)){continue;}
                //提取每個方法上面配置的url
                SRequestMapping requestMapping = method.getAnnotation(SRequestMapping.class);

                // //demo//query
                String url = ("/" + baseUrl + "/" + requestMapping.value()).replaceAll("/+","/");
                handlerMapping.put(url,method);
                System.out.println("Mapped : " + url + "," + method);
            }

        }
    }

    private void doAutowired() {
        if(ioc.isEmpty()){return;}

        for (Map.Entry<String,Object> entry : ioc.entrySet()) {

            //把所有的包括private/protected/default/public 修飾字段都取出來
            for (Field field : entry.getValue().getClass().getDeclaredFields()) {
                if(!field.isAnnotationPresent(SAutowired.class)){ continue; }

                SAutowired autowired = field.getAnnotation(SAutowired.class);

                //如果使用者沒有自定義的beanName,就預設根據型別注入
                String beanName = autowired.value().trim();
                if("".equals(beanName)){
                    //field.getType().getName() 獲取欄位的型別
                    beanName = field.getType().getName();
                }

                //暴力訪問
                field.setAccessible(true);

                try {
                    //ioc.get(beanName) 相當於通過介面的全名拿到介面的實現的例項
                    field.set(entry.getValue(),ioc.get(beanName));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    private void doInstance() {
        if(classNames.isEmpty()){return;}

        try {
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);

                if(clazz.isAnnotationPresent(SController.class)) {
                    //key提取出來了,把value也搞出來
                    String beanName = toLowerFirstCase(clazz.getSimpleName());
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);
                }else if(clazz.isAnnotationPresent(SService.class)){
                    //1、在多個包下出現相同的類名,只能寄幾(自己)起一個全域性唯一的名字
                    //自定義命名
                    String beanName = clazz.getAnnotation(SService.class).value();
                    if("".equals(beanName.trim())){
                        beanName = toLowerFirstCase(clazz.getSimpleName());
                    }

                    //2、預設的類名首字母小寫
                    Object instance = clazz.newInstance();
                    ioc.put(beanName, instance);

                    //3、如果是介面
                    //判斷有多少個實現類,如果只有一個,預設就選擇這個實現類
                    //如果有多個,只能拋異常
                    for (Class<?> i : clazz.getInterfaces()) {
                        if(ioc.containsKey(i.getName())){
                            throw new Exception("The " + i.getName() + " is exists!!");
                        }
                        ioc.put(i.getName(),instance);
                    }

                }else{
                    continue;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    //自己寫,自己用
    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
//        if(chars[0] > )
        chars[0] += 32;
        return String.valueOf(chars);
    }

    private void doScanner(String scanPackage) {
        //jar 、 war 、zip 、rar
        URL url = this.getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.","/"));
        File classPath = new File(url.getFile());

        //當成是一個ClassPath資料夾
        for (File file : classPath.listFiles()) {
            if(file.isDirectory()){
                doScanner(scanPackage + "." + file.getName());
            }else {
                if(!file.getName().endsWith(".class")){continue;}
                //全類名 = 包名.類名
                String className = (scanPackage + "." + file.getName().replace(".class", ""));
                //Class.forName(className);
                classNames.add(className);
            }
        }
    }

    private void doLoadConfig(String contextConfigLocation) {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(null != is){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}