getServletConfigClasses() 和 getRootConfigClasses()的不同点

本文介绍了Spring MVC中如何通过分层配置实现模块化的应用程序设计。具体包括如何利用AbstractAnnotationConfigDispatcherServletInitializer的getRootConfigClasses()和getServletConfigClasses()方法来定义根上下文和servlet上下文。

getServletConfigClasses() 和 getRootConfigClasses()都是AbstractAnnotationConfigDispatcherServletInitializer的抽象方法,现在来看一下两者的区别。

Spring的ApplicationContext提供了加载多个(分层)上下文的功能,允许每个上下文集中在一个特定的层上,例如应用程序的Web层或中间层服务。

使用分层ApplicationContext的一个典型示例是,当我们在Web应用程序中有多个DispatcherServlet时,我们将分享一些常见的bean,例如它们之间的数据源。 这样,我们可以定义一个包含所有公共bean的Root ApplicationContext和从根上下文继承公共bean的多个WebApplicationContexts。

在Web MVC框架中,每个DispatcherServlet都有自己的WebApplicationContext,它继承了Root WebApplicationContext中已定义的所有bean。 可以在特定于servlet的作用域中重写这些继承的bean,并且可以为给定的Servlet实例定义新的作用域特定的bean。

 

如果您居住在单个DispatherServlet世界中,则此方案也可能只有一个根上下文:

Talk is cheap, Show me the code!

假设我们要开发一个Web应用程序,我们将使用Spring MVC,Spring Security和Spring Data JPA。对于这个简单的场景,我们至少会有三个不同的配置文件。一个WebConfig,包含我们所有与Web相关的配置,例如ViewResolvers,Controllers,ArgumentResolvers等。如下所示:

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "com.so.web")
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        final boolean DO_NOT_USE_SUFFIX_PATTERN_MATCHING = false;
        configurer.setUseSuffixPatternMatch(DO_NOT_USE_SUFFIX_PATTERN_MATCHING);
    }
}

在这里,我正在定义一个ViewResolver,来解析普通的jsp。我们需要一个RepositoryConfig,它包含所有数据访问工具,如DataSource,EntityManagerFactory,TransactionManager等。它可能如下所示:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.so.repository")
public class RepositoryConfig {
    @Bean
    public DataSource dataSource() { ... }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... }

    @Bean
    public PlatformTransactionManager transactionManager() { ... }
}

还有一个包含所有安全相关内容的SecurityConfig!

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... }

    @Override
    protected void configure(HttpSecurity http) throws Exception { ... }
}

为了将所有这些粘合在一起,我们有两种选择。首先,我们可以通过在根上下文中添加RepositoryConfig和SecurityConfig以及在其子上下文中添加WebConfig来定义典型的分层ApplicationContext:

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

由于我们在这里只有一个DispatcherServlet,我们可以将Web Config添加到根上下文并使servlet上下文为空:

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class, WebConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

Further Reading

Skaffman did a great job on explaining ApplicationContext hierarchies in this answer, which is highly recommended. Also, you can read Spring Documentation.

package com.lx.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; public class jdbcConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource){ DataSourceTransactionManager ds = new DataSourceTransactionManager(); ds.setDataSource(dataSource); return ds; } } package com.lx.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import javax.sql.DataSource; public class MybatisConfig { @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){ SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("com.lx.domain"); return factoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer msc = new MapperScannerConfigurer(); //接口 msc.setBasePackage("com.lx.dao"); return msc; } } package com.lx.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import java.util.logging.Filter; public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringmvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } /*protected Filter[] getServletFilters(){ CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("UTF-8"); return new Filter[]{filter}; }*/ }package com.lx.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import java.util.logging.Filter; public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringmvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } /*protected Filter[] getServletFilters(){ CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding("UTF-8"); return new Filter[]{filter}; }*/ } package com.lx.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @ComponentScan({"com.lx.service"}) @PropertySource("jdbc.properties") @Import({jdbcConfig.class , MybatisConfig.class}) @EnableTransactionManagement public class SpringConfig { } package com.lx.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @Configuration @ComponentScan("com.lx.controller") @EnableWebMvc public class SpringmvcConfig { } 对以上五个整合ssm的配置类结合javaweb的几层框架做出解释,并总结一下不同配置类之间的关系作用
05-28
package com.itheima.config; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(filterName = "encodingFilter",urlPatterns = "/*") public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) {} @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("UTF-8"); servletResponse.setCharacterEncoding("UTF-8"); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() {} } package com.itheima.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import javax.sql.DataSource; @PropertySource("classpath:jdbc.properties") public class JdbcConfig { @Value("${jdbc.driverClassName}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String userName; @Value("${jdbc.password}") private String password; @Bean("dataSource") public DataSource getDataSource(){ //创建对象 DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } } package com.itheima.config; import com.github.pagehelper.PageInterceptor; import org.apache.ibatis.plugin.Interceptor; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import javax.sql.DataSource; import java.util.Properties; public class MyBatisConfig { /**配置PageInterceptor分页插件*/ @Bean public PageInterceptor getPageInterceptor() { PageInterceptor pageIntercptor = new PageInterceptor(); Properties properties = new Properties(); properties.setProperty("value", "true"); pageIntercptor.setProperties(properties); return pageIntercptor; } /* 定义MyBatis的核心连接工厂bean, 等同于<bean class="org.mybatis.spring.SqlSessionFactoryBean"> 参数使用自动装配的形式加载dataSource, 为set注入提供数据源,dataSource来源于JdbcConfig中的配置 */ @Bean public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource,@Autowired PageInterceptor pageIntercptor){ SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean(); //等同于<property name="dataSource" ref="dataSource"/> ssfb.setDataSource(dataSource); Interceptor[] plugins={pageIntercptor}; ssfb.setPlugins(plugins); return ssfb; } /* 定义MyBatis的映射扫描, 等同于<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> */ @Bean public MapperScannerConfigurer getMapperScannerConfigurer(){ MapperScannerConfigurer msc = new MapperScannerConfigurer(); //等同于<property name="basePackage" value="com.itheima.dao"/> msc.setBasePackage("com.itheima.mapper"); return msc; } } package com.itheima.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer { /* 加载Spring配置类中的信息, 初始化Spring容器 */ protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } /* 加载Spring MVC配置类中的信息, 初始化Spring MVC容器 */ protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } } package com.itheima.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration /* 将MyBatisConfig类JdbcConfig类交给Spring管理 */ @Import({MyBatisConfig.class,JdbcConfig.class}) @ComponentScan( "com.itheima.service") @EnableTransactionManagement public class SpringConfig { @Bean("transactionManager") public DataSourceTransactionManager getDataSourceTxManager(@Autowired DataSource dataSource){ DataSourceTransactionManager dtm = new DataSourceTransactionManager(); dtm.setDataSource(dataSource); return dtm; } } package com.itheima.config; import com.itheima.interceptor.ResourcesInterceptor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.*; import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.view.InternalResourceViewResolver; import java.util.List; @Configuration @PropertySource("classpath:ignoreUrl.properties") @ComponentScan({"com.itheima.controller"}) @EnableWebMvc public class SpringMvcConfig implements WebMvcConfigurer { @Value("#{'${ignoreUrl}'.split(',')}") private List<String> ignoreUrl; @Bean public ResourcesInterceptor resourcesInterceptor(){ return new ResourcesInterceptor(ignoreUrl); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor( resourcesInterceptor()).addPathPatterns("/**").excludePathPatterns("/css/**","/js/**","/img/**"); } /* *开启对静态资源的访问 * 类似在Spring MVC的配置文件中设置<mvc:default-servlet-handler/>元素 */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/admin/",".jsp"); } } package com.itheima.controller; import com.itheima.domain.Book; import com.itheima.domain.User; import com.itheima.service.BookService; import entity.PageResult; import entity.Result; 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 org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /* 图书信息Controller */ @Controller @RequestMapping("/book") public class BookController { //注入BookService对象 @Autowired private BookService bookService; /** * 查询最新上架的图书 */ @RequestMapping("/selectNewbooks") public ModelAndView selectNewbooks() { //查询最新上架的5个的图书信息 int pageNum = 1; int pageSize = 5; PageResult pageResult = bookService.selectNewBooks(pageNum, pageSize); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("books_new"); modelAndView.addObject("pageResult", pageResult); return modelAndView; } /** * 根据图书id查询图书信息 * @param id 查询的图书id */ @ResponseBody @RequestMapping("/findById") public Result<Book> findById(String id) { try { Book book=bookService.findById(id); if(book==null){ return new Result(false,"查询图书失败!"); } return new Result(true,"查询图书成功",book); }catch (Exception e){ e.printStackTrace(); return new Result(false,"查询图书失败!"); } } /** * 借阅图书 * @param book 借阅的图书 * @return */ @ResponseBody @RequestMapping("/borrowBook") public Result borrowBook(Book book, HttpSession session) { //获取当前登录的用户姓名 String pname = ((User) session.getAttribute("USER_SESSION")).getName(); book.setBorrower(pname); try { //根据图书的id用户进行图书借阅 Integer count = bookService.borrowBook(book); if (count != 1) { return new Result(false, "借阅图书失败!"); } return new Result(true, "借阅成功,请到行政中心取书!"); } catch (Exception e) { e.printStackTrace(); return new Result(false, "借阅图书失败!"); } } /** * 分页查询符合条件且未下架图书信息 * @param book 查询的条件封装到book中 * @param pageNum 数据列表的当前页码 * @param pageSize 数据列表1页展示多少条数据 */ @RequestMapping("/search") public ModelAndView search(Book book, Integer pageNum, Integer pageSize, HttpServletRequest request) { if (pageNum == null) { pageNum = 1; } if (pageSize == null) { pageSize = 10; } //查询到的图书信息 PageResult pageResult = bookService.search(book, pageNum, pageSize); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("books"); //将查询到的数据存放在 ModelAndView的对象中 modelAndView.addObject("pageResult", pageResult); //将查询的参数返回到页面,用于回显到查询的输入框中 modelAndView.addObject("search", book); //将当前页码返回到页面,用于分页插件的分页显示 modelAndView.addObject("pageNum", pageNum); //将当前查询的控制器路径返回到页面,页码变化时继续向该路径发送请求 modelAndView.addObject("gourl", request.getRequestURI()); return modelAndView; } /** * 新增图书 * @param book 页面表单提交的图书信息 * 将新增的结果向页面传递信息封装到Result对象中返回 */ @ResponseBody @RequestMapping("/addBook") public Result addBook(Book book) { try { Integer count=bookService.addBook(book); if(count!=1){ return new Result(false, "新增图书失败!"); } return new Result(true, "新增图书成功!"); }catch (Exception e){ e.printStackTrace(); return new Result(false, "新增图书失败!"); } } /** * 编辑图书信息 * @param book 编辑的图书信息 */ @ResponseBody @RequestMapping("/editBook") public Result editBook(Book book) { try { Integer count= bookService.editBook(book); if(count!=1){ return new Result(false, "编辑失败!"); } return new Result(true, "编辑成功!"); }catch (Exception e){ e.printStackTrace(); return new Result(false, "编辑失败!"); } } /** *分页查询当前被借阅且未归还的图书信息 * @param pageNum 数据列表的当前页码 * @param pageSize 数据列表1页展示多少条数据 */ @RequestMapping("/searchBorrowed") public ModelAndView searchBorrowed(Book book,Integer pageNum, Integer pageSize, HttpServletRequest request) { if (pageNum == null) { pageNum = 1; } if (pageSize == null) { pageSize = 10; } //获取当前登录的用户 User user = (User) request.getSession().getAttribute("USER_SESSION"); PageResult pageResult = bookService.searchBorrowed(book,user, pageNum, pageSize); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("book_borrowed"); //将查询到的数据存放在 ModelAndView的对象中 modelAndView.addObject("pageResult", pageResult); //将查询的参数返回到页面,用于回显到查询的输入框中 modelAndView.addObject("search", book); //将当前页码返回到页面,用于分页插件的分页显示 modelAndView.addObject("pageNum", pageNum); //将当前查询的控制器路径返回到页面,页码变化时继续向该路径发送请求 modelAndView.addObject("gourl", request.getRequestURI()); return modelAndView; } /** * 归还图书 * @param id 归还的图书的id */ @ResponseBody @RequestMapping("/returnBook") public Result returnBook(String id, HttpSession session) { //获取当前登录的用户信息 User user = (User) session.getAttribute("USER_SESSION"); try { boolean flag = bookService.returnBook(id, user); if (!flag) { return new Result(false, "还书失败!"); } return new Result(true, "还书确认中,请先到行政中心还书!"); }catch (Exception e){ e.printStackTrace(); return new Result(false, "还书失败!"); } } /** * 确认图书归还 * @param id 确认归还的图书的id */ @ResponseBody @RequestMapping("/returnConfirm") public Result returnConfirm(String id) { try { Integer count=bookService.returnConfirm(id); if(count!=1){ return new Result(false, "确认失败!"); } return new Result(true, "确认成功!"); }catch (Exception e){ e.printStackTrace(); return new Result(false, "确认失败!"); } } } package com.itheima.controller; import com.itheima.domain.Record; import com.itheima.domain.User; import com.itheima.service.RecordService; import entity.PageResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; @Controller @RequestMapping("/record") public class RecordController { @Autowired private RecordService recordService; /** * 查询借阅记录 * @param record 借阅记录的查询条件 * @param pageNum 当前页码 * @param pageSize 每页显示数量 */ @RequestMapping("/searchRecords") public ModelAndView searchRecords(Record record, HttpServletRequest request, Integer pageNum, Integer pageSize){ if(pageNum==null){ pageNum=1; } if(pageSize==null){ pageSize=10; } //获取当前登录用户的信息 User user = ((User) request.getSession().getAttribute("USER_SESSION")); PageResult pageResult=recordService.searchRecords(record,user,pageNum,pageSize); ModelAndView modelAndView=new ModelAndView(); modelAndView.setViewName("record"); //将查询到的数据存放在 ModelAndView的对象中 modelAndView.addObject("pageResult",pageResult); //将查询的参数返回到页面,用于回显到查询的输入框中 modelAndView.addObject("search",record); //将当前页码返回到页面,用于分页插件的分页显示 modelAndView.addObject("pageNum",pageNum); //将当前查询的控制器路径返回到页面,页码变化时继续向该路径发送请求 modelAndView.addObject("gourl", request.getRequestURI()); return modelAndView; } } package com.itheima.controller; import com.itheima.domain.User; import com.itheima.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * 用户登录注销Controller */ @Controller public class UserController { @RequestMapping("/toMainPage") public String toMainPage(){ return "main"; } //注入userService @Autowired private UserService userService; /* 用户登录 */ @RequestMapping("/login") public String login(User user, HttpServletRequest request){ try { User u=userService.login(user); /* 用户账号密码是否查询出用户信息 是:将用户信息存入Session,并跳转到后台首页 否:Request域中添加提示信息,并转发到登录页面 */ if(u!=null){ request.getSession().setAttribute("USER_SESSION",u); return "redirect:/admin/main.jsp"; } request.setAttribute("msg","用户名或密码错误"); return "forward:/admin/login.jsp"; }catch(Exception e){ e.printStackTrace(); request.setAttribute("msg","系统错误"); return "forward:/admin/login.jsp"; } } /* 注销登录 */ @RequestMapping("/logout") public String logout( HttpServletRequest request){ try { HttpSession session = request.getSession(); //销毁Session session.invalidate(); return "forward:/admin/login.jsp"; }catch(Exception e){ e.printStackTrace(); request.setAttribute("msg","系统错误"); return "forward:/admin/login.jsp"; } } } package com.itheima.domain; import java.io.Serializable; public class Book implements Serializable { private Integer id; //图书编号 private String name; //图书名称 private String isbn; //图书标准ISBN编号 private String press; //图书出版社 private String author; //图书作者 private Integer pagination;//图书页数 private Double price; //图书价格 private String uploadTime; //图书上架时间 private String status; //图书状态 private String borrower; //图书借阅人 private String borrowTime; //图书借阅时间 private String returnTime; //图书预计归还时间 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public String getPress() { return press; } public void setPress(String press) { this.press = press; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Integer getPagination() { return pagination; } public void setPagination(Integer pagination) { this.pagination = pagination; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public String getUploadTime() { return uploadTime; } public void setUploadTime(String uploadTime) { this.uploadTime = uploadTime; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getBorrower() { return borrower; } public void setBorrower(String borrower) { this.borrower = borrower; } public String getBorrowTime() { return borrowTime; } public void setBorrowTime(String borrowTime) { this.borrowTime = borrowTime; } public String getReturnTime() { return returnTime; } public void setReturnTime(String returnTime) { this.returnTime = returnTime; } } package com.itheima.domain; import java.io.Serializable; public class Record implements Serializable { private String id; //图书借阅id private String bookname; //借阅的图书名称 private String bookisbn; //借阅的图书的ISBN编号 private String borrower; //图书借阅人 private String borrowTime; //图书借阅时间 private String remandTime; //图书归还时间 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getBookname() { return bookname; } public void setBookname(String bookname) { this.bookname = bookname; } public String getBookisbn() { return bookisbn; } public void setBookisbn(String bookisbn) { this.bookisbn = bookisbn; } public String getBorrower() { return borrower; } public void setBorrower(String borrower) { this.borrower = borrower; } public String getBorrowTime() { return borrowTime; } public void setBorrowTime(String borrowTime) { this.borrowTime = borrowTime; } public String getRemandTime() { return remandTime; } public void setRemandTime(String remandTime) { this.remandTime = remandTime; } } package com.itheima.domain; import java.io.Serializable; public class User implements Serializable { private Integer id; //用户id private String name; //用户名称 private String password; //用户密码 private String email; //用户邮箱(用户账号) private String role; //用户角色 private String status; //用户状态 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } package com.itheima.interceptor; import com.itheima.domain.User; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; /** * 资源拦截器 */ public class ResourcesInterceptor extends HandlerInterceptorAdapter { //任意角色都能访问的路径 private List<String> ignoreUrl; public ResourcesInterceptor(List<String> ignoreUrl) { this.ignoreUrl = ignoreUrl; } public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { User user = (User) request.getSession().getAttribute("USER_SESSION"); //获取请求的路径 String uri = request.getRequestURI(); //如果用户是已登录状态,判断访问的资源是否有权限 if (user != null) { //如果是管理员,放行 if ("ADMIN".equals(user.getRole())) { return true; } //如果是普通用户 else if (!"ADMIN".equals(user.getRole())) { for (String url : ignoreUrl) { //访问的资源不是管理员权限的资源,放行 if (uri.indexOf(url) >= 0) { return true; } } } } //对用户登录的相关请求,放行 if (uri.indexOf("login") >= 0) { return true; } //其他情况都直接跳转到登录页面 request.setAttribute("msg", "您还没有登录,请先登录!"); request.getRequestDispatcher("/admin/login.jsp").forward(request, response); return false; } } package com.itheima.mapper; import com.github.pagehelper.Page; import com.itheima.domain.Book; import org.apache.ibatis.annotations.*; /** * 图书接口 */ public interface BookMapper { @Select("SELECT * FROM book where book_status !='3' order by book_uploadtime DESC") @Results(id = "bookMap",value = { //id字段默认为false,表示不是主键 //column表示数据库表字段,property表示实体类属性名。 @Result(id = true,column = "book_id",property = "id"), @Result(column = "book_name",property = "name"), @Result(column = "book_isbn",property = "isbn"), @Result(column = "book_press",property = "press"), @Result(column = "book_author",property = "author"), @Result(column = "book_pagination",property = "pagination"), @Result(column = "book_price",property = "price"), @Result(column = "book_uploadtime",property = "uploadTime"), @Result(column = "book_status",property = "status"), @Result(column = "book_borrower",property = "borrower"), @Result(column = "book_borrowtime",property = "borrowTime"), @Result(column = "book_returntime",property = "returnTime") }) Page<Book> selectNewBooks(); @Select("SELECT * FROM book where book_id=#{id}") @ResultMap("bookMap") //根据id查询图书信息 Book findById(String id); @Select({"<script>" + "SELECT * FROM book " + "where book_status !='3'" + "<if test=\"name != null\"> AND book_name like CONCAT('%',#{name},'%')</if>" + "<if test=\"press != null\"> AND book_press like CONCAT('%', #{press},'%') </if>" + "<if test=\"author != null\"> AND book_author like CONCAT('%', #{author},'%')</if>" + "order by book_borrowtime" + "</script>" }) @ResultMap("bookMap") //分页查询图书 Page<Book> searchBooks(Book book); //新增图书 Integer addBook(Book book); //编辑图书信息 Integer editBook(Book book); @Select( {"<script>" + "SELECT * FROM book " + "where book_borrower=#{borrower}" + "AND book_status ='1'"+ "<if test=\"name != null\"> AND book_name like CONCAT('%',#{name},'%')</if>" + "<if test=\"press != null\"> AND book_press like CONCAT('%', #{press},'%') </if>" + "<if test=\"author != null\"> AND book_author like CONCAT('%', #{author},'%')</if>" + "or book_status ='2'"+ "<if test=\"name != null\"> AND book_name like CONCAT('%',#{name},'%')</if>" + "<if test=\"press != null\"> AND book_press like CONCAT('%', #{press},'%') </if>" + "<if test=\"author != null\"> AND book_author like CONCAT('%', #{author},'%')</if>" + "order by book_borrowtime" + "</script>"}) @ResultMap("bookMap") //查询借阅但未归还的图书待归还确认的图书 Page<Book> selectBorrowed(Book book); @Select({"<script>" + "SELECT * FROM book " + "where book_borrower=#{borrower}" + "AND book_status in('1','2')"+ "<if test=\"name != null\"> AND book_name like CONCAT('%',#{name},'%')</if>" + "<if test=\"press != null\"> AND book_press like CONCAT('%', #{press},'%') </if>" + "<if test=\"author != null\"> AND book_author like CONCAT('%', #{author},'%')</if>" + "order by book_borrowtime" + "</script>"}) @ResultMap("bookMap") //查询借阅但未归还的图书 Page<Book> selectMyBorrowed(Book book); } package com.itheima.mapper; import com.github.pagehelper.Page; import com.itheima.domain.Record; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; public interface RecordMapper { //新增借阅记录 Integer addRecord(Record record); @Select({"<script>" + "SELECT * FROM record " + "where 1=1" + "<if test=\"borrower != null\">AND record_borrower like CONCAT('%',#{borrower},'%')</if>" + "<if test=\"bookname != null\">AND record_bookname like CONCAT('%',#{bookname},'%') </if>" + "order by record_remandtime DESC" + "</script>" }) @Results(id = "recordMap",value = { //id字段默认为false,表示不是主键 //column表示数据库表字段,property表示实体类属性名。 @Result(id = true,column = "record_id",property = "id"), @Result(column = "record_bookname",property = "bookname"), @Result(column = "record_bookisbn",property = "bookisbn"), @Result(column = "record_borrower",property = "borrower"), @Result(column = "record_borrowtime",property = "borrowTime"), @Result(column = "record_remandtime",property = "remandTime") }) //查询借阅记录 Page<Record> searchRecords(Record record); } package com.itheima.mapper; import com.itheima.domain.User; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; public interface UserMapper{ @Select("select * from user where user_email=#{email} AND user_password=#{password} AND user_status!='1'") @Results(id = "userMap",value = { //id字段默认为false,表示不是主键 //column表示数据库表字段,property表示实体类属性名。 @Result(id = true,column = "user_id",property = "id"), @Result(column = "user_name",property = "name"), @Result(column = "user_password",property = "password"), @Result(column = "user_email",property = "email"), @Result(column = "user_role",property = "role"), @Result(column = "user_status",property = "status") }) User login(User user); } package com.itheima.service.impl; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.itheima.domain.Book; import com.itheima.domain.Record; import com.itheima.domain.User; import com.itheima.mapper.BookMapper; import com.itheima.service.BookService; import com.itheima.service.RecordService; import entity.PageResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @Service @Transactional public class BookServiceImpl implements BookService { @Autowired private BookMapper bookMapper; /** * 根据当前页码每页需要展示的数据条数,查询最新上架的图书信息 * @param pageNum 当前页码 * @param pageSize 每页显示数量 */ @Override public PageResult selectNewBooks(Integer pageNum, Integer pageSize) { // 设置分页查询的参数,开始分页 PageHelper.startPage(pageNum, pageSize); Page<Book> page=bookMapper.selectNewBooks(); return new PageResult(page.getTotal(),page.getResult()); } /** * 根据id查询图书信息 * @param id 图书id */ public Book findById(String id) { return bookMapper.findById(id); } /** * 借阅图书 * @param book * @return */ @Override public Integer borrowBook(Book book) { //根据id查询出需要借阅的完整图书信息 Book b = this.findById(book.getId()+""); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //设置当天为借阅时间 book.setBorrowTime(dateFormat.format(new Date())); //设置所借阅的图书状态为借阅中 book.setStatus("1"); //将图书的价格设置在book对象中 book.setPrice(b.getPrice()); //将图书的上架设置在book对象中 book.setUploadTime(b.getUploadTime()); return bookMapper.editBook(book); } /** * @param book 封装查询条件的对象 * @param pageNum 当前页码 * @param pageSize 每页显示数量 */ @Override public PageResult search(Book book, Integer pageNum, Integer pageSize) { // 设置分页查询的参数,开始分页 PageHelper.startPage(pageNum, pageSize); Page<Book> page=bookMapper.searchBooks(book); return new PageResult(page.getTotal(),page.getResult()); } /** * 新增图书 * @param book 页面提交的新增图书信息 */ public Integer addBook(Book book) { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //设置新增图书的上架时间 book.setUploadTime(dateFormat.format(new Date())); return bookMapper.addBook(book); } /** * 编辑图书信息 * @param book 图书信息 */ public Integer editBook(Book book) { return bookMapper.editBook(book); } /** * 查询用户当前借阅的图书 * @param book 封装查询条件的对象 * @param user 当前登录用户 * @param pageNum 当前页码 * @param pageSize 每页显示数量 */ @Override public PageResult searchBorrowed(Book book, User user, Integer pageNum, Integer pageSize) { // 设置分页查询的参数,开始分页 PageHelper.startPage(pageNum, pageSize); Page<Book> page; //将当前登录的用户放入查询条件中 book.setBorrower(user.getName()); //如果是管理员,查询自己借阅但未归还的图书所有待确认归还的图书 if("ADMIN".equals(user.getRole())){ page= bookMapper.selectBorrowed(book); }else { //如果是普通用户,查询自己借阅但未归还的图书 page= bookMapper.selectMyBorrowed(book); } return new PageResult(page.getTotal(),page.getResult()); } /** * 归还图书 * @param id 归还的图书的id * @param user 归还的人员,也就是当前图书的借阅者 */ @Override public boolean returnBook(String id,User user) { //根据图书id查询出图书的完整信息 Book book = this.findById(id); //再次核验当前登录人员图书借阅者是不是同一个人 boolean rb=book.getBorrower().equals(user.getName()); //如果是同一个人,允许归还 if(rb){ //将图书借阅状态修改为归还中 book.setStatus("2"); bookMapper.editBook(book); } return rb; } @Autowired //注入RecordService对象 private RecordService recordService; /** * 归还确认 * @param id 待归还确认的图书id */ @Override public Integer returnConfirm(String id) { //根据图书id查询图书的完整信息 Book book = this.findById(id); //根据归还确认的图书信息,设置借阅记录 Record record = this.setRecord(book); //将图书的借阅状态修改为可借阅 book.setStatus("0"); //清除当前图书的借阅人信息 book.setBorrower(""); //清除当前图书的借阅时间信息 book.setBorrowTime(""); //清除当亲图书的预计归还时间信息 book.setReturnTime(""); Integer count= bookMapper.editBook(book); //如果归还确认成功,则新增借阅记录 if(count==1){ return recordService.addRecord(record); } return 0; } /** * 根据图书信息设置借阅记录的信息 * @param book 借阅的图书信息 */ private Record setRecord(Book book){ Record record=new Record(); //设置借阅记录的图书名称 record.setBookname(book.getName()); //设置借阅记录的图书isbn record.setBookisbn(book.getIsbn()); //设置借阅记录的借阅人 record.setBorrower(book.getBorrower()); //设置借阅记录的借阅时间 record.setBorrowTime(book.getBorrowTime()); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //设置图书归还确认的当天为图书归还时间 record.setRemandTime(dateFormat.format(new Date())); return record; } } package com.itheima.service.impl; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.itheima.domain.Record; import com.itheima.domain.User; import com.itheima.mapper.RecordMapper; import com.itheima.service.RecordService; import entity.PageResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; @Service @Transactional public class RecordServiceImpl implements RecordService { @Autowired private RecordMapper recordMapper; /** * 新增借阅记录 * @param record 新增的借阅记录 */ @Override public Integer addRecord(Record record) { return recordMapper.addRecord(record); } /** * 查询借阅记录 * @param record 借阅记录的查询条件 * @param user 当前的登录用户 * @param pageNum 当前页码 * @param pageSize 每页显示数量 */ @Override public PageResult searchRecords(Record record, User user, Integer pageNum, Integer pageSize) { // 设置分页查询的参数,开始分页 PageHelper.startPage(pageNum, pageSize); //如果不是管理员,则查询条件中的借阅人设置为当前登录用户 if(!"ADMIN".equals(user.getRole())){ record.setBorrower(user.getName()); } Page<Record> page= recordMapper.searchRecords(record); return new PageResult(page.getTotal(),page.getResult()); } } package com.itheima.service.impl; import com.itheima.domain.User; import com.itheima.mapper.UserMapper; import com.itheima.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** *用户接口实现类 */ @Service public class UserServiceImpl implements UserService { //注入userMapper @Autowired private UserMapper userMapper; //通过User的用户账号用户密码查询用户信息 @Override public User login(User user) { return userMapper.login(user); } } package com.itheima.service; import com.itheima.domain.Book; import com.itheima.domain.User; import entity.PageResult; /** * 图书接口 */ public interface BookService { //查询最新上架的图书 PageResult selectNewBooks(Integer pageNum, Integer pageSize); //根据id查询图书信息 Book findById(String id); //借阅图书 Integer borrowBook(Book book); //分页查询图书 PageResult search(Book book, Integer pageNum, Integer pageSize); //新增图书 Integer addBook(Book book); //编辑图书信息 Integer editBook(Book book); //查询当前借阅的图书 PageResult searchBorrowed(Book book, User user, Integer pageNum, Integer pageSize); //归还图书 boolean returnBook(String id,User user); //归还确认 Integer returnConfirm(String id); } package com.itheima.service; import com.itheima.domain.Record; import com.itheima.domain.User; import entity.PageResult; /** * 借阅记录接口 */ public interface RecordService { //新增借阅记录 Integer addRecord(Record record); //查询借阅记录 PageResult searchRecords(Record record, User user, Integer pageNum, Integer pageSize); } package com.itheima.service; import com.itheima.domain.User; /** *用户接口 */ public interface UserService{ //通过User的用户账号用户密码查询用户信息 User login(User user); } package entity; import java.io.Serializable; import java.util.List; /** * 分页结果的实体类 */ public class PageResult implements Serializable{ private long total; // 总数 private List rows; // 返回的数据集合 public PageResult(long total, List rows) { super(); this.total = total; this.rows = rows; } public long getTotal() { return total; } public void setTotal(long total) { this.total = total; } public List getRows() { return rows; } public void setRows(List rows) { this.rows = rows; } } package entity; import java.io.Serializable; /** * 用于向页面传递信息的类 */ public class Result<T> implements Serializable{ private boolean success; //是否成功操作成功 private String message; //需要传递的信息 private T data; //需要传递的数据 public Result(boolean success, String message) { super(); this.success=success; this.message = message; } public Result(boolean success, String message, T data) { this.success = success; this.message = message; this.data = data; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public T getData() { return data; } public void setData(T data) { this.data = data; } } <?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.itheima.mapper.BookMapper"> <!--新增图书--> <insert id="addBook" parameterType="com.itheima.domain.Book"> insert into book(book_id,book_name,book_isbn,book_press,book_author,book_pagination,book_price,book_uploadtime,book_status,book_borrower,book_borrowtime,book_returntime) values (#{id},#{name},#{isbn},#{press},#{author},#{pagination},#{price},#{uploadTime},#{status},#{borrower},#{borrowTime},#{returnTime}) </insert> <!--修改book信息(修复空格隐患)--> <update id="editBook"> update book <trim prefix="set" suffixOverrides=","> <if test="name != null" > book_name = #{name}, </if> <if test="isbn != null" > book_isbn = #{isbn}, </if> <if test="press != null" > book_press = #{press}, </if> <if test="author != null" > book_author = #{author}, </if> <if test="pagination != null" > book_pagination = #{pagination}, </if> <if test="price != null" > book_price = #{price}, </if> <if test="uploadTime != null" > book_uploadtime = #{uploadTime}, </if> <if test="status != null" > book_status = #{status}, </if> <if test="borrower!= null" > book_borrower= #{borrower}, <!-- 去除#{borrower}右侧的空格 --> </if> <if test="borrowTime != null" > book_borrowtime = #{borrowTime}, </if> <if test="returnTime != null" > book_returntime = #{returnTime} </if> </trim> where book_id = #{id} </update> </mapper> <!--<?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.itheima.mapper.BookMapper">--> <!--<!–新增图书–>--> <!--<insert id="addBook" parameterType="com.itheima.domain.Book">--> <!-- insert into book(book_id,book_name,book_isbn,book_press,book_author,book_pagination,book_price,book_uploadtime,book_status,book_borrower,book_borrowtime,book_returntime)--> <!-- values (#{id},#{name},#{isbn},#{press},#{author},#{pagination},#{price},#{uploadTime},#{status},#{borrower},#{borrowTime},#{returnTime})--> <!--</insert>--> <!--<!–修改book信息–>--> <!-- <update id="editBook" >--> <!-- update book--> <!-- <trim prefix="set" suffixOverrides=",">--> <!-- <if test="name != null" >--> <!-- book_name = #{name},--> <!-- </if>--> <!-- <if test="isbn != null" >--> <!-- book_isbn = #{isbn},--> <!-- </if>--> <!-- <if test="press != null" >--> <!-- book_press = #{press},--> <!-- </if>--> <!-- <if test="author != null" >--> <!-- book_author = #{author},--> <!-- </if>--> <!-- <if test="pagination != null" >--> <!-- book_pagination = #{pagination},--> <!-- </if>--> <!-- <if test="price != null" >--> <!-- book_price = #{price},--> <!-- </if>--> <!-- <if test="uploadTime != null" >--> <!-- book_uploadtime = #{uploadTime},--> <!-- </if>--> <!-- <if test="status != null" >--> <!-- book_status = #{status},--> <!-- </if>--> <!-- <if test="borrower!= null" >--> <!-- book_borrower= #{borrower},--> <!-- </if>--> <!-- <if test="borrowTime != null" >--> <!-- book_borrowtime = #{borrowTime},--> <!-- </if>--> <!-- <if test="returnTime != null" >--> <!-- book_returntime = #{returnTime}--> <!-- </if>--> <!-- </trim>--> <!-- where book_id = #{id}--> <!-- </update>--> <!--</mapper>--> <?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.itheima.mapper.RecordMapper"> <insert id="addRecord"> insert into record(record_id,record_bookname,record_bookisbn,record_borrower,record_borrowtime,record_remandtime) values (#{id},#{bookname},#{bookisbn},#{borrower},#{borrowTime},#{remandTime}) </insert> </mapper> <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>BookSystem</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <!--Spring核心容器--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.8.RELEASE</version> </dependency> <!--Spring事务管理--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.8.RELEASE</version> </dependency> <!--Spring的JDBC操作数据库的依赖,包含Spring自带数据源,jdbcTemplate--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.8.RELEASE</version> </dependency> <!--Spring MVC核心--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.8.RELEASE</version> </dependency> <!--MyBatis核心--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.19</version> </dependency> <!--MyBatis的分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.0</version> </dependency> <!--MyBatis整合Spring--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.7</version> </dependency> <!--MySQL数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <!--Druid数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency> <!--servlet-api:引入Servlet的功能--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--jsp-api:JSP页面的功能包--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!--JSTL标签库--> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!--Jackson--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/SMVCBen</path> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> </plugin> </plugins> </build> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project>
最新发布
12-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值