spring-web 网络开发

前言

springmvc是做为一个web开发的基础.负责web容器与spring容器的桥接工作。

相关配置

通过在DispatcherServlet配置关联2容器。

public class SpringWebTest {

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        ServletContextHandler servletHandler = new ServletContextHandler();
        server.setHandler(servletHandler);
        loadDispatcherServlet(servletHandler);
        configContext(servletHandler);
        server.start();
        server.join();
    }

    // 加载DispatcherServlet,并指定spring容器加载路径
    private static void loadDispatcherServlet(ServletContextHandler handler){
        ServletHolder holder = new ServletHolder(Source.EMBEDDED);
        holder.setHeldClass(DispatcherServlet.class);
        holder.setInitParameter("contextConfigLocation", "classpath:spring-web.xml");
        holder.setInitOrder(1);
        handler.addServlet(holder, "/");
    }

    // 监听器加载父容器
    // Listener的加载优先于Servlet
    private static void configContext(ServletContextHandler handler){
        //handler.setInitParameter("contextConfigLocation", "classpath:spring-web.xml");
        //handler.addEventListener(new ContextLoaderListener());
    }
}

public class HelloController implements Controller, View, ViewResolver {

    @Nullable
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("hello");
        mav.getModel().put("msg", "eeeeeeee");
        return mav;
    }

    @Nullable
    public String getContentType() {
        return null;
    }

    public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        ServletOutputStream stream = response.getOutputStream();
        Object value = model.get("msg");
        stream.write(value.toString().getBytes());
        stream.flush();
    }

    @Nullable
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        return this;
    }
}
    <bean id="userController" class="controller.HelloController"></bean>

    <bean name="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="order" value="1"/>
        <property name="mappings">
            <props>
                <prop key="user.do">userController</prop>
            </props>
        </property>
    </bean>

    <bean id="viewresolver" class="controller.HelloController">
    </bean>

Sevlet简述

在《Jetty概述》一文中简述了Servlet容器的概念,具体可参考《servlet规范》。下面进行部分介绍。

web配置文件

做为ServletContex的配置文件,协助加载组件,其顺序

context-param -> listener -> filter -> servlet

ServletConfig

Servlet容器的配置

 public interface ServletConfig {
    
    // 容器名称,对应web.xml display-name
    public String getServletName();
    
    // 获取容器实例
    public ServletContext getServletContext();
    
    // 容器初始化参数,对应web.xml context-param
    public String getInitParameter(String name);
}
ServletContext

容器实例,提供一些工具性的方法及组件

public interface ServletContext {

    // 当前容器对应请求的主路径
    public String getContextPath();

    // 根据uripath获取容器
    public ServletContext getContext(String uripath);
    
    // 根据路径查找文件,例如
    // /welcome.html, /WEB-INF/web.xml  
    public Set<String> getResourcePaths(String path);
    
    // 获取path转发器,使用forward方法进行容器内转发
    public RequestDispatcher getRequestDispatcher(String path);

    // 获取通过web.xml注册的Servlet
    public Servlet getServlet(String name) throws ServletException;
    
    // 获取服务器上的工作路径 + path
    public String getRealPath(String path);
    
    // 获取web容器的版本
    public String getServerInfo();
    
    // 获取通过web.xml context-param
    public String getInitParameter(String name);

    // 手动设置 context-param
    public boolean setInitParameter(String name, String value);

    // 获取 context中暂存的对象,相当于map.get
    public Object getAttribute(String name);
    
    // 手工设置 context中暂存的对象。 相当于map.set
    public void setAttribute(String name, Object object);
     
    // 容器名称,对应web.xml display-name
    public String getServletContextName();

    // 增加监听器
    public void addListener(String className);

    // 添加过滤器
    public FilterRegistration.Dynamic addFilter(String filterName, String className);

    // session的配置,具体要关注web容器
    public SessionCookieConfig getSessionCookieConfig();
}
Servlet

具体的请求处理控制单元
在这里插入图片描述

/* Servlet的抽象实现类
 * @see 	GenericServlet  提供获取ServletConfig信息一的些访求
 * @see 	HttpServlet     把service根据请求头拆分成 get,post,put... 遵守rest规范
 */  
public interface Servlet {
    // init()初始化阶段
    // config 参应web.xml  servlet init-param
    public void init(ServletConfig config) throws ServletException;
    
    // 客户端请求阶段
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

    // 终止阶段
    public void destroy();
}

web容器

对 spring 容器进行扩充打通 Servlet容器

存放于spring-web包中,spring-web 类似于spring-context, 主要架负责桥接web方面的组件
在这里插入图片描述

WebApplicationContext

两容器相互映射的名称接口

public interface WebApplicationContext  {

    // 把父亲spring容器存放在servlet容器中的Bean名称
	// @see org.springframework.web.context.support.WebApplicationContextUtils#getWebApplicationContext
	// @see org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext
	// @see ContextLoaderListener
	String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

    // 向 spring 容器注册名为 “request” 的 RequestScope
    // RequestScope 的功能是把 Request 作用域的bean 引向 httpServletRequest.setAttribute
	// @see WebApplicationContextUtils.registerWebApplicationScopes
	String SCOPE_REQUEST = "request";

	// 向 spring 容器注册名为 "session" 的 SessionScope
    // SessionScope 的功能是把 Session 作用域的bean 引向 httpServletSession.setAttribute
	// @see WebApplicationContextUtils.registerWebApplicationScopes
	String SCOPE_SESSION = "session";

	// 向 spring 容器注册名为 "application" 的 ServletContextScope
    // ServletContextScope 的功能是把 Application 作用域的bean 引向 ServletContext.setAttribute
	// @see WebApplicationContextUtils.registerWebApplicationScopes
	String SCOPE_APPLICATION = "application";

	// 把servlet容器存入在 spring容器中的Bean名称
	// @see WebApplicationContextUtils.registerEnvironmentBeans
	String SERVLET_CONTEXT_BEAN_NAME = "servletContext";

	// 把web.xml context-param 转成Map存入在spring容器中的Bean名称
	// @see WebApplicationContextUtils.registerEnvironmentBeans
	String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";

	// 把ServletContext attribute 转成Map存入在spring容器中的Bean名称
	// @see WebApplicationContextUtils.registerEnvironmentBeans
	String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";

	// 获取servlet容器
	ServletContext getServletContext();
}
ConfigurableWebApplicationContext

扩展WebApplicationContext,并提供配置接口

public interface ConfigurableWebApplicationContext {

	// web.xml display-name + 此前缀 为 spring 容器的名字
	String APPLICATION_CONTEXT_ID_PREFIX = WebApplicationContext.class.getName() + ":";

	// 把servletConfig存入在 spring容器中的Bean名称
	// @see WebApplicationContextUtils.registerEnvironmentBeans
	String SERVLET_CONFIG_BEAN_NAME = "servletConfig";

	// 获取 spring配置文件目录
	String[] getConfigLocations();
}public abstract class AbstractRefreshableWebApplicationContext  {

	// servlet容器配置
	private ServletContext servletContext;

	// servlet容器配置
	private ServletConfig servletConfig;

	// 主题,类似于MessageSource, 用切换css样式
	private ThemeSource themeSource;

	// 注入spring-context postProcessBeanFactory流程
	// 通过 ServletContextAwareProcessor 向 ServletContextAware, ServletConfigAware 注入相当对象
	// 向spring容器注入Scope 例如 request, session , apllication
	// 向spring容器注入servlet环境, servletConfig,ServletContext
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);

	// 注入spring-context, onRefresh流程
    // 设置默认主题处理
	protected void onRefresh();

	// 注入spring-context, oprepareRefresh流程
    // 把 servletConfig,ServletContext 放到spring Environment环境中
	protected void initPropertySources(); 
}
AbstractRefreshableWebApplicationContext

对spring context 初始化流程做 servlet 容器设置

public abstract class AbstractRefreshableWebApplicationContext  {
	// servlet容器配置
	private ServletContext servletContext;

	// servlet容器配置
	private ServletConfig servletConfig;

	// 主题,类似于MessageSource, 用切换css样式
	private ThemeSource themeSource;

	// 注入spring-context postProcessBeanFactory流程
	// 通过 ServletContextAwareProcessor 向 ServletContextAware, ServletConfigAware 注入相当对象
	// 向spring容器注入Scope 例如 request, session , apllication
	// 向spring容器注入servlet环境, servletConfig,ServletContext
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);

	// 注入spring-context, onRefresh流程
    // 设置默认主题处理
	protected void onRefresh();

	// 注入spring-context, oprepareRefresh流程
    // 把 servletConfig,ServletContext 放到spring Environment环境中
	protected void initPropertySources(); 
}

Webmvc

spring 不容器 servlet的请求控制方式,按MVC模型Servlet基础上结合spring容器进行扩展

存放于spring-webmvc包中,专注于mvc模式部分,依赖于 spring-web打通servlet容器和spring容器.

Jetty Demo

Jetty概述》介绍jetty-webapp内容。网上Demo都是依赖webapp的web.xml方式。笔者为了少加一个包,现在采用直接依赖jetty-servlet的方式创建。

public class SpringWebTest {

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        ServletContextHandler servletHandler = new ServletContextHandler();
        server.setHandler(servletHandler);
        loadDispatcherServlet(servletHandler);
        configContext(servletHandler);
        server.start();
        server.join();
    }

    // 加载DispatcherServlet,并指定spring容器加载路径
    private static void loadDispatcherServlet(ServletContextHandler handler){
        ServletHolder holder = new ServletHolder(Source.EMBEDDED);
        holder.setHeldClass(DispatcherServlet.class);
        holder.setInitParameter("contextConfigLocation", "classpath:spring-web.xml");
        holder.setInitOrder(1);
        handler.addServlet(holder, "/");
    }

    // 监听器加载父容器
    // Listener的加载优先于Servlet
    // 2容器易于service层和controller层分离
    private static void configContext(ServletContextHandler handler){
        //handler.setInitParameter("contextConfigLocation", "classpath:spring-parent.xml");
        //handler.addEventListener(new ContextLoaderListener());
    }
}

DispatcherServlet

mvc的核心servlet
在这里插入图片描述

HttpServletBean

负责接入Servlet生命周期

public abstract class HttpServletBean  {
    // DispatcherServlet 实现 init 周期
    // 1. 把 ServletConfig 接入到 Environment
    // 2. 抽象出 initServletBean 让子类扩展
	public final void init() throws ServletException;
}
FrameworkServlet

结合Servlet生命周期关联容器

public abstract class FrameworkServlet {

	// 默认加载的spring 容器类
	public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;

	// 把spring容器存放在servlet容器中的Bean名称前缀
	public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";

	// 把spring容器存放在servlet容器中的Bean名称
	private String contextAttribute;

	// 默认加载的spring 容器类
	private Class<?> contextClass = DEFAULT_CONTEXT_CLASS;

    // 配置文件 spring-web.xml 的路径
	private String contextConfigLocation;

    // spring容器初始化后切入逻辑类
	private final List<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
			new ArrayList<>();

	// 字符串ApplicationContextInitializer类名,以,分割。最终入contextInitializers
	private String contextInitializerClasses;

	// 是否将 spring 容器 push到servlet context
	private boolean publishContext = true;

    // 每个请求进来是不当做Event事件进行push
    // @see publishRequestHandledEvent
	private boolean publishEvents = true;

    // 是否把请求中的 Locale RequestAttributes 放在上下文中爆露
    // @see initContextHolders
	private boolean threadContextInheritable = false;

    // 是否将 option的请求,转发到service处理
    // @see doOptions
	private boolean dispatchOptionsRequest = false;

	// 是否将 trace的请求,转发到service处理
    // @see doTrace
	private boolean dispatchTraceRequest = false;

    // 是否打印请求明细
    // @see logResult
	private boolean enableLoggingRequestDetails = false;

	// spring 容器
	private WebApplicationContext webApplicationContext;

    // 实现HttpServletBean的切口
    // 1. 通过 initWebApplicationContext 初始还容器
    // 2. 抽象出 initFrameworkServlet 让子类扩展
	protected final void initServletBean() throws ServletException;

    // 初始化spring容器
    // 1. 通过 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 拿到父亲容器
    // 2. 创建容器Refresh 设置父亲容器
    // 3. 设置容器进 ServletContext 以 contextAttribute 为名
    // @see configureAndRefreshWebApplicationContext
	protected WebApplicationContext initWebApplicationContext();

    // 把httpServlet 中的 doput dopost,导向 doService方法中
    // 1. 设置请求上下文对象
    // 2. 是否异步处理
    // 3. 日志处理
	protected final void processRequest(HttpServletRequest request, HttpServletResponse response);
}
DispatcherServlet

专注MVC流程设计

public class DispatcherServlet  {

    // spring容器在 request的名字
	public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT";

    // MultipartResolver在容器中的名字    
	public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";

    // multipart类型http请求,multipartl转为正常的HttpServletRequest
    // @see checkMultipart   
	private MultipartResolver multipartResolver;

    // LocaleResolver在容器中的名字    
	public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";

    // LocaleResolver 在 request中的名字
	public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER";

    // 从request中取出请求地区,放入上下文
    // @see buildLocaleContext
	private LocaleResolver localeResolver;

    // themeResolver在容器中的名字    
	public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";

    // themeResolver 在 request中的名字
	public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_RESOLVER";

    // ThemeSource 在 request中的名字
	public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_SOURCE";

    // 从request中取出主题请求,放入上下文
    // @see buildLocaleContext
	private ThemeResolver themeResolver;

	// handlerMappings在容器中的名字    
	public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";

    // 路径和执行器的关系维护
    // @see getHandler
    private List<HandlerMapping> handlerMappings;

    // handlerAdapter在容器中的名字    
	public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
    
    // 为HandlerMapping中执行器,统一执行方式,返回model
    // @see getHandlerAdapter
    private List<HandlerAdapter> handlerAdapters;


	// handlerExceptionResolver在容器中的名字    
	public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";

    // 执行异常在request中的名字
	public static final String EXCEPTION_ATTRIBUTE = DispatcherServlet.class.getName() + ".EXCEPTION";

    
    // 解决执行器出来的异常
    // @see processHandlerException
    private List<HandlerExceptionResolver> handlerExceptionResolvers;

	// RequestToViewNameTranslator在容器中的名字    
    public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";

    // viewResolver在容器中的名字    
	public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
    
    // 根据执行器返回的model 使用策略转到view
    // @see resolveViewName
	private List<ViewResolver> viewResolvers;

    // 默认返回视图
    // @see getDefaultViewName
	private RequestToViewNameTranslator viewNameTranslator;

    // flashMapManager在容器中的名字    
	public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager";

    // flashMapManager 在 request中的名字
	public static final String FLASH_MAP_MANAGER_ATTRIBUTE = DispatcherServlet.class.getName() + ".FLASH_MAP_MANAGER";


    // 输入的(转发前)的 FlashMap 在 request的名字
	public static final String INPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".INPUT_FLASH_MAP";

    // 要转发 的 FlashMap 在 request的名字
	public static final String OUTPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP";


    // 解决Redirect参数保存问题,利用session的方式保存,转前存,存后取出
    // @see doService
    private FlashMapManager flashMapManager;

    // 以上组件的默认的配置文件名
    private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";

    // 以上组件的默认配置的内存映射
    // @see getDefaultStrategies
    private static final Properties defaultStrategies;

    // 直接根据类型从容器中取HandlerMappings,不走 HANDLER_MAPPING_BEAN_NAME
	private boolean detectAllHandlerMappings = true;

    // 直接根据类型从容器中取HandlerAdapter,不走 HANDLER_ADAPTER_BEAN_NAME
	private boolean detectAllHandlerAdapters = true;

    // 直接根据类型从容器中取ExceptionResolver,不走 HANDLER_EXCEPTION_RESOLVER_BEAN_NAME
	private boolean detectAllHandlerExceptionResolvers = true;

    // 直接根据类型从容器中取ViewResolver,不走 VIEW_RESOLVER_BEAN_NAME
	private boolean detectAllViewResolvers = true;

    // 页面没找到以异常的方式,不返回404
    // @see noHandlerFound
	private boolean throwExceptionIfNoHandlerFound = false;
}

SpringMVC运行原理

以逻辑图,简述其运行流程

在这里插入图片描述
流程说明:

  1. 客户端(浏览器)发送请求,直接请求到DispatcherServlet。
  2. DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。
  3. 解析到对应的Handler后,开始由HandlerAdapter适配器处理。
  4. HandlerAdapter会根据Handler来调用真正的处理器开处理请求,并处理相应的业务逻辑。
  5. 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View。
  6. ViewResolver会根据逻辑View查找实际的View。
  7. DispaterServlet把返回的Model传给View。
  8. 通过View返回给请求者(浏览器)

主要参考

SpringMVC实现原理及详解

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要下载spring-boot-maven-plugin 2.1.3的jar文件,可以按照以下步骤进行。 首先,打开Maven中央仓库的网站(https://mvnrepository.com/),在搜索框中输入"spring-boot-maven-plugin",然后点击搜索按钮。 在搜索结果页面上,找到版本号为2.1.3的spring-boot-maven-plugin。点击该版本号的链接,进入该版本的详细信息页面。 在详细信息页面中,可以找到该版本的jar文件下载链接。点击下载链接,将jar文件保存到本地计算机。 注意,在下载jar文件之前,请确保已经安装了Maven构建工具以及配置了相应的仓库地址。此外,还要注意根据你的项目需求,选择适合的Maven版本和spring-boot-maven-plugin的正确版本进行下载。 完成以上步骤后,你就成功地下载了spring-boot-maven-plugin 2.1.3的jar文件。你可以将该jar文件导入到你的项目中,然后使用相应的插件功能。 ### 回答2: 要下载spring-boot-maven-plugin2.1.3.jar文件,可以按照以下步骤进行操作: 1. 首先,在你的项目的pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.1.3.RELEASE</version> </dependency> ``` 这会告诉Maven在构建过程中使用该插件。 2. 接下来,可以使用Maven的命令行工具或者集成开发环境(IDE)中的Maven插件来下载该插件。 - 在命令行中,可以使用以下命令下载插件: ```shell mvn dependency:copy -Dartifact=org.springframework.boot:spring-boot-maven-plugin:2.1.3.RELEASE:jar -DoutputDirectory=/path/to/output/directory ``` 其中,`/path/to/output/directory`是你希望将该插件保存的目录路径。 - 在IDE中,可以在项目的Maven视图或者依赖管理视图中找到`spring-boot-maven-plugin`依赖项,右击该依赖并选择"Download"或者"Copy"选项,将插件下载到指定的目录路径中。 3. 下载完成后,你可以在指定的目录路径中找到`spring-boot-maven-plugin-2.1.3.jar`文件。 请注意,下载的插件的版本需要与你在pom.xml文件中指定的版本一致,否则可能会导致兼容性问题。 ### 回答3: 要下载spring-boot-maven-plugin2.1.3.jar文件,您可以按照以下步骤进行操作: 1. 首先,打开您的Web浏览器,并导航到https://search.maven.org/网站。 2. 在搜索框中输入“spring-boot-maven-plugin”,然后点击搜索按钮。 3. 在搜索结果中找到与版本2.1.3相匹配的spring-boot-maven-plugin。请确保选择了正确的版本。 4. 单击该版本的链接,然后进入该版本的页面。 5. 在此页面上,您将看到“Download”按钮。单击该按钮以开始下载jar文件。 6. 单击“Download”按钮后,浏览器将提示您选择保存文件的位置。选择合适的位置,并单击“保存”。 7. 等待下载完成。下载速度取决于您的网络连接速度以及服务器的响应速度。 8. 下载完成后,您将在您选择保存的位置找到该jar文件。 现在,您已经成功地下载了spring-boot-maven-plugin2.1.3.jar文件。您可以将此jar文件用于您的项目中,根据您的需要进行配置和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值