Java进阶之路Spring

第2部分 Web中的Spring

2019-04-15  本文已影响2人  elijah777

第2部分 Web中的Spring

第5章 构建Spring Web应用

5.1.2 搭建Spring MVC

配置DispatcherServlet

按照传统的方式,像DispatcherServlet这样的Servlet会配置在web.xml文件中,这个文件
会放到应用的WAR包里面

DispatcherServlet和Servlet监听器(也就是ContextLoaderListener)的关系

启用Spring MVC

多种方式来配置DispatcherServlet,与之类似,启用Spring MVC组件的方法也不
仅一种。

Spring是使用XML进行配置的,使用 <mvc:annotation-driven >启用注解驱动的Spring MVC。

最简单的Spring MVC配置就是一个带有@EnableWebMvc注解的类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

/**
 * @Auther: shuaihu.shen@hand-china.com
 * @Date: 2018/12/4 09:13
 * @Description:
 */
@Configuration
@EnableWebMvc     // 启用mvc
@ComponentScan("com.web.spittr")  // 启用组件扫描
public class Webconfig extends WebMvcConfigurerAdapter {

    /**
     * 配置JSP视图解析器
     * @return 视图
     */
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }
    
    /**
     * 将对静态资源的请求转发到Servlet容器中默认的Servlet上
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
        configurer.enable();
    }
    
}
   

需要配置视图解析器和启用组件扫描,对静态资源的处理

注意

WebConfig现在添加了@Component-Scan注解,因此将会扫描spitter.web包来查找组件。稍后你就会看到,我们所编写的控制器将会带有@Controller注解,这会使其成为组件扫描时的候选bean。因此,我们不需要在配置类中显式声明任何的控制器。

添加了一个ViewResolver bean。更具体来讲,是Internal-ResourceViewResolver。我们只需要知道它会查找JSP文件,在查找的时候,它会在视图名称上加一个特定的前缀和后缀(例如,名为home的视图将会解析为/WEB-INF/views/home.jsp)。

最后,新的WebConfig类还扩展了WebMvcConfigurerAdapter并重写了其configureDefaultServletHandling()方法。通过调用DefaultServlet-HandlerConfigurer的enable()方法,我们要求DispatcherServlet将对静态资源的
请求转发到Servlet容器中默认的Servlet上,而不是使用DispatcherServlet本身来处理此类请求。

5.2 编写基本的控制器

在Spring MVC中,控制器只是方法上添加了@RequestMapping注解的类,这个注解声明了它们所要处理的请求。
开始的时候,我们尽可能简单,假设控制器类要处理对“/”的请求,并渲染应用的首页

/**
 * @Auther: shuaihu.shen@hand-china.com
 * @Date: 2018/12/13 08:59
 * @Description:  超级简单的控制器
 */
@Controller
public class HomeController {

    @RequestMapping(value = "/", method = GET)
    public String home(){
        return "home";
    }
}

此时此刻运行一下项目便可以成功了。

程序清单:

  1. SpittrWebAppInitializer.java 核心配置文件 可以替代web.xml
  2. Webconfig.java 视图解析器 启用组件扫描 静态文件处理 类似于dispatcherservlet
  3. RootConfig.java 非核心补充文件
  4. HomeController.java 简单控制器
  5. home.jsp 访问页

测试:

import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;

public class HomeControllerTest {

    @Test
    public void testHomePage() throws Exception {
        HomeController homeController = new HomeController();
        // 搭建MockMvc
        MockMvc mockMvc = MockMvcBuilders.standaloneSetup(homeController).build();
        // 对 "/" 执行GET请求   预期得到home视图
        mockMvc.perform(get("/")).andExpect(view().name("home"));
        assertEquals("home", homeController.home());
    }
}

发起了对“/”的GET请求,并断言结果视图的名称为home。

它首先传递一个HomeController实例
到MockMvcBuilders.standaloneSetup()并调用build()来构建MockMvc实例。然后它使用MockMvc实例来执行针对“/”的GET请求并设置期望得到的视图名称

基础知识补充:

final变量在使用前需要初始化,static final修饰的变量在定义的时候进行初始化。

直接复制或者在构造参数中复制

5.3 接受请求的

参数传递

这个处理器方法将会处理形如“/spittles/show?spittle_id=12345”这样的请求。尽管这也可以正
常工作,但是从面向资源的角度来看这并不理想。在理想情况下,要识别的资源(Spittle)应
<u>该通过URL路径进行标示,而不是通过查询参数。</u><u>对“/spittles/12345”发起GET请求要优于</u>
<u>对“/spittles/show?spittle_id=12345”发起请求</u>。前者能够识别出要查询的资源,而后者描述的是
带有参数的一个操作——本质上是通过HTTP发起的RPC。

两种不同的参数传递方式

   /**
     * 展示不同数量的数据
     * @param max 最大值
     * @param count 数量
     * @param model  
     * @return spitterList
     */
    @RequestMapping(value = "show", method = RequestMethod.GET)
    public String showSpittles(@RequestParam(value = "max",defaultValue = "MAX_VALUE",required = true) long max,
                               @RequestParam(value = "count",defaultValue = "DEFAULT_COUNT_SIZE",required = true) int count,
                               Model model) {
        List<Spittle> spittleList = spittleRepository.findSpittles(max, count);
        model.addAttribute("spittleList", spittleList);
        return "spittles";
    }


   

   

5.4 处理表单

 /**
     * 注册BO 带有校验
     * @param spittle
     * @param errors
     * @return
     */
    @RequestMapping(value = "register", method = RequestMethod.POST)
    public String processRegistration(@Validated Spittle spittle, Errors errors) {

        // 如果表单校验出差,则返回到注册页面
        if (errors.hasErrors()) {
            return "registerForm";
        }
        // 重定向到基本信息页
        return "redirect:/spitter" + spittle.getUsername();
    }


    /**
     * 通过spitter的username查找
     * @param username
     * @param model
     * @return
     */
    @RequestMapping(value = "spittle/{username}", method = RequestMethod.GET)
    public String spittle(@PathVariable("username") String username, Model model) {
        List<Spittle> spittleList = new ArrayList<>();
        spittleList.add(spittleRepository.findByUsername(username));
        model.addAttribute("spittleList", spittleList);
        return "spittles";
    }

Java校验API所提供的校验注解

注 解 描述
@AssertFalse 所注解的元素必须是Boolean类型,并且值为false
@AssertTrue 所注解的元素必须是Boolean类型,并且值为true
@DecimalMax 所注解的元素必须是数字,并且它的值要小于或等于给定的BigDecimalString值
@DecimalMin 所注解的元素必须是数字,并且它的值要大于或等于给定的BigDecimalString值
@Digits 所注解的元素必须是数字,并且它的值必须有指定的 @Digits(integer = 0, fraction =10 )
@Future 所注解的元素的值必须是一个将来的日期
@Past 所注解的元素的值必须是一个已过去的日期
 /**
     * 通过id查找
     * @param spittleId
     * @param model
     * @return
     */
    @RequestMapping(value = "spittle/{spittleId}", method = RequestMethod.GET)
    public String spittle(@PathVariable("spittleId") Long spittleId, Model model) {
        List<Spittle> spittleList = new ArrayList<>();
        spittleList.add(spittleRepository.findOne(spittleId));
        model.addAttribute("spittleList", spittleList);
        return "spittles";
    }

    /**
     * 打开注册页面
     * @return
     */
    @RequestMapping(value = "register", method = RequestMethod.GET)
    public String showRegisterationFrom() {
        return "registerForm";
    }

5.5 小结

读完之后也基本上入门的内容,代码也跟着写一下,但也有生疏的地方,jsp页面标签的陌生,即使现在已经在项目上不怎么用了,尤其刚搭建项目时,由于jar包的冲突,实在尴尬,页面一直是500,又看了很多帖子,加了几个jar包就好了。

知识虽然基础,但需要系统的去认识


============================================================

第6章 渲染Web视图

本章内容:
将模型数据渲染为HTML
使用JSP视图
通过tiles定义视图布局
使用Thymeleaf视图

Spring MVC定义了一个名为ViewResolver的接口

public interface ViewResolver {
    View resolveViewName(String var1, Locale var2) throws Exception;
}
public interface View {
    String getContentType();
    void render(Map<String, ?> var1, HttpServletRequest var2, HttpServletResponse var3) throws Exception;
}

View接口的任务就是接受模型以及Servlet的request和response对象,并将输出结果渲染到response中。

6.3 使用Apache Tiles视图定义

原始的方式:

页面定义一个通用的头部和底部。最原始的方式就是查找每个JSP模板,并为其添加头部和底部的HTML。但是这种方法的扩展性并不好,也难以维护。为每个页面添加这些元素会有一些初始成本,而后续的每次变更都会耗费类似的成本。
更好的方式是:

使用布局引擎,如Apache Tiles,定义适用于所有页面的通用页面布局。SpringMVC以视图解析器的形式为Apache Tiles提供了支持,这个视图解析器能够将逻辑视图名解析为Tile定义

6.4 使用Thymeleaf

JSP规范是与Servlet规范紧密耦合的,这意味着它只能用在基于Servlet的Web应用之中。JSP模板不能作为通用的模板(如格式化Email),也不能用于非Servlet的Web应用

为了要在Spring中使用Thymeleaf,我们需要配置三个启用Thymeleaf与Spring集成的bean:

配置Thymeleaf视图解析器

package com.web.spittr.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring3.SpringTemplateEngine;
import org.thymeleaf.spring3.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver;
/**
 * @Auther: shuaihu.shen@hand-china.com
 * @Date: 2018/12/4 09:13
 * @Description:
 */
@Configuration
@EnableWebMvc     // 启用mvc
@ComponentScan("com.web.spittr")  // 启用组件扫描
public class Webconfig extends WebMvcConfigurerAdapter {

    /**
     * 配置JSP视图解析器
     * @return
     */
    @Bean
    public TemplateResolver templateResolver() {
        TemplateResolver templateResolver = new ServletContextTemplateResolver();
        templateResolver.setPrefix("/WEB-INF/views/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode("HTML5");
        return templateResolver;
    }

    /**
     * thymeleaf 视图解析器
     * @param templateEngine
     * @return
     */
    @Bean
    public ViewResolver viewResolver2(
            SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }

    /**
     * 模板引擎
     * @param templateResolver
     * @return
     */
    @Bean
    public SpringTemplateEngine templateEngine(TemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }

   

    /**
     * 静态文件处理
     * @param configurer
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
        configurer.enable();
    }

}

引入Thymeleaf 真的让人感到着急,前后一直弄,指导昨天晚上十一点之后才可以,一直不能导入TemplateResolver这个类,找了很久,不知道缺失什么jar包,其实也知道方向如何,只能没有去试,jar的版本冲突,可怜的娃子,以后还是找稳定一些的,作者给的jar不用去尝试新的了。

   <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf-spring3 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring3</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>

=============================================================

上一篇下一篇

猜你喜欢

热点阅读