2.spring-手寫1.0
阿新 • • 發佈:2022-03-30
配置
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();
}
}
}
}
}