手写SpringMVC豪华版

SpringMVC作为最常用的web框架,如果有一天用自己写的框架去实现自己的项目,是不是也挺有意思的。之前的博客中已经完成了,SpirngIOC容器的模拟实现,所以就在原来的基础上实现自己的SpringMVC框架。话不多说上源码:

1、实现自定义注解:

package servlet.annotation;

import java.lang.annotation.*;

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

package servlet.annotation;

import java.lang.annotation.*;

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


package servlet.annotation;

import java.lang.annotation.*;

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


package servlet.annotation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    String value();
}


package servlet.annotation;

import java.lang.annotation.*;

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

2、实现Bean的定义类BeanDefinition,扩展类BeanWrapper,事件监听类BeanPostProcessor

package servlet.context.beans;

/**
 * 存储配置文件中的信息,相当于保存在内存中的配置
 */
public class BeanDefinition {

    private String beanClassName;

    private String factoryBeanName;

    private boolean lazyInit=false;

    public String getBeanClassName() {
        return beanClassName;
    }

    public void setBeanClassName(String beanClassName) {
        this.beanClassName = beanClassName;
    }

    public String getFactoryBeanName() {
        return factoryBeanName;
    }

    public void setFactoryBeanName(String factoryBeanName) {
        this.factoryBeanName = factoryBeanName;
    }

    public boolean isLazyInit() {
        return lazyInit;
    }

    public void setLazyInit(boolean lazyInit) {
        this.lazyInit = lazyInit;
    }

    //    public void setBeanClassName(String beanClassName){
//
//    }
//
//    public String getBeanCLassName(){
//        return null;
//    }
//
//    public void setFactoryBeanName(String factoryBeanName){
//
//    }
//
//    public String getFactoryBeanName(){
//        return null;
//    }
//
//    public void setLazyInit(boolean lazyInit){
//
//    }
//
//    public boolean isLazyInit(){
//        return false;
//    }

}


package servlet.context.beans;
//用于做事件监听
public class BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean,String beanName){
        return null;
    }
    public Object postProcessAfterInitializatioin(Object bean,String beanName){
        return null;
    }
}



package servlet.context.beans;

public class BeanWrapper {
    //还会用到观察者模式
    // 支持事件响应,会有一个监听

    private BeanPostProcessor beanPostProcessor;

    private Object wrapperInstance;
    //通过反射new出来的,要把它包装起来
    private Object originalInstance;

    public BeanWrapper(Object instance) {
        this.wrapperInstance = instance;
        this.originalInstance = instance;
    }

    public Object getWrappedInstance() {
        return this.wrapperInstance;
    }

    //返回代理以后的Class
    //可能会是$Proxy0
    public Class<?> getWrappedClass() {
        return this.wrapperInstance.getClass();
    }

    public BeanPostProcessor getBeanPostProcessor() {
        return beanPostProcessor;
    }

    public void setBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        this.beanPostProcessor = beanPostProcessor;
    }
}

3、实现Bean信息的读取类

package servlet.context.support;

import servlet.context.beans.BeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
//用于对配置文件查找,读取,解析
public class BeanDefinitiionReader {

    private Properties config=new Properties();

    private List<String> registyBeanClasses=new ArrayList<String>();
    //配置文件中用来获取自动扫描的包名的key
    private final String SCAN_PACKAGE="scanPackage";

    public BeanDefinitiionReader(String ... locations){
        //spring中通过reader去查找和定位
        InputStream is=this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(null!=is) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        doScanner(config.getProperty(SCAN_PACKAGE));
    }

    public List<String> getRegistyBeanClasses(){
        return null;
    }

    public List<String> loadBeanDefinitions(){
        return this.registyBeanClasses;
    };
    //每注册一个className,就返回一个BeanDefinition,自己包装
    //BeanDefinition只是为了对配置信息进行包装
    public BeanDefinition registerBean(String className){
        if(this.registyBeanClasses.contains(className)){
            BeanDefinition beanDefinition=new BeanDefinition();
            beanDefinition.setBeanClassName(className);
            beanDefinition.setFactoryBeanName(toLowerFirstWord(className.substring(className.lastIndexOf(".")+1)));
            return beanDefinition;
        }
        return null;
    }

    //递归扫描所有相关联的class,保存在一个List中
    private void doScanner(String packageName){

        URL url=this.getClass().getClassLoader().getResource("/"+packageName.replaceAll("\\.","/"));
        File classDir=new File(url.getFile());
        for(File file:classDir.listFiles()){
            if(file.isDirectory()){
                doScanner(packageName+"."+file.getName());
            }else {
                registyBeanClasses.add(packageName+"."+file.getName().replace(".class",""));
            }
        }
    }

    private String toLowerFirstWord(String str){
        char[] charArr=str.toCharArray();
        charArr[0]+=32;
        return String.valueOf(charArr);
    }


    public Properties getConfig(){
        return this.config;
    }
}

4、定义Bean的顶级接口

package servlet.core;

public interface BeanFactory {

    Object getBean(String beanName);
}

5、实现IOC容器ApplicationContext
 

package servlet.context;

import servlet.annotation.Autowired;
import servlet.annotation.Controller;
import servlet.annotation.Service;
import servlet.context.beans.BeanDefinition;
import servlet.context.beans.BeanPostProcessor;
import servlet.context.beans.BeanWrapper;
import servlet.context.support.BeanDefinitiionReader;
import servlet.context.support.DefaultListableBeanFactory;
import servlet.core.BeanFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

public class ApplicationContext  implements BeanFactory {

    private String[] configLocations;

    private BeanDefinitiionReader reader;
    //用来保存配置信息的map
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
    //用来保存注册是单例的容器
    private Map<String, Object> beanCacheMap = new HashMap<>();
    //用来存储所有的被代理过得对象
    private Map<String,BeanWrapper> beanWrapperMap = new ConcurrentHashMap<>();

    public ApplicationContext(String... configLocations) {
        this.configLocations = configLocations;
        refresh();
    }


    public void refresh() {


        //定位
        this.reader = new BeanDefinitiionReader(configLocations);

        //加载

        List<String> beanDefinitions = reader.loadBeanDefinitions();

        //注册
        doRegistry(beanDefinitions);

        //依赖注入,(lazy-init=false,执行依赖注入)
        //这里自动调用getBean方法
        doAutowired();
        System.out.println("IOC注册成功");
    }
    private void doAutowired(){
        for(Map.Entry<String,BeanDefinition> beanDefinitionEntry:beanDefinitionMap.entrySet()){
            //如果这个bean不是延迟加载,调用getBean方法进行实例化
            if(!beanDefinitionEntry.getValue().isLazyInit()){
                String beanName=beanDefinitionEntry.getKey();
                getBean(beanName);
            }
        }
    }
    //依赖注入
    public void populateBean(String bean,Object instance){
        Class clazz=instance.getClass();
        //对包含Controller.class和包含Service.class的类进行依赖注入
        if(clazz.isAnnotationPresent(Controller.class)||clazz.isAnnotationPresent(Service.class)){
            Field[] fields=clazz.getDeclaredFields();
            for (int i = 0; i <fields.length; i++) {
                Field field=fields[i];
                //如果字段内不包含autowire注释,跳过该字段继续循环
                if(!field.isAnnotationPresent(Autowired.class)){
                    continue;
                }
                Autowired autowired=field.getAnnotation(Autowired.class);
                //获取autowired注解的值
                String beanName=autowired.value().trim();
                //如果注解值为空,使用默认注解
                if("".equals(beanName)){
                    beanName=field.getType().getName();

                }
                Object object=beanWrapperMap.get(beanName).getWrappedInstance();
                field.setAccessible(true);
                try {
                    field.set(instance,object);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // 真正的将beanDefiniton注册到beanDefinitionMap
    private void doRegistry(List<String> beanDefinitions) {
        //beanName有三种情况
        //1、默认首字母小写
        //2、自定义名字
        //3、接口注入
        try {
            for (String className : beanDefinitions) {
                Class<?> beanClass = Class.forName(className);
                if (beanClass.isInterface()) {
                    continue;
                }
                BeanDefinition beanDefinition = reader.registerBean(className);
                if(beanDefinition!=null){
                    this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
                }

                Class<?>[] interfaces=beanClass.getInterfaces();

                for (Class clazz:interfaces
                     ) {
                this.beanDefinitionMap.put(clazz.getName(),beanDefinition);
                }
                //到这里为止,容器初始化完毕
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //依赖注入从这里开始,通过读取BeanDefinition中的信息,
    //然后,通过反射机制创建一个实例,并返回
    //Spring的做法是,不会把最原始的对象放出去,会用一个BeanWrapper来进行一次包装
    //装饰器模式,
    //1、保留原来的OOP关系
    //2、我需要对他进行扩展和增强
    @Override
    public Object getBean(String beanName) {
        BeanDefinition beanDefinition=this.beanDefinitionMap.get(beanName);
        String className=beanDefinition.getBeanClassName();
        try{
            //生成通知事件
            BeanPostProcessor beanPostProcessor=new BeanPostProcessor();

            Object instance=instantionBean(beanDefinition);
            if(null==instance){
                return null;
            }
            //实例初始化以前调用一次
            beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
            BeanWrapper beanWrapper=new BeanWrapper(instance);
            beanWrapper.setBeanPostProcessor(beanPostProcessor);
            this.beanWrapperMap.put(beanName,beanWrapper);
            //实例初始化以后调用一次
            beanPostProcessor.postProcessAfterInitializatioin(instance,beanName);
            populateBean(beanName,instance);
            //通过这样一调用,相当于给自己留下了可操作空间
            return this.beanWrapperMap.get(beanName).getWrappedInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    //传一个beanDefinition,返回一个instance
    private Object instantionBean(BeanDefinition beanDefinition){
        Object instance=null;
        String className=beanDefinition.getBeanClassName();
        try {
            //根据class才能确定一个类是否有实例
            if(this.beanCacheMap.containsKey(className)){
                instance=this.beanCacheMap.get(className);
            }else{
                Class clazz=Class.forName(className);
                instance=clazz.newInstance();
                beanCacheMap.put(className,instance);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return instance;
    }

    public String[] getBeanDefinitionNames(){
        return this.beanDefinitionMap.keySet().toArray(new String[this.beanDefinitionMap.size()]);
    }

    public int getBeanDefinitionCount(){
        return this.beanDefinitionMap.size();
    }

    public Properties getConfig(){
        return reader.getConfig();
    }

//    @Override
//    protected void onRefresh() {
//        super.onRefresh();
//    }
//
//    @Override
//    protected void refreshBeanFactory() {
//        super.refreshBeanFactory();
//    }
}

6、实现SpringMVC入口启动类DispatcherServlet
 

package servlet;

import servlet.annotation.Controller;
import servlet.annotation.RequestMapping;
import servlet.annotation.RequestParam;
import servlet.context.ApplicationContext;
import servlet.webmvc.HandlerAdapter;
import servlet.webmvc.HandlerMapping;
import servlet.webmvc.ModelAndView;
import servlet.webmvc.ViewResolver;

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.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//Servlet只是作为mvc的启动入口
public class DispatcherServlet extends HttpServlet {
    private final String LOCATION="contextConfigLocation";
    //SpringMVC最核心的一个设计
    private List<HandlerMapping> handlerMappings=new ArrayList<HandlerMapping>();

    private List<ViewResolver> viewResolvers=new ArrayList<ViewResolver>();

    private Map<HandlerMapping,HandlerAdapter> handlerAdapters=new HashMap<HandlerMapping,HandlerAdapter>();

    @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 {
        try {
            this.doDispatch(req, resp);
        }catch (Exception e){
            resp.getWriter().write("500 Exception"+Arrays.toString(e.getStackTrace()).replaceAll("\\[|\\]","")
            .replaceAll("\\s+","\r\n"));
        }
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        ApplicationContext applicationContext=new ApplicationContext(config.getInitParameter(LOCATION));
        initStrategy(applicationContext);

    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception{
        HandlerMapping handler=getHandler(req);
        if(handler==null){
            resp.getWriter().write("404 NOT FOUND");
            return;
        }
        HandlerAdapter ha=getHandlerAdapter(handler);

        ModelAndView mv=ha.handle(req,resp,handler);

        processDispatchServlet(resp,mv);
    }

    private HandlerMapping getHandler(HttpServletRequest req){
        if(this.handlerMappings.isEmpty()){
            return null;
        }
        String uri=req.getRequestURI();
        String contextPath=req.getContextPath();
        String url=uri.replace(contextPath,"").replaceAll("/+","/");
        for(HandlerMapping handlerMapping:this.handlerMappings){
            Matcher matcher=handlerMapping.getPattern().matcher(url);
            if(matcher.matches()){
            return handlerMapping;
            }
        }
        return null;
    }
    private HandlerAdapter getHandlerAdapter(HandlerMapping handler){
        return handlerAdapters.get(handler);
    }
    private void processDispatchServlet(HttpServletResponse resp,ModelAndView mv)throws Exception{
            if(mv==null){
                return;
            }
            if(viewResolvers.isEmpty()){
                return;
            }
            for(ViewResolver viewResolver:viewResolvers){
                if(viewResolver.getViewName().equals(mv.getViewname())){
                    String result=viewResolver.doViewResolver(mv);
                    resp.getWriter().write(result);
                    return;
                }
            }
    }

    private void initStrategy(ApplicationContext context){
        initHandlerMapping(context);
        initHandlerAdapters(context);
        initViewResolvers(context);
    }
    private void initHandlerMapping(ApplicationContext context){
            String[] beanNames=context.getBeanDefinitionNames();
        for (String beanName:beanNames) {
            Object instance=context.getBean(beanName);
            Class<?> clazz=instance.getClass();
            if(!clazz.isAnnotationPresent(Controller.class)){
                continue;
            }
            RequestMapping requestMapping=clazz.getAnnotation(RequestMapping.class);
            String baseUrl="";
            if(requestMapping!=null){
                baseUrl=requestMapping.value();
            }
            Method[] methods=clazz.getMethods();
            for (Method me :
                    methods) {
                if(!me.isAnnotationPresent(RequestMapping.class)){
                    continue;
                }
                RequestMapping rm=me.getAnnotation(RequestMapping.class);
               String url=baseUrl+rm.value().replaceAll("/+","/");
               Pattern pattern=Pattern.compile(url);
               HandlerMapping handlerMapping=new HandlerMapping(pattern,instance,me);
               this.handlerMappings.add(handlerMapping);
            }
        }
    }
    private void initHandlerAdapters(ApplicationContext context){
        for (HandlerMapping handlerMapping:this.handlerMappings
             ) {
            Map<String,Integer> paramMapping=new HashMap<String,Integer>();
                Method me=handlerMapping.getMethod();
                Annotation[][] annotations=me.getParameterAnnotations();
                for(int i=0;i<annotations.length;i++){
                    Annotation[] annotationsArr=annotations[i];
                    for(Annotation annotation:annotationsArr){
                        if(annotation instanceof RequestParam){
                           String paramName=((RequestParam) annotation).value();
                           if(!"".equals(paramName)){
                            paramMapping.put(paramName,i);
                           }
                        }
                    }
                }
                //接下来处理非命名参数,只处理Request Response
                Class<?>[] parameterTypes=me.getParameterTypes();
                for(int i=0;i<parameterTypes.length;i++){
                    Class<?> clazz=parameterTypes[i];
                    if(clazz==HttpServletRequest.class||clazz==HttpServletResponse.class){
                    paramMapping.put(clazz.getName(),i);
                    }
                }
                handlerAdapters.put(handlerMapping,new HandlerAdapter(paramMapping));
        }

    }
    private void initViewResolvers(ApplicationContext context){
        Properties config=context.getConfig();
        String path=config.getProperty("templateRoot");
        String templateRootPath=this.getClass().getClassLoader().getResource(path).getFile();
        File templateRootFile=new File(templateRootPath);
        for(File file:templateRootFile.listFiles()){
            ViewResolver viewResolver=new ViewResolver(file.getName(),file);
            this.viewResolvers.add(viewResolver);
        }
    }
}

7、实现SpringMVC三大核心组件HandlerMapping , HandlerAdapter ,ViewResolver 和ModelAndView

 

package servlet.webmvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Map;

public class HandlerAdapter {
    private Map<String,Integer> paramMapping;

    public HandlerAdapter(Map<String, Integer> paramMapping) {
        this.paramMapping = paramMapping;
    }

    public ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, HandlerMapping handler)throws Exception{
        //req 根据用户的请求信息,跟method中的参数进行动态匹配
        //resp主要是为了给方法中的参数赋值
        //获取方法的形参列表 parameterTypes
        Class<?>[] parameterTypes=handler.getMethod().getParameterTypes();
        //获取请求参数列表
        Map<String,String[]> parameterMap=req.getParameterMap();
        //构建参数数组
        Object[] paramValues=new Object[parameterTypes.length];
        for(Map.Entry<String,String[]> entry:parameterMap.entrySet()){
            String value= Arrays.toString(entry.getValue()).replaceAll("\\[|\\]","").replaceAll("\\s","");
            if(paramMapping.containsKey(entry.getKey())){
                int index=paramMapping.get(entry.getKey());
                Object obj=convertToOtherType(value,parameterTypes[index]);
                paramValues[index]=obj;
            }
        }
        if(this.paramMapping.containsKey(HttpServletRequest.class.getName())) {
            int reqIndex = paramMapping.get(HttpServletRequest.class.getName());
            paramValues[reqIndex] = req;
        }
        if(this.paramMapping.containsKey(HttpServletResponse.class.getName())) {
            int respIndex = paramMapping.get(HttpServletResponse.class.getName());
            paramValues[respIndex] = resp;
        }
        Object result= handler.getMethod().invoke(handler.getController(),paramValues);
        if(result==null){
            return null;
        }
        if(handler.getMethod().getReturnType()==ModelAndView.class){
            return (ModelAndView)result;
        }else {
            return null;
        }
    }
    private Object convertToOtherType(String value,Class<?> clazz){
        if(clazz==String.class){
            return value;
        }else if(clazz==Integer.class){
            return Integer.valueOf(value);
        }else if(clazz==int.class){
            return Integer.valueOf(value).intValue();
        }else{
            return null;
        }
    }

}
package servlet.webmvc;

import java.lang.reflect.Method;
import java.util.regex.Pattern;

public class HandlerMapping {
    private Pattern pattern;
    private Object controller;
    private Method method;

    public HandlerMapping(Pattern pattern, Object controller, Method method) {
        this.pattern = pattern;
        this.controller = controller;
        this.method = method;
    }

    public Pattern getPattern() {
        return pattern;
    }

    public Object getController() {
        return controller;
    }

    public Method getMethod() {
        return method;
    }

    public void setPattern(Pattern pattern) {
        this.pattern = pattern;
    }

    public void setController(Object controller) {
        this.controller = controller;
    }

    public void setMethod(Method method) {
        this.method = method;
    }
}
package servlet.webmvc;

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

public class ModelAndView {
    private String viewname;
    private Map<String,Object> model=new HashMap<String,Object>();

    public ModelAndView(String viewname, Map<String, Object> model) {
        this.viewname = viewname;
        this.model = model;
    }

    public String getViewname() {
        return viewname;
    }

    public Map<String, Object> getModel() {
        return model;
    }

    public void setViewname(String viewname) {
        this.viewname = viewname;
    }

    public void setModel(Map<String, Object> model) {
        this.model = model;
    }
}
package servlet.webmvc;

import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//设计这个类的主要目的
//1、将一个静态文件转化为一个动态文件
//2、根据用户传的参数不同,产生不同的结果
//最终输出字符串,交给resp输出
public class ViewResolver {
    private String viewName;
    private File templateFile;
    public ViewResolver(String viewName,File templateFile){
        this.viewName=viewName;
        this.templateFile=templateFile;
    }

    public String getViewName() {
        return viewName;
    }

    public File getTemplateFile() {
        return templateFile;
    }

    public void setViewName(String viewName) {
        this.viewName = viewName;
    }

    public void setTemplateFile(File templateFile) {
        this.templateFile = templateFile;
    }

    public String doViewResolver(ModelAndView mv) throws Exception{
        InputStream is=new FileInputStream(this.templateFile);
        BufferedReader ir=new BufferedReader(new InputStreamReader(is,"utf-8"));
        String line=null;
        StringBuffer sb=new StringBuffer();
        while((line=ir.readLine())!=null){
            Matcher matcher=matcher(line);
            while (matcher.find()){
                for(int i=1;i<=matcher.groupCount();i++){
                 //把¥{}中间的字符创取出来
                String paramName=matcher.group(i);
                Object paramValue=mv.getModel().get(paramName);
                if(paramValue==null){
                    continue;
                }
                line=line.replaceAll("¥\\{"+paramName+"\\}",paramValue.toString());
                }
            }
            sb.append(line);

        }
        return sb.toString();
    }

    private static Matcher matcher(String line){
        Pattern pattern=Pattern.compile("¥\\{(.+?)\\}",Pattern.CASE_INSENSITIVE);
        Matcher matcher=pattern.matcher(line);
        return matcher;
    }

    public static void main(String[] args) {
        String line="<h1>Hello ¥{teacher}! ¥{teacher}</h1>";
        Matcher matcher=matcher(line);
        while (matcher.find()){
            for(int i=1;i<=matcher.groupCount();i++){
                //把¥{}中间的字符创取出来
                String paramName=matcher.group(i);
//                Object paramValue=mv.getModel().get(paramName);
//                if(paramValue==null){
//                    continue;
//                }
                line=line.replaceAll("¥\\{"+paramName+"\\}","tom");
                System.out.println(line);
            }
        }
    }
}

8、业务demo:

package demo.controller;

import demo.service.IService;
import servlet.annotation.Autowired;
import servlet.annotation.Controller;
import servlet.annotation.RequestMapping;
import servlet.annotation.RequestParam;
import servlet.webmvc.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Controller
public class DemoController {
    @Autowired
    IService iService;
    @RequestMapping("/getInfo")
    public void getInfo(@RequestParam("param") String param){
        iService.add();
    }
    @RequestMapping("/doTest")
    public ModelAndView test1(HttpServletRequest request, HttpServletResponse response,
                              @RequestParam("param") String param){
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("teacher",param);
      ModelAndView mv=new ModelAndView("first.html",map);
      return mv;
    }


    @RequestMapping("/doTest2")
    public void test2(HttpServletRequest request, HttpServletResponse response){
        try {
            response.getWriter().println("doTest2 method success!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package demo.service;

import servlet.annotation.Service;


public interface IService {

    public void add();
}


package demo.service.impl;

import demo.service.IService;
import servlet.annotation.Service;

@Service
public class IServiceImpl implements IService {
    @Override
    public void add() {
        System.out.println("新增一条数据");
    }
}

 

9、web.xml 和配置文件
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>mvc</servlet-name>
    <servlet-class>servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:application.properties</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvc</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

</web-app>

application.properties
 

scanPackage=demo
templateRoot=layouts

first.html
 

<!DOCTYPE html/>
<html lang="zh-cn">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<h1>¥{teacher}</h1>
</body>

</html>

10.运行后在浏览器中访问:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值