手写框架篇
需求分析
* 查询用户:请求URL http://localhost/queryUser
* 添加用户:请求URL http://localhost/savaUser
- 问题:如果按照常规Servlet开发习惯,一个类只会处理一个请求。
- 解决方案:自定义Servlet extends BaseServlet(公共的Servlet)
BaseServlet{
doPost(){
}
}
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;
}
public class BeanNameUrlHandlerMapping implements HandlerMapping {
private Map<String, Object> urlHandlers = new HashMap<>();
public BeanNameUrlHandlerMapping() {
this.urlHandlers.put("/queryUser", new QueryUserHandler());
}
@Override
public Object getHandler(HttpServletRequest request) throws Exception {
String uri = request.getRequestURI();
return this.urlHandlers.get(uri);
}
}
public class SimpleUrlHandlerMapping implements HandlerMapping {
private Map<String, Object> urlHandlers = new HashMap<>();
public SimpleUrlHandlerMapping() {
this.urlHandlers.put("/saveUser", new SaveUserHandler());
}
@Override
public Object getHandler(HttpServletRequest request) throws Exception {
String uri = request.getRequestURI();
return this.urlHandlers.get(uri);
}
}
定义处理器适配器
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);
}
}
定义前端控制器
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;
}
public class DispatcherServlet extends AbstractServlet {
private List<HandlerMapping> handlerMappings = new ArrayList<>();
private List<HandlerAdapter> handlerAdapters = new ArrayList<>();
@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 {
Object handler = getHandler(request);
if (handler == null) {
return;
}
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 {
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框架:
<dependency>
<groupId>com.yw.spring.framework</groupId>
<artifactId>spring-framework-custom</artifactId>
<version>1.0</version>
</dependency>
- 将V1版本中的处理器映射器、处理器适配器、前端控制器等复制到该工程下,如下图所示:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5cd311214b417bc02eca56d2f220e7a1.png)
修改自定义Spring框架整合
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d3e696e2c360584c5e78c281279d990d.png)
- 新增标记接口:用于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) {
if (bean instanceof Aware) {
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
}
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
ReflectUtils.invokeMethod(bean, beanDefinition.getInitMethod());
}
}
- 修改 ListableBeanFactory 接口
public interface ListableBeanFactory extends BeanFactory {
<T> List<T> getBeansByType(Class type);
}
- 修改 BeanDefinitionRegistry 接口:新增 getBeanDefinitions 方法
public interface BeanDefinitionRegistry {
BeanDefinition getBeanDefinition(String beanName);
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
List<BeanDefinition> getBeanDefinitions();
}
- DefaultListableBeanFactory 实现 ListableBeanFactory,BeanDefinitionRegistry中的两个方法:
public class DefaultListableBeanFactory extends AbstractAutowiredCapableBeanFactory
implements BeanDefinitionRegistry, ListableBeanFactory {
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<>();
for (BeanDefinition bd : beanDefinitions.values()) {
Class<?> clazzType = bd.getClazzType();
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 {
private List<HandlerMapping> handlerMappings = new ArrayList<>();
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 {
String location = config.getInitParameter("contextConfigLocation");
initContainer(location);
initStrategies();
}
private void initContainer(String location) {
beanFactory = new DefaultListableBeanFactory();
ClasspathResource resource = new ClasspathResource(location);
InputStream inputStream = resource.getResource();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.loadBeanDefinitions(inputStream);
registerDefaultStrategies();
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;
}
}
<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>
<?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();
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)) {
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 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<>();
Map<String, String[]> parameterMap = request.getParameterMap();
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
String name = parameter.getName();
Class<?> type = parameter.getType();
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
测试
@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地址