JavaEE 企业级分布式高级架构师(四)SpringMVC学习笔记(2)

手写框架篇

需求分析

  • 需求:
* 查询用户:请求URL http://localhost/queryUser
* 添加用户:请求URL http://localhost/savaUser
  • 问题:如果按照常规Servlet开发习惯,一个类只会处理一个请求。
  • 解决方案:自定义Servlet extends BaseServlet(公共的Servlet)
BaseServlet{
     doPost(){
         // url中必须带有method参数
         // method参数的值就是对应要调用的方法名称
         // 通过反射调用制定方法
     }
}

MyServlet extends BaseServlet{
   query(){
   }
   save(){
   }
}
  • 只需要一个Servlet进行请求分发即可,处理请求的类只是一个普通类(不需要实现Servlet相关的类)

自定义SpringMVC框架V1版本

定义处理器

  • 处理器接口规范:
public interface HttpRequestHandler {
    void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
/**
 * 可以针对返回值进行二次处理
 */
public interface SimpleControllertHandler {
    ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
  • 处理器实现类:
/**
 * 查询用户处理器
 */
public class QueryUserHandler implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/plain;charset=utf-8");
        response.getWriter().write("--- QueryUserHandler ---");
    }
}
/**
 * 添加用户处理器
 */
public class SaveUserHandler implements SimpleControllertHandler {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/plain;charset=utf-8");
        response.getWriter().write("--- SaveUserHandler ---");
        return null;
    }
}

定义处理器映射器

  • 处理器映射器接口规范:
/**
 * 它的实现类是用来建立请求和处理类的映射关系
 * 该接口的作用是提供对该映射关系的访问,比如说根据请求查找处理类
 */
public interface HandlerMapping {
    /**
     * 根据请求查找处理类
     */
    Object getHandler(HttpServletRequest request) throws Exception;
}
  • 处理器映射器实现类:
/**
 * <bean name="/queryUser" class="QueryUserHandler的全路径"></bean>
 */
public class BeanNameUrlHandlerMapping implements HandlerMapping {
    private Map<String, Object> urlHandlers = new HashMap<>();

    public BeanNameUrlHandlerMapping() {
    	// TODO 暂时先写死
        this.urlHandlers.put("/queryUser", new QueryUserHandler());
    }

    @Override
    public Object getHandler(HttpServletRequest request) throws Exception {
        String uri = request.getRequestURI();

        return this.urlHandlers.get(uri);
    }
}
/**
 * <bean  class="内置的处理器类">
 *  <props>
 *      <prop key="url">类的全路径</prop>
 *  </props>
 * </bean>
 */
public class SimpleUrlHandlerMapping implements HandlerMapping {
    private Map<String, Object> urlHandlers = new HashMap<>();

    public SimpleUrlHandlerMapping() {
        // TODO 暂时先写死
        this.urlHandlers.put("/saveUser", new SaveUserHandler());
    }

    @Override
    public Object getHandler(HttpServletRequest request) throws Exception {
        String uri = request.getRequestURI();
        return this.urlHandlers.get(uri);
    }
}

定义处理器适配器

  • 处理器适配器接口规范:
/**
 * 该接口是DispatcherServlet用来调用不同类型处理器的统一类型
 * HandlerAdapter和Handler类型是一对一的,就类似于某一个类型的电脑,对应一个统一的电源适配器
 */
public interface HandlerAdapter {
    /**
     * 用来匹配适配器和处理器
     */
    boolean supports(Object handler);

    /**
     * 调用不同类型的处理器完成请求处理
     */
    ModelAndView handleRequest(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
  • 处理器适配器实现类:
public class HttpRequestHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof HttpRequestHandler);
    }

    @Override
    public ModelAndView handleRequest(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        return null;
    }
}
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof SimpleControllertHandler);
    }

    @Override
    public ModelAndView handleRequest(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception {
        return ((SimpleControllertHandler) handler).handleRequest(request, response);
    }
}

定义前端控制器

  • 抽象的Servlet:
public abstract class AbstractServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doDispatch(request, response);
    }

    /**
     * 请求分发
     */
    public abstract void doDispatch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
  • DispatcherServlet:
/**
 * springmvc提供的唯一的一个Servlet类
 */
public class DispatcherServlet extends AbstractServlet {
    /**
     * HandlerMapping的策略集合
     */
    private List<HandlerMapping> handlerMappings = new ArrayList<>();
    /**
     * HandlerAdapter的策略集合
     */
    private List<HandlerAdapter> handlerAdapters = new ArrayList<>();

    /**
     * servlet初始化
     */
    @Override
    public void init() throws ServletException {
        handlerMappings.add(new BeanNameUrlHandlerMapping());
        handlerMappings.add(new SimpleUrlHandlerMapping());

        handlerAdapters.add(new HttpRequestHandlerAdapter());
        handlerAdapters.add(new SimpleControllerHandlerAdapter());
    }

    @Override
    public void doDispatch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // 1、根据请求,查找对应的处理类
            // 问题1:处理类长啥样?(它和Servlet无关,可以随便写,只是说为了统一,最后指定规范[接口])
            // 问题2:去哪找处理类?(也就是请求URL和处理类的关系在哪建立)
            Object handler = getHandler(request);
            if (handler == null) {
                return;
            }
            // 2、调用处理类的方法,执行请求处理,并返回处理结果
            HandlerAdapter ha = getHandlerAdapter(handler);
            if (ha == null) {
                return;
            }
            ha.handleRequest(handler, request, response);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    private Object getHandler(HttpServletRequest request) throws Exception {
        // 首先 处理类和请求之间 的映射关系可能存储在不同的地方(HandlerMapping)
        if (handlerMappings != null) {
            for (HandlerMapping hm : handlerMappings) {
                Object handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

    private HandlerAdapter getHandlerAdapter(Object handler) {
        if (handlerAdapters != null) {
            // 遍历策略集合
            for (HandlerAdapter ha : handlerAdapters) {
                if (ha.supports(handler)) {
                    return ha;
                }
            }
        }
        return null;
    }
}

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>com.yw.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

自定义SpringMVC框架V2版本

  • 创建一个工程:springmvc-framework-custom,并引入之前手写的Spring框架:
<!-- 引入自定义的Spring框架 -->
<dependency>
  <groupId>com.yw.spring.framework</groupId>
  <artifactId>spring-framework-custom</artifactId>
  <version>1.0</version>
</dependency>
  • 将V1版本中的处理器映射器、处理器适配器、前端控制器等复制到该工程下,如下图所示:
    在这里插入图片描述

修改自定义Spring框架整合

在这里插入图片描述

  • 新增标记接口:用于BeanFactory容器的注入
public interface Aware {
}
public interface BeanFactoryAware extends Aware {
    void setBeanFactory(BeanFactory beanFactory);
}
  • 定义接口 InitializingBean:实现该接口可以在 依赖注入 与 初始化Bean 之间完成一些事情
public interface InitializingBean {
    void afterPropertiesSet();
}
  • 修改AbstractAutowiredCapableBeanFactory中的initializeBean方法:
public abstract class AbstractAutowiredCapableBeanFactory extends AbstractBeanFactory {
    // 省略...
    
    private void initializeBean(Object bean, BeanDefinition beanDefinition) {
        // 需要针对Aware接口标记的类进行特殊处理
        if (bean instanceof Aware) {
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(this);
            }
        }
        // 可以进行InitializeBean接口的处理
        if (bean instanceof InitializingBean) {
            ((InitializingBean) bean).afterPropertiesSet();
        }
        ReflectUtils.invokeMethod(bean, beanDefinition.getInitMethod());
    }
}
  • 修改 ListableBeanFactory 接口
/**
 * 对于Bean容器中的Bean可以进行集合操作或者说叫批量操作
 */
public interface ListableBeanFactory extends BeanFactory {
    /**
     * 可以根据指定类型获取它或者它实现类的对象
     */
    <T> List<T> getBeansByType(Class type);
}
  • 修改 BeanDefinitionRegistry 接口:新增 getBeanDefinitions 方法
/**
 * 1、实现类是封装了BeanDefinition集合信息
 * 2、接口类是提供对于其封装的BeanDefinition信息进行添加和获取功能
 */
public interface BeanDefinitionRegistry {
    /**
     * 获取BeanDefinition
     */
    BeanDefinition getBeanDefinition(String beanName);

    /**
     * 注册BeanDefinition
     */
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);

    /**
     * 获取BeanDefinition集合
     */
    List<BeanDefinition> getBeanDefinitions();
}
  • DefaultListableBeanFactory 实现 ListableBeanFactory,BeanDefinitionRegistry中的两个方法:
/**
 * 既是spring中的真正管理Bean实例的容器工厂
 * 同时又是管理BeanDefinition的BeanDefinition注册器
 */
public class DefaultListableBeanFactory extends AbstractAutowiredCapableBeanFactory
        implements BeanDefinitionRegistry, ListableBeanFactory {
    /**
     * 存储BeanDefinition的容器
     */
    private Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>(128);

    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return beanDefinitions.get(beanName);
    }

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        beanDefinitions.put(beanName, beanDefinition);
    }

    @Override
    public List<BeanDefinition> getBeanDefinitions() {
        List<BeanDefinition> results = new ArrayList<>();
        for (BeanDefinition bd : beanDefinitions.values()) {
            results.add(bd);
        }
        return results;
    }

    @Override
    public <T> List<T> getBeansByType(Class type) {
        List<T> results = new ArrayList<>();
        // 获取容器中所有的BeanDefinition,遍历每个BeanDefinition,取出来它的类型
        for (BeanDefinition bd : beanDefinitions.values()) {
            Class<?> clazzType = bd.getClazzType();
            // type如果是clazzType的父类型,则返回true
            if (type.isAssignableFrom(clazzType)) {
                results.add((T) getBean(bd.getBeanName()));
            }
        }
        return results;
    }
}

修改处理器映射器

  • BeanNameUrlHandlerMapping 增加实现 InitializingBean 和 BeanFactoryAware 两个接口:体现Spring框架和SpringMVC框架的整合
public class BeanNameUrlHandlerMapping implements HandlerMapping, InitializingBean, BeanFactoryAware {
    private Map<String, Object> urlHandlers = new HashMap<>();

    private DefaultListableBeanFactory beanFactory;

    public BeanNameUrlHandlerMapping() {
    }

    @Override
    public Object getHandler(HttpServletRequest request) throws Exception {
        String uri = request.getRequestURI();

        return this.urlHandlers.get(uri);
    }

    @Override
    public void afterPropertiesSet() {
        List<BeanDefinition> beanDefinitions = beanFactory.getBeanDefinitions();
        for (BeanDefinition bd : beanDefinitions) {
            String beanName = bd.getBeanName();
            if (beanName.startsWith("/")) {
                this.urlHandlers.put(beanName, beanFactory.getBean(beanName));
            }
        }
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }
}

修改前端控制器

  • resources目录下新增 DispatcherServlet.properties 文件:
com.yw.springmvc.framework.mapping.HandlerMapping=com.yw.springmvc.framework.mapping.impl.BeanNameUrlHandlerMapping

com.yw.springmvc.framework.adapter.HandlerAdapter=com.yw.webmvc.framework.adapter.impl.HttpRequestHandlerAdapter,\
  com.yw.springmvc.framework.adapter.impl.SimpleControllerHandlerAdapter
  • 修改DispatcherServlet:整合Spring框架,并从配置文件中加载默认的处理器映射器、处理器适配器等策略
public class DispatcherServlet extends AbstractServlet {
    /**
     * HandlerMapping的策略集合
     */
    private List<HandlerMapping> handlerMappings = new ArrayList<>();
    /**
     * HandlerAdapter的策略集合
     */
    private List<HandlerAdapter> handlerAdapters = new ArrayList<>();

    private DefaultListableBeanFactory beanFactory;

    private static Properties defaultStrategies;

    static {
        try {
            ClasspathResource resource = new ClasspathResource("DispatcherServlet.properties");
            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
//        handlerAdapters.add(new HttpRequestHandlerAdapter());
//        handlerAdapters.add(new SimpleControllerHandlerAdapter());
//
//        handlerMappings.add(new BeanNameUrlHandlerMapping());
//        handlerMappings.add(new SimpleUrlHandlerMapping());
        String location = config.getInitParameter("contextConfigLocation");
        // 初始化spring容器
        initContainer(location);
        // 初始化策略集合
        initStrategies();
    }

    private void initContainer(String location) {
        // 加载spring容器需要的BeanDefinition信息
        beanFactory = new DefaultListableBeanFactory();

        ClasspathResource resource = new ClasspathResource(location);
        InputStream inputStream = resource.getResource();

        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.loadBeanDefinitions(inputStream);

        // 注册默认策略BeanDefinition
        registerDefaultStrategies();

        // 将spring容器中管理的所有单例Bean进行初始化(getBean)
        beanFactory.getBeansByType(Object.class);
    }

    private void registerDefaultStrategies() {
        registerDefaultStrategies(HandlerMapping.class);
        registerDefaultStrategies(HandlerAdapter.class);
    }

    private <T> void registerDefaultStrategies(Class<T> strategyInterface) {
        String key = strategyInterface.getName();
        String value = defaultStrategies.getProperty(key);
        if (value == null) {
            return;
        }
        String[] clazzNames = StringUtils.split(value, ",");
        for (String clazzName : clazzNames) {
            try {
                Class<?> clazzType = Class.forName(clazzName);
                String beanName = clazzType.getSimpleName();
                BeanDefinition beanDefinition = new BeanDefinition(clazzName, beanName);
                beanDefinition.setScope("singleton");
                beanFactory.registerBeanDefinition(beanName, beanDefinition);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }

    private void initStrategies() {
        initHandlerMappings();
        initHandlerAdapters();
    }

    private void initHandlerMappings() {
        handlerMappings = beanFactory.getBeansByType(HandlerMapping.class);
    }

    private void initHandlerAdapters() {
        handlerAdapters = beanFactory.getBeansByType(HandlerAdapter.class);
    }

    // 省略...
}

测试

  • 定义处理器:
public class QueryUserHandler implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/plain;charset=utf-8");
        response.getWriter().write("--- QueryUserHandler V2 ---");
    }
}
public class SaveUserHandler implements SimpleControllerHandler {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/plain;charset=utf-8");
        response.getWriter().write("--- SaveUserHandler V2 ---");
        return null;
    }
}
  • 配置springmvc.xml:
<beans>
  <!-- 配置处理器映射器 -->
  <bean class="com.yw.springmvc.framework.mapping.impl.BeanNameUrlHandlerMapping"/>

  <!-- 配置处理器适配器 -->
  <bean class="com.yw.springmvc.framework.adapter.impl.HttpRequestHandlerAdapter"/>
  <bean class="com.yw.springmvc.framework.adapter.impl.SimpleControllerHandlerAdapter"/>

  <!-- 配置处理器 -->
  <bean name="/queryUser" class="com.yw.springmvc.example.handler.QueryUserHandler" />
  <bean name="/saveUser" class="com.yw.springmvc.example.handler.SaveUserHandler" />
</beans>
  • 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>com.yw.springmvc.framework.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

自定义SpringMVC框架V3版本

自定义注解

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

定义RequestMappingHandlerMapping

public class RequestMappingHandlerMapping implements HandlerMapping, InitializingBean, BeanFactoryAware {
    private Map<String, HandlerMethod> urlHandlers = new HashMap<>();

    private DefaultListableBeanFactory beanFactory;

    @Override
    public Object getHandler(HttpServletRequest request) throws Exception {
        String uri = request.getRequestURI();
        return this.urlHandlers.get(uri);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }

    @Override
    public void afterPropertiesSet() {
        List<BeanDefinition> beanDefinitions = this.beanFactory.getBeanDefinitions();
        for (BeanDefinition bd : beanDefinitions) {
            Class<?> clazzType = bd.getClazzType();
            // 如果类上带有@Controller或者@RequestMapping注解
            if (isHandler(clazzType)) {
                RequestMapping classMapping = clazzType.getAnnotation(RequestMapping.class);
                String classUrl = classMapping.value();

                Method[] methods = clazzType.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.isAnnotationPresent(RequestMapping.class)) {
                        // 建立URL和HandlerMethod对象的映射关系

                        StringBuilder sb = new StringBuilder();
                        if (!classUrl.startsWith("/")) {
                            sb.append("/");
                        }
                        sb.append(classUrl);

                        RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);
                        String methodUrl = methodMapping.value();
                        if (!methodUrl.startsWith("/")) {
                            sb.append("/");
                        }
                        sb.append(methodUrl);

                        // 获取HandlerMethod
                        HandlerMethod hm = new HandlerMethod(beanFactory.getBean(bd.getBeanName()), method);
                        this.urlHandlers.put(sb.toString(), hm);
                    }
                }
            }
        }
    }

    private boolean isHandler(Class<?> clazzType) {
        return (clazzType.isAnnotationPresent(Controller.class)
                || clazzType.isAnnotationPresent(RequestMapping.class));
    }
}

定义RequestMappingHandlerAdapter

public class RequestMappingHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return (handler instanceof HandlerMethod);
    }

    @Override
    public ModelAndView handleRequest(Object handler, HttpServletRequest request, HttpServletResponse response) throws Exception {
        HandlerMethod hm = (HandlerMethod) handler;
        Object controller = hm.getController();
        Method method = hm.getMethod();

        // 处理请求参数
        Object[] args = handleParameters(request, method);

        // 通过反射调用方法
        Object returnValue = method.invoke(controller, args);

        // 处理返回值
        handleReturnValue(returnValue, response);

        return null;
    }

    private Object[] handleParameters(HttpServletRequest request, Method method) {
        List<Object> args = new ArrayList<>();

        // 请求参数KV集合
        Map<String, String[]> parameterMap = request.getParameterMap();

        // 方法参数数组
        Parameter[] parameters = method.getParameters();
        for (Parameter parameter : parameters) {
            // 取出参数名称(需要特殊处理,否则获取到的就是arg0,arg1这样的参数名称)
            String name = parameter.getName();
            Class<?> type = parameter.getType();
            // 方法参数名称一定要和请求的Key保持一致
            String[] strings = parameterMap.get(name);
            Object valueToUse = resolveValue(strings, type);
            args.add(valueToUse);
        }
        return args.toArray();
    }

    private Object resolveValue(String[] strings, Class<?> type) {
        if (type == Integer.class) {
            return Integer.parseInt(strings[0]);
        } else if (type == String.class) {
            return strings[0];
        }
        return null;
    }

    private void handleReturnValue(Object value, HttpServletResponse response) throws Exception {
        if (value instanceof String) {
            response.setContentType("text/plain;charset=utf-8");
            response.getWriter().write(value.toString());
        } else if (value instanceof Map) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JsonUtils.object2Json(value));
        }
    }
}

DispatcherServlet.properties新增配置

com.yw.springmvc.framework.mapping.HandlerMapping=com.yw.springmvc.framework.mapping.impl.BeanNameUrlHandlerMapping,\
  com.yw.springmvc.framework.mapping.impl.RequestMappingHandlerMapping

com.yw.springmvc.framework.adapter.HandlerAdapter=com.yw.webmvc.framework.adapter.impl.HttpRequestHandlerAdapter,\
  com.yw.springmvc.framework.adapter.impl.SimpleControllerHandlerAdapter,\
  com.yw.springmvc.framework.adapter.impl.RequestMappingHandlerAdapter

测试

  • 定义控制器:
/**
 * 注意:
 * SpringMvc中的处理器在该类中到底指的是谁?
 * 是Controller类呢?还是其他的?
 * 真正的处理器是Controller中的某个使用RequestMapping注解标记的方法
 * 也就是Controller对象+Method对象==> HandlerMethod对象(真正的处理器)
 */
@Controller
@RequestMapping("user")
public class UserController {

    @RequestMapping("query")
    @ResponseBody
    public Map<String, Object> query(Integer id, String name) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("id", id);
        map.put("name", name);
        return map;
    }

    @RequestMapping("save")
    @ResponseBody
    public String save() {
        return "OK";
    }
}

代码实现github地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
开课吧-javaEE企业级分布式高级架构师是一门专注于培养企业级应用开发的高级技术课程。该课程旨在帮助学员全面掌握Java EE企业级开发的技能和知识,培养他们成为具备分布式应用系统设计和架构能力的高级架构师。 在这门课程中,学员将学习Java EE的核心概念和技术,包括Servlet、JSP、JDBC、EJB、JNDI等。同时,学员还将深入学习分布式应用开发的相关技术,如Web服务、消息队列、分布式缓存、负载均衡等。除此之外,课程还将涉及如何使用流行的Java EE开发框架(如Spring、Hibernate等)进行企业应用开发,并介绍分布式系统的设计原则和最佳实践。 通过学习这门课程,学员将能够了解分布式应用架构的基本原理,并具备设计和构建分布式应用系统的能力。他们将熟练掌握Java EE平台的各种技术和工具,能够灵活运用它们开发高性能、可扩展性强的企业级应用系统。此外,通过课程中的实战项目,学员还将锻炼解决实际问题和项目管理的能力。 作为一门高级架构师的课程,它将帮助学员进一步提升自己的职业发展。毕业后,学员可以在企业中担任分布式应用的架构师、系统设计师、技术经理等角色,负责企业级应用系统的设计和开发。此外,他们还可以选择独立开发,提供技术咨询和解决方案。 总之,开课吧-javaEE企业级分布式高级架构师是一门非常有价值的课程,它将帮助学员掌握Java EE企业级开发的核心技术和分布式应用架构的设计原理,培养他们成为具备高级架构师能力的软件开发专业人士。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

讲文明的喜羊羊拒绝pua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值