SpringMVC4笔记——第一章到第四章

《精通SpringMVC4》

链接:https://pan.baidu.com/s/1vmaSmQ1TOenWGE7HdeQe2g 
提取码:vwk3 

别人的读书笔记https://blog.csdn.net/qq_36807862/article/details/81290041

1.5.2

@SpringBootApplication 注解,如果看一下这个注解的代码的话,就会发现它实际上组合了3 个其他的注解,也就是@Configuration(表明这个类将会处理Spring常规配置,比如bean的声明)、@EnableAutoConfiguration 和@ComponentScan(告诉Spring去哪里查找Spring组件,服务,控制器等,默认扫描当前包以及包下面所有子包)

1.6如果你之前搭建过Spring MVC 应用,那么可能已经习惯于编写相关的XML 文件或Java注解配置类。
一般来讲,初始的步骤如下所示:

  1. 初始化Spring MVC 的DispatcherServlet;
  2. 搭建转码过滤器,保证客户端请求进行正确地转码;
  3. 搭建视图解析器(view resolver),告诉Spring 去哪里查找视图,以及它们是使用哪种方言编写的(JSP、Thymeleaf 模板等);
  4. 配置静态资源的位置(CSS、JS);
  5. 配置所支持的地域以及资源bundle;
  6. 配置multipart 解析器,保证文件上传能够正常工作;
  7. 将Tomcat 或Jetty 包含进来,从而能够在Web 服务器上运行我们的应用;
  8. 建立错误页面(如404)。
//在完成所有Bean的实例化后,Spring又加载了一系列策略方法,用于SpringMVC。
protected void initStrategies(ApplicationContext context) {
    //文件类型解析器
    initMultipartResolver(context);
    //为了让web应用程序支持国际化,必须识别每个用户的首选区域,并根据这个区域显示内容。 
    //LocaleResolver解析器主要解决国际化的问题。
    initLocaleResolver(context);
    //主题样式解析器,
    initThemeResolver(context);
    //处理器映射解析器(非常重要)
    initHandlerMappings(context);
    //handlerAdapter解析器
    initHandlerAdapters(context);
    //异常解析器
    initHandlerExceptionResolvers(context);
    //通过提供的 Servlet实例来初始化RequestToViewNameTranslator
    initRequestToViewNameTranslator(context);
    //视图解析器,
    initViewResolvers(context);
    
    initFlashMapManager(context);
}

关于快速搭建web项目,Springboot帮我们做的事情:SpringBoot 是带有一定倾向性的Spring项目配置器,SpringBoot仅仅是基于常见的使用场景,帮助我们对应用进行配置,不过我们可以在任意的地方覆盖这些默认值,并声明自己的配置。

1.6 .1分发器和multipart解析器

为什么我们已经拥有了分发器servlet和multipart解析器?

通过查看DispatcherServletAutoConfiguration这个配置类我们就了解了SpringBoot已经帮我们配置了dispatcherServlet和multipartResolver。
DispatcherServletAutoConfiguration这是一个典型的SpringBoot配置类

  • 与其他的Spring 配置类相同,它使用了@Configuration 注解;
  • 般会通过@Order 注解来声明优先等级,可以看到DispatcherServletAutoConfiguration需要优先进行配置;
  • 其中也可以包含一些提示信息,如@AutoConfigureAfter 或@AutoConfigureBefore,从而进一步细化配置处理的顺序;
  •  它 还 支 持 在 特 定 的 条 件下启用某项功能。通过使用@ConditionalOnClass(DispatcherServlet.class) 这个特殊的配置, 能够确保我们的类路径下包含DispatcherServlet,这能够很好地表明Spring MVC 位于类路径中,用户当前希望将其启动起来。

这个文件中还包含了Spring MVC 分发器Servlet 和multipart 解析器的典型配置。整个Spring MVC 配置被拆分到了多个文件之中。org.springframework.boot.autoconfigure.web包下面都是Spring web 相关的配置,还有读取配置的类xxxProperties

1.6.2 视图解析器、静态资源以及区域配置

另一个密切相关的配置类是WebMvcAutoConfiguration,他声明了视图解析器,地域解析器(localeresolver),以及静态资源的位置。

视图解析器:

 @Configuration
    @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
    @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
    @Order(0)
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
        @Bean
        @ConditionalOnMissingBean
        public InternalResourceViewResolver defaultViewResolver() {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix(this.mvcProperties.getView().getPrefix());
            resolver.setSuffix(this.mvcProperties.getView().getSuffix());
            return resolver;
        }
}

配置很普通,很简单,其中使用了配置属性,允许用户自定义。它的意思就是说“将会在用户的application.properties 文件中查找两个变量,这两个变量的名字是spring.mvc.view.prefix=" ", spring.mvc.view.suffix=" ".在配置中只需两行代码就能将视图解析器搭建起来了,这是非常便利的。

在这个文件中还声明了静态资源和地域的配置:

public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    public LocaleResolver localeResolver() {...}
    public void addResourceHandlers(ResourceHandlerRegistry registry) {...}
}

1.7 错误与转吗配置

org.springframework.boot.autoconfigure.web.servlet.error包

ErrorMvcAutoConfiguration:这个类帮我们做了简单的错误处理

  • 定义了一个bean,即DefaultErrorAttributes,它通过特定的属性暴露了有用的错误信息,这些属性包括状态、错误码和相关的栈跟踪信息。
  • 定义了一个BasicErrorController bean,这是一个MVC 控制器,负责展现我们所看到的错误页面。
  • 允许我们将Spring Boot 的whitelabel 错误页面设置为无效,这需要将配置文件application.properties 中error.whitelable.enabled 设置为false。
  • 我们还可以借助模板引擎提供自己的错误页面。例如,它的名字是error.html,ErrorTemplateMissingCondition 条件会对此进行检查。

自动配置实在是太强了!!!

 


Spring MVC的解析器中

我们重点关注两个,initHandlerMappings和initHandlerAdapters。

 


1.8 嵌入式Servlet容器(Tomcat)的配置

默认情况下,SpringBoot在打包和运行应用时会使用Tomcat嵌入式API(Tomcat embedded API):嵌入式servlet容器的配置类包含了三个不同的配置,那一个处于激活状态取决于类路径下哪些内容是可用的。因此,服务器可以很容易地进行替换,只需将spring-boot-starter-tomcat JAR 依赖移除掉,并将其替换为Jetty或Undertow 对应的依赖即可。

配置servlet容器时的不同选项:ServerProperties

1.8.1HTTP 端口 server.port= -1(禁用HTTP协议)/0(在随机端口启动应用)

1.8.2 SSL配置

1.8.3 其他配置

在配置中我们可以简单的通过@Bean元素添加java web元素,比如servlet,Filter,listlistener。SpringBoot可以很方便的与Servlet配合使用。

除此之外,SpringBoot还为我们内置了3项内容:

  • 在JackSonAutoConfiguration中,声明Jackson进行JSON序列化。**注意Jackson使用默认时区,反序列化将会出现日期问题,配置成东八区只需要添加配置spring.jackson.time-zone=GMT+8 
  • 在HttpMessageConvertersAutoConfiguration中声明了默认的HttpMessageConverter
  • 在JmxAutoConfiguration中声明了JMX功能(Java Management Extension java管理扩展),添加Spring-boot-starter-actuator

第二章、精通MVC架构 

2.1MVC架构:将数据和表现层解耦,模型和视图解耦,相同的数据跨多个视图重用

  • 模型:包含了应用中所需的各种展现数据。
  • 视图:由数据的多种表述所组成,它将会展现给用户。以不同的方式来查看数据
  • 控制器:将会处理用户的操作,它是连接模型和视图的桥梁。

2.2 对MVC的质疑及其最佳实践

2.2.1 贫血的领域模型

DDD(Domain Driver Design,领域驱动设计):核心理念是将面向对象的范式应用到领域对象之中。违背这一原则的话就被称为贫血的领域模型

贫血的领域模型通常来讲会具有如下的症状:

  • 模型是由简单老式的Java 对象(plain old Java object,POJO)所构成的,只有getter 和setter 方法;
  • 所有业务逻辑都是在服务层处理的;
  • 对模型的校验会在本模型外部进行,例如在控制器中。

DDD实践需要将领域从应用逻辑中分离出来,DDD规则所涉及的非常多...

避免领域贫血的途径如下:

  • 服务层适合进行应用级别的抽象(如事务处理),而不是业务逻辑;
  • 领域对象应该始终处于合法的状态。通过校验器(validator)或JSR-303 的校验注解,让校验过程在表单对象中进行;
  • 将输入转换成有意义的领域对象;
  • 将数据层按照Repository 的方式来实现,Repository 中会包含领域查询(例如参考Spring Data 规范);
  • 将领域逻辑与底层的持久化框架解耦;
  • 尽可能使用实际的对象,例如操作FirstName 类而不是操作String。

2.3 Spring MVC

  1. 模型-由Spring MVC 的Model 或者ModelView简单封装的Map,与数据层交互-推荐使用springData库
  2. 控制层-@Controller处理,响应http请求;控制器响应有两种方式:
  • 在web响应中直接写入内容(比如RESTful应用,在响应中直接暴露模型的JSON或者XML描述);
  • 将应用路由一个视图并将属性注入到该视图中。(模型传递到视图中,由模板引擎进行渲染,并写入相应之中)

2.4 使用Thymeleaf模板引擎

  1. 添加依赖
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
       <version>2.1.7.RELEASE</version>
    </dependency>

    添加依赖就能启动Thymleaf模板引擎了

  2. 添加一个页面,将其放到src/main/resources/templates目录中
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Hello My Thymeleaf</title>
    </head>
    <body>
        <span th:text="|Hello thymeleaf|">Hello html</span>
    </body>
    </html>

    html xmlns属性可以在文档中定义多个命名空间

  3. 修改Controller层
    @Controller
    public class HelloController {
        @RequestMapping("/")
        /**
         * @ResponseBody 注解将被拦截,转化为JSON
         * 移除@ResponseBody,再返回字符串就会告诉SpringMVC要将这个字符串映射为视图名称,而不是在响应中直接描述模型
         * */
    //    @ResponseBody
        public String hello() {
            return "resultPage";
        }
    }

    结果:

2.5 Spring MVC架构

跟踪浏览器所发送的HTTP 请求的行程以及它是如何从服务器端得到响应的。了解整个SpringMVC的核心流程

参考:Spring MVC的核心流程(步骤)https://www.cnblogs.com/Jones-dd/p/8831013.html

2.5.1DispatcherServlet

  • DispatcherServlet是一个典型的HttpServlet 类,它会将HTTP 请求分发给HandlerMapping 。
  • HandlerMapping 会将资源(URL)与控制器关联起来。
  • 控制器上对应的方法(也就是带有@RequestMapping 注解的方法)将会被调用。在这个方法中,控制器会设置模型数据并将视图名称返回给分发器。
  • 然后,DispatcherServlet 将会查询ViewResolver 接口,从而得到对应视图的实现。
  • 在样例中,ThymeleafAutoConfiguration 将会为我们搭建视图解析器。通过查看ThymeleafProperties 类,可以知道视图的默认前缀是“classpath:/templates/”,后缀是“.html”。这就意味着,假设视图名为resultPage,那么视图解析器将会在类路径的templates 目录下查找名为resultPage.html 的文件。
  • 在我们的应用中,ViewResolver 接口是静态的,但是更为高级的实现能够根据请求的头信息或用户的地域信息,返回不同的结果。
  • 视图最终将会被渲染,其结果会写入到响应之中。

2.5.2 将数据传递给视图

修改resultPage.html让其展现来自模型中的信息

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello My Thymeleaf</title>
</head>
<body>
    <span th:text="|Hello thymeleaf|">Hello html</span>
    <span th:text="${message}">Hello html</span>
</body>
</html>
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
    @RequestMapping("/")
    public String hello(Model model) {
        model.addAttribute("message","hello from Controller!");
        return "resultPage";
    }
}

很多对象都可以注入到控制器的方法之中,例如HttpRequest、HttpResponse、Locale、TimeZone 和Principal,其中Principal 代表了一个认证过的用户。完整的对象列表可以在Spring文档中查阅

2.6 Spring 表达式语言--"${}"语法(Spring Expression Language 表达式语言)

https://www.cnblogs.com/xdp-gacl/p/3938361.html

      SpEL不局限于在视图中使用,可以在Spring 框架的各种地方使用,比如使用@Value注解往bean中注入属性时也可使用SpEL

从请求参数中获取数据

  • @RequestParam将参数添加到URL中,请求参数位于URL的?字符之后,使用&符号进行分割。@RequestParam接收的参数是来自requestHeader中,即请求头。通常用于GET请求,像POST、DELETE等其它类型的请求也可以使用。
  • 带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义@PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中。
  • 注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/jsonapplication/xml等类型的数据。通常用于接收POST、DELETE等类型的请求数据,GET类型也可以适用。

2.7 结束Hello Word 开始获取Tweet--无法访问tweet的开发者中心

2.8 Spring MVC的stream流和lambda表达式

Java8 中每个集合都会有一个默认的stream()方法,能实现函数式风格的操作。这些操作可以是中间操作,返回一个流,也可以是终止操作,返回一个值

常用中间操作:

  • map:为列表中的每个元素都应用某个方法,并返回结果所组成的列表
  • filter:返回匹配断言的所有元素
  • reduce:借助一个操作和累加器,将一个列表聚合到单个值上

collect 方法允许我们调用一个终止操作。Collectors 类是一组终止操作,它会将结果放到列表、集合或Map 之中,允许进行分组(grouping)、连接(joining)等操作。

lambda表达式用到只包含一个方法的接口之中(匿名内部类的一种,主要用于替换广泛使用的匿名内部类,比如Thread类,Runnable接口),λ表达式的目标类型是“函数接口(functional interface)”

lambda表达式的组成

 函数式接口:

2.9 使用WebJars实现质感设计

  • 在Controller中实现请求重定向:RedirectAttributes 是一个Spring 的模型,专门用于redirect 场景下传送值
  • Redirect/Forward,只需要在返回的字符串上添加"redirect:"或者"forward:"前缀即可
  • 重定向(URL变化)/转发(URL不变化)

第三章、处理表单和复杂的URL映射

3.1 表单

@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
}

对SpringMVC进行自定义配置,可以实现WebMvcConfigurer 接口,或者扩展WebMvcConfigurerAdapter 类

3.2 校验:

javax.validation.constraints包中的注解
hibernate-validator的jar包中:org.hibernate.validator.constraints中的注解

3.3 国际化

SpringMVC拦截器(Interceptor) 可以类比为Servlet的过滤器,拦截器在Spring应用的上下文中,以bean的形式配置,允许进行自定义的预处理,跳过处理器的执行,以及执行自定义的事后处理;而过滤器和servlet一起在web.xml中配置(现在也可以使用java 进行配置@WebFilter)

第四章、文件上传与错误处理

4.1 上传文件

用户提交的文件将会以MultipartFile 接口的形式注入到控制器中,这个接口提供了多个方法,用来获取文件的名称、大小及其内容。

使用@ConfigurationProperties(prefix=" ")读取用户配置

@ModelAttribute创建模型属性,并且可以通过相同的注解将模型属性注入到Controller当中

@Controller
//将参数定义为会话属性
@SessionAttributes("picturePath")
public class PictureUploadController {
     @ModelAttribute("picturePath")
    public Resource picturePath() {
        return anonymousPicture;
    }
    @RequestMapping(value = "/uploadedPicture")
    public void getUploadedPicture(HttpServletResponse response, @
            ModelAttribute("picturePath") Path picturePath) throws IOException {
        response.setHeader("Content-Type",                 
        URLConnection.guessContentTypeFromName(picturePath.toString()));
        Files.copy(picturePath, response.getOutputStream());
    }

}

问题在于模型属性在不同的请求间会进行重置,因此我们需要将picturePath参数定义为会话属性。可以通过在控制器类上添加@SessionAttributes("picturePath")

4.3 将基本信息放入到会话中

HTTP 会话(session)是用来在请求之间存储信息的一种方式。HTTP 是无状态的协议,这就意味着没有办法将同一用户的两请求关联起来。Servlet 容器最常用的办法是为每个用户关联一个名为JSESSIONID 的cookie。这个cookie将会通过请求头信息进行传输,借助这项技术允许用户将任意的对象存储在Map 中,也就是名为HttpSession 的抽象形式。这样的会话一般情况下会在用户关闭或切换Web浏览器,或者预定时间内用户没有活跃的动作时失效。

在Spring 中,将内容放到会话中的另外一种流行方式就是为bean 添加@Scope("session")注解。这样就能将会话bean注入到控制器中,其他的Spring组件可以为其设值,或者从中检索值;

借助SpringMVC将数据存储到会话中所需要做的工作非常简单:

//创建一个会话bean
@Component
@Scope(value = "session",proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ShoppingCart {
    ...
}
/**
 * @description: 注入一个会话bean
 **/
@Controller
public class ShoppingCartController {
    private ShoppingCart shoppingCart;
    @Autowired
    public ShoppingCartController(ShoppingCart shoppingCart) {
        this.shoppingCart = shoppingCart;
    }
}

关于域注入和构造函数注入地讨论http://olivergierke.de/2013/11/why-field-injection-is-evil/

@Scope(value = "session",proxyMode = ScopedProxyMode.TARGET_CLASS)

proxyMode有三个可用的参数(NO-不创建任何代理;TARGET_CLASS-使用CGLib代理;INTERFACES-使用JDK代理)

当我们将一些内容注入到长期存活的组件中时,例如单例bean;代理的好处就体现出来了。因为注入只会发生一次,bean创建之后,对被注入的bean的后续调用不一定能反应真实状态。

会话bean的实际状态存储在会话之中,并没有直接反应在bean上。这就反映了Spring为什么要创建代理:他需要拦截对bean方法的调用,并监听它的变化。通过这种方式,bean状态的存储和获取就对底层的HTTP会话完全透明了。

对于会话bean,我们必须要使用代理模式。CGLib 代理会对字节码进行instrument 操作,能够用在任意的类上,而JDK 的方式可能会更加轻量级,但是需要你实现一个接口。

会话bean 最好能够实现Serializable接口,因为HTTP会话能够将任意的bean存储在内存之中。

4.4自定义错误页面

处理错误的更高级方式就是定义自己的ErrorController 实现类,这个控制器负责在全局处理所有的异常。可以参考ErrorMvcAutoConfiguration 类和BasicErrorController,这是默认的实现。

4.5 使用矩阵变量进行URL映射

矩阵变量可以映射为URL中不同的对象类型

  • Map<String, List<?>>:这将会处理多个变量的多个值。
  • Map<String, ?>:这会处理一个变量只有一个值的场景。
  • List<?>:如果我们只对一个变量感兴趣,并且变量的名称可以配置的话,可以使用这种方式。
  • someUrl/param?var1=value1&var2=value2
  • 我们可以使用如下的矩阵变量,替换之前的参数:someUrl/param;var1=value1;var2=value2
  • 它还支持将每个参数设置为列表:someUrl/param;var1=value1,value2;var2=value3,value4

默认情况下SpringMVC会移除URL中封号之后的字符,我们需要先关闭这种默认行为

在WebConfiguration类中添加配置

@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
    UrlPathHelper urlPathHelper = new UrlPathHelper();
    urlPathHelper.setRemoveSemicolonContent(false);
    configurer.setUrlPathHelper(urlPathHelper);
}

然后使用@MatrixVariable(pathVar="ByCriteria") Map<String, List<String>> filterParams 接收参数。

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值