无xml创建web工程和java的SPI机制

一.java的SPI机制

1.java提供的一套用来被第三方实现或扩展的接口,SPI的作用就是为这些被扩展的接口寻找实现类

2.SPI的实现

1)创建两个类,实现接口

1.MianTiao.java

package com.hhh.spi.impl;

import com.hhh.spi.IEat;

public class MianTiao  implements IEat {
    @Override
    public void eat() {
        System.out.println("chi miantiao");
    }
}

2)MiFan.java

package com.hhh.spi.impl;

import com.hhh.spi.IEat;

public class MiFan implements IEat {
    @Override
    public void eat() {
        System.out.println("chi mifan");
    }
}

2)创建接口

3)在resource下创建文件夹:META-INF/services,在其文件夹下创建以接口全路径命名的文件,文件中写接口的实现类的全路径

4)新建测试类,使用ServiceLoader.load加载实现类

 5)运行程序,查看效果

 二.无xml创建web工程

1.ServletContainerInitializer接口的作用

web容器启动的时候,会利用SPI机制在classpath下的META-INF/services/javax..servlet.ServletContainerInitializer这个文件找到工程中的此接口实现类,并执行onStartup方法

2.在pom文件中添加依赖


    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <!--这个依赖只在编译阶段有效-->
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-core</artifactId>
      <version>7.0.47</version>
    </dependency>

2.新建ServletContainerInitializer实现类WebServletContainerInitializer.java

package com.hhh.config;


import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.Set;

public class WebServletContainerInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {

        System.out.println("this is run");
    }
}

3.在META-INF/service目录下新建以ServletContainerInitializer接口全路径命名的一个文件,其内容为实现类的全路径,如图所示

 4.配置tomcat,运行tomcat,查看效果

三.配置servlet和filter(失败)

1.新建一个servlet的包,用来配置servlet

在onStartup方法中注册servlet,filter等,使用ServletContext这个方法参数

1.新建MyServlet.java类,继承接口HttpServlet

package com.hhh.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("my servlet");
    }
}

2.在WebServletContainerInitializer.java类中注册servlet

(我报红了,有错误,先放着)

package com.hhh.config;

import com.hhh.servlet.MyServlet;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import java.util.Set;

//ServletRegistration
public class WebServletContainerInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {

        System.out.println("this is run");

        ServletRegistration.Dynamic dynamic=  servletContext.getClass("my",MyServlet.class);

        dynamic.addMapping("/my");
    }
}

3.运行程序,查看效果

1.新建一个filter的包,用来配置filter

1.新建MyFilter.java类,继承接口HttpServlet

package com.hhh.filter;

import javax.servlet.*;
import java.io.IOException;

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter before");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("filter after");
    }

    @Override
    public void destroy() {

    }
}

2.在WebServletContainerInitializer.java类中注册filter(代码报红,注释了)

package com.hhh.config;

import com.hhh.filter.MyFilter;
import com.hhh.servlet.MyServlet;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import java.util.Set;


import javax.servlet.*;
import java.util.EnumSet;
import java.util.Set;



//ServletRegistration
public class WebServletContainerInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {

        System.out.println("this is run");

        //注册servlet
      //      ServletRegistration.Dynamic dynamic=  servletContext.addServlet("my",MyServlet.class);

        //    dynamic.addMapping("/my");
//
        //注册filter
     //        FilterRegistration.Dynamic myFilter= servletContext.addFilter("MyFilter", MyFilter.class);
      //       myFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),true,"my");
    }
}

四.无xml配置springmvc的原理

spring提供了一个org.springframework.web.SpringServletContainerInitializzer,也是利用了spi机制。

1.@HandlesTypes(WebApplicationInitializer.class)这个注解的作用

导入项目中的WebApplicationInitializer的实现类,放到SpringServletContainerInitializer类中的InStartip方法的参数1中,参数1是一个set集合。(参数2可用来注册Servlet)

2.SpringServletContainerInitializer的onStartup方法

//onStartup方法原理
                            //webAppInitializerClasses:这是class文件
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
    
        //这个集合里头要放对象
        List<WebApplicationInitializer> initializers = new LinkedList();
        Iterator var4;
        if (webAppInitializerClasses != null) {
            var4 = webAppInitializerClasses.iterator();

            while(var4.hasNext()) {
                Class<?> waiClass = (Class)var4.next();
                //判断class文件不是抽象类不是接口
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
        //创建class的实例并放入集合                     initializers.add((WebApplicationInitializer)waiClass.newInstance());
                    } catch (Throwable var7) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
        } else {
            AnnotationAwareOrderComparator.sort(initializers);
            servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);
            var4 = initializers.iterator();

            执行实例的onStartip方法
            while(var4.hasNext()) {
                WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
                initializer.onStartup(servletContext);
            }

        }
    }

先判断set集合中的实现类是否都可以,然后这个接口会循环实现类的onStartup方法

3.在包config中新建一个配置类为AppIniConfig.java,继承某抽象类,实现各类方法

package com.hhh.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override

    //读取spring的配置类——对应ApplicationContext
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    //指定springmvc的配置类——springmvc.xml
    protected Class<?>[] getServletConfigClasses() {

        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    //指定前端控制器的拦截路径
    protected String[] getServletMappings() {
        //拦截所有路径
        return new String[]{"/"};
    }
}

4.去使用这个配置类,在config包中新建一个springmvc的配置类为SpringMvcConfig.java,而后新建controller包,在该类指定扫描路径

package com.hhh.config;
//springvc的配置类

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration   //注解——这个类为表示为配置类
//指定扫描路径
@ComponentScan("com.hhh.controller")
public class SpringMvcConfig {
    
}

5.在controller包内新建一个类用来测试HelloController.java

package com.hhh.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
//映射路径
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping("/test1")
    @ResponseBody
    public String test1(){
        return "test1";
        //这个字符串会返回到前端
    }
}

6.启动tomcat,运行程序查看效果

 7.在webapp下放一个静态资源

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>First</title>
</head>
<body>
<h1>First</h1>
</body>
</html>

8.在SpringMvcConfig.java配置类中去处理静态资源

1.加注解:@EnableWebMvc

2.实现addResourceHandlers方法

package com.hhh.config;
//springvc的配置类

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;

import java.util.List;

@Configuration   //注解——这个类为表示为配置类
//指定扫描路径
@ComponentScan("com.hhh.controller")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry formatterRegistry) {

    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> list) {

    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> list) {

    }

    @Override
    public Validator getValidator() {
        return null;
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer contentNegotiationConfigurer) {

    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) {

    }

    @Override
    public void configurePathMatch(PathMatchConfigurer pathMatchConfigurer) {

    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) {

    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) {

    }

    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {

    }

    @Override
    public void addInterceptors(InterceptorRegistry interceptorRegistry) {

    }

    @Override
    public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }

    @Override
    public void addViewControllers(ViewControllerRegistry viewControllerRegistry) {

    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {

    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {
      //静态资源处理方式的添加
        resourceHandlerRegistry.addResourceHandler("/html/*").addResourceLocations("/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) {

    }

    @Override
    public void addCorsMappings(CorsRegistry corsRegistry) {

    }
}

9.启动tomcat,运行程序,查看效果

五.无xmlWeb工程整合MyBatis——整合的本质还是在spring中配置MyBatis,包括以下步骤

1.新建domain,新建Manager类,其中的属性要依据数据表manager1中的字段一一对应

package com.hhh.domain;

public class Manager {
    private  String id;
    private  String name;

//无参的构造方法
    public Manager(){

    }

    public Manager(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Manager{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

2.新建dao包,新建接口ManagerDao.java

package com.hhh.dao;

import com.hhh.domain.Manager;

import java.util.List;

public interface ManagerDao {
    public List<Manager> findAll();

    public void insert(Manager manager);

    public void delete(String id);
}

3.在四步骤中已经配置完springmvc ,接下来配置spring。在config包下新建一个类配置spring:SpringConig.java

package com.hhh.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

import javax.sql.DataSource;

@Configuration   //表示此类为配置类
@ComponentScan(basePackages ="com.hhh",
        excludeFilters =@ComponentScan.Filter(type = FilterType.ANNOTATION,value = Controller.class))
//扫描除了controller之外的注解,basePackages指定基本的扫描路径, excludeFilters指定不扫描的路径,里面type为基于注解去排除

//3.配置MapperFactoryBean或者配置自动扫描dao层接口
@MapperScan("com.hhh.dao")


public class SpringConfig {
    //记得去AppInitConfig类中添加需要读取的spring配置类
    //配置bean

    //1.配置连接池dataSource
    @Bean
    public DataSource dataSource(){
        //创建DataSource,在pom文件导入数据库连接池的包
        DruidDataSource dataSource=new DruidDataSource();
        //ssmframe为数据库的数据库名
        dataSource.setUrl("jdbc:mysql://localhost:3306/ssmframe");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUsername("root");
        dataSource.setPassword("hyt123456");
        return dataSource;

    }

    //2.配置sqlSessionFactory
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(){
        SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        return sqlSessionFactoryBean;

    }



    //

}

这里有一个注意点,需要在AppInitConfig类中添加需要读取的spring配置类

4.在resource目录下新建一层和dao层一样的文件夹,在dao目录下新建一个ManagerDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hhh.dao.ManagerDao">
    <select id="findAll" resultType="com.hhh.domain.Manager">
        SELECT * FROM manager1
    </select>

<!--这里的manager1为ssmframe数据库中的其中一个表-->

</mapper>

5.新建一个service,在service新建一个ManagerService去调用ManagerDao,这里节省步骤,直接在已有的HelloController类中去调用ManagerDAO

package com.hhh.controller;

import com.hhh.dao.ManagerDao;
import com.hhh.domain.Manager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
//映射路径
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private ManagerDao managerDao;
    //这是idea的编译提示,不是编译报错,所以不影响代码运行的。这个bean只有在代码跑起来的时候才会被spring生成,未运行的时候是没有的。

    @RequestMapping("/test1")
    @ResponseBody
    /*public String test1(){
        return "test1";
        //这个字符串会返回到前端
    }*/

    public List<Manager>test1(){
        return managerDao.findAll();
    }
}

6.注意,记得添加相关依赖

 7.启动tomcat,在浏览器中查看效果

 8.idea完整页面展示

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值