• 【书籍篇】Spring实战第4版 第2部分 Web中的Spring



    读前须知: 本篇章内容取自《Spring实战第4版》 P135~P223,如需更多详细内容请购买正版书籍
    上一章节: 【书籍篇】Spring实战第4版 第1部分 Spring的核心
    下一章节: 【书籍篇】Spring实战第4版 第2部分 Web中的Spring(二)


    五. 构建Spring Web应用程序

    5.1 SpirngMVC请求流程

    web浏览器发送请求
    第一站:前端控制器(DispatcherServlet),其作用是将从处理器映射(handler mapping)获取请求的下一站是哪里(哪个控制器)。
    第二站:将请求数据交由控制器处理(controller)或者是控制器将业务逻辑委托给一个或多个服务对象处理,
    	   处理完的数据称为模型(model),再进行友好的方式进行格式化,最后发送给视图(view)
    第三站:视图渲染数据响应给web浏览器。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.2 搭建Spring MVC

    5.2.1 配置DispatcherServlet

    public class SpittrWebAppInitializer
    	extends AbstractAnnotationConfigDispatcherServletInitializer {
        @Override
        protected String[] getServletMappings() {
            return new String[] {"/"};	// 将DispatcherServlet映射到"/"
        }
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class<?>[] {RootConfig.class};
        }
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class<?>[] {WebConfig.class};
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5.2.2 配置WebConfig

    @Configuration
    @EnableWebMvc
    public class WebConfig {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.2.3 配置RootConfig

    @Configuration
    @ComponentScan(basePackages={"spittr"}, 
        excludeFilters={
            @Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)
    })
    public class RootConfig {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5.3 编写基本的控制器

    @Controller		// 声明为一个控制器
    public class DemoController {
        @RequestMapping(value="/", method=GET)	// 处理对"/"的Get请求
        public String demo() {
           return "demo";		// 发送给视图“demo”
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5.4 Spittr首页

    略。。。详细可从书中p144获知

    5.6 复杂的控制器

    5.6.1 定义类级别的请求处理

    @Controller
    @RequestMapping("/")
    public class DemoController {
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.6.2 传递模型数据到视图中

    略。。。详细可从书中p147获知

    5.6.3 接受请求的输入

    @Controller
    @RequestMapping("/")
    public class DemoController {
        
        @Autowired
        private DemoService demoService;
        
    	@RequestMapping(value="/getList", method=GET)
        public List<String> getList(@RequestParam("conut") long count) {  
           return demoService.selectByCount(count);
        }
        
        @RequestMapping(value="/{id}", method=GET)
        public List<String> getObj(@PathVariable("id") long id) {  
           return demoService.selectById(id);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    5.6.4 处理表单

    略。。。详细可从书中p158获知

    5.6.5 校验表单

    在Spring MVC中提供了对java校验API的支持,详细可从书中p164获知或百度

    public class Demo {
        @NotNull
        @Size(min=5, max=16)
        private Long id;
        ...
    }
    
    @Controller
    @RequestMapping("/")
    public class DemoController {
        @RequestMapping(value="/valid", method=POST)
    	public Boolean valid(@Valid Demo demo, Errors errors) {
            if (errors.hasErrors()) {
                return false;
            }
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    六. 渲染Web视图

    6.1 视图解析器

    Spring自带了13个视图解析器

    视图解析器描述
    BeanNameViewResolver将视图解析为Spring应用上下文中的bean,其中bean的ID与视图的名字相同
    ContentNegotiatingViewResolver通过考虑客户端的内容类型来解析视图,委托给另一个能够产生对应内容类型的视图解析器
    FreeMarkerViewResolver将视图解析为FreeMarker模板
    InternalResourceViewResolver将视图解析为Web应用的内部资源(一般为JSP)
    JasperReportsViewResolver将视图解析为JasperReports定义
    ResourceBundleViewResolver将视图解析为资源bundle(一般为属性文件)
    TilesViewResolver将视图解析为Apache Tiles定义,其中tile ID与视图名称相同(注意有两个不同的TilesViewResolver实现,分别对应Tiles 2.0 和 Tiles 3.0)
    UrlBasedViewResolver直接更具视图的名称解析视图,视图的名称会匹配一个物理视图的定义
    VelocityLayoutViewResolver将视图解析为Velocity布局,从不同的Velocity模板中组合页面
    VelocityViewResolver将视图解析为Velocity模板
    XmlViewResolver将视图解析为XML文件中bean的定义(类似于BeanNameViewResolver)
    XsltViewReslover将视图解析为XSLT转换后的结果
    ThymeleafViewResolver将逻辑视图名称解析为Thymeleaf模板视图

    6.2 创建JSP视图

    6.2.1 配置InternalResourceViewResolver

    @bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INFO/views/");
        resolver.setSuffix(".jsp");
        // 解析JSTL标签
        resolver.setViewClass("org.springframework.web.servlet.view.JstlView.class");
        return resolver;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    <bean id="viewResolver"  class= "org.springframework.web.servlet.view.InternalResourceViewResolver" 
          p:prefix="/WEB-INFO/views/" p:suffix=".jsp" 
          p:viewClass="org.springframework.web.servlet.view.JstlView" />
    
    • 1
    • 2
    • 3

    6.2.2 使用Spring的JSP库

    
    <%@ tagblib uri="http://wwww.springframwork.org/tags/form" prefix="sf" %>
    
    • 1
    • 2

    6.2.3 Spring通用标签库

    <%@ tagblib uri="http://wwww.springframwork.org/tags" prefix="s" %>
    
    • 1

    6.2.4 展示国际化信息

    • 1
    • 2
    • 3
    @Bean
    public MessageSource messageSource() {
    	ResourceBunleMessageSource messageSource = new ResourceBunleMessageSource();
        messageSource.setBeanname("message");
        return messageSource;
    }
    
    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBunleMessageSource messageSource = new ReloadableResourceBunleMessageSource();
        messageSource.setBasename("file://etc/spittr/messages");	// 类路径以 classpath: 为前缀
        messageSource.setCacheSeconds(10);
        return messageSource;
    }
    
    // en.properties
    spittr.welcome=Welcome to Spittr!
        
    // zh.properties
    spittr.welcome=欢迎来到Spittr!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    6.2.5 创建URL

    。。。详细可从书中p182获知
    
    • 1

    6.2.6 转义

    。。。详细可从书中p184获知
    
    • 1

    6.3 使用Apache Tiles视图定义布局

    6.3.1 配置Tile视图解析器

    @Bean
    public TilesConfigurer tilesConfigurer() {
        TilesConfigurer tiles = new TilesConfigurer();
        // 指定Tile的定义的位置	"/WEB-INFO/**/tiles.xml"	
        tiles.setDefinitions(new String[] {
            "/WEB-INFO/layout/tiles.xml"	
        });
        // 启用刷新功能
        tiles.setCheckRefresh(true);
        return tiles;
    }
    
    @Bean
    public ViewResolver viewResolver() {
        return new TilesViewResolver();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
    	<property name="definitions">
        	<list>
            	<value>/WEB-INFO/layout/tiles.xmlvalue>
                <value>/WEB-INFO/**/tiles.xmlvalue>
            list>
        property>
    bean>
    
    <bean id="viewResolver" class="org.springframework.web.servlet.view.tiles3.ViewResolver" />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6.3.2 定义Tiles

    <xml version="1.0" encoding="UTF-8">
    <DOCTYPE tiles-definitions PUBLIC
    	"...">
    <tiles-definitions>
        
    	<definition name="base" template="/WEB-INF/layout/page.jsp">
            
        	<put-attribute name="body" value="/WEB-INF/layout/header.jsp" />
            <put-attribute name="footer" value="/WEB-INF/layout/footer.jsp" />
        definition>
    
    	
    	<definition name="home" template="/WEB-INF/layout/home.jsp">
            
        	<put-attribute name="body" value="/WEB-INF/layout/home.jsp" />
        definition>
    tiles-definitions>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    6.3.3 主布局模板

    <%@ tagblib uri="http://wwww.springframwork.org/tags" prefix="s" %>
    <%@ tagblib uri="tiles.apache.org/tags-tiles" prefix="t" %>
    
    
        
            ...
        
        
            
            
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    6.4 使用Thymeleaf模板

    略。。。详细可从书中p190~196获知

    6.4.1 配置Thymeleaf视图解析器

    6.4.2 定义Thymeleaf模板

    6.4.3 借助Thymeleaf实现表单绑定

    七. Spring MVC的高级技术

    7.1 Spring MVC配置的替代方案

    略。。。详细可从书中p200~205获知

    7.1.1 自定义DispacherServlet配置

    7.1.2 添加其他Servlet和Filter

    7.1.3 web.xml中声明DispatcherServlet

    7.1.4 web.xml中使用基于java的配置

    7.2 处理Multipart形式的数据

    7.2.1 配置multipart解析器

    从Spring3.1开始,Spring内置了两个MultipartResolver的实现供我们选择

    multipart解析器描述
    CommonsMultipartResolver使用Jakarta Commons FileUpload解析multipart请求
    StandardServletMultipartResolver依赖于servlet3.0对multipart请求的支持

    7.2.2 StandardServletMultipartResolver

    @bean
    public MultipartResolver multipartResolver() throws IOException {
        return new StandardServletMultipartResolver();
    }
    
    • 1
    • 2
    • 3
    • 4
    // java配置
    @Override
    protected void custiomizeRegistration(Dynamic registration) {
        // 临时路径,文件大小不超过2MB,整个请求不超过4MB,所有文件都写入磁盘
        registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"2096000, 4192000, 0));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    
    <servlet>
    	<servlet-name>appServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <load-on-startup>1load-on-startup>
        <multipart-config>
        	<location>/tmp/spittr/uploadslocation>
            <max-file-size>2096000max-file-size>
            <max-request-size>4192000max-request-size>
        multipart-config>
    servlet>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    7.2.3 CommonsMultipartResolver

    @bean
    public MultipartResolver multipartResolver() throws IOException {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads"));	// 临时路径
        resolver.setMaxUploadSize(2096000);		// 最大的文件容量
        resolver.setMaxInMemorySize(0);		// 最大的内存大小
        return resolver;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.3 处理Multipart请求

    ... ...
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    // 方式一:无法获取文件信息
    @RequestMapping(value="/register", method=POST)
    public String processRegistration(
    	@RequestPart("profilePicture") btye[] profilePicture,
        @Valid Spitter spitter,
        Errors errors) {
        ...
    }
    
    // 方式二:使用part,能获取文件信息
    @RequestMapping(value="/register", method=POST)
    public String processRegistration(
    	@RequestPart("profilePicture") Part profilePicture,
        @Valid Spitter spitter,
        Errors errors) {
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    7.4 处理异常

    7.4.1 异常映射HTTP状态码

    @ResponseStatus(value=HttpStatus.NOT_FOUND, reson="Spittle Not Found")
    public class SpitterNotFoundException extends RuntimeException {
        ...
    }
    
    • 1
    • 2
    • 3
    • 4

    7.4.2 异常处理方法

    // 方式一
    @RequestMapping(method=POST)
    public String saveSpitter(SpittleForm form, Model model) {
        try {
            spittleRepository.save(new Spittle(null, form.getName()));
        	return "redirect:/spittles";
        } catch (DuplicateSpittleException e) {
            return "error/duplicate";
        }
    }
    
    
    // 方式二
    // 该控制器里的方法抛出DuplicateSpittleException异常就会调用handleDuplicateSpittle()方法来处理异常
    @RequestMapping(method=POST)
    public String saveSpitter(SpittleForm form, Model model) {
        spittleRepository.save(new Spittle(null, form.getName()));
        return "redirect:/spittles";
    }
    	
    @ExceptionHandler(DuplicateSpittleException.class)
    public String handleDuplicateSpittle() {
        return "error/duplicate";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    7.4.3 为控制器添加通知

    // 任意控制器抛出DuplicateSpittleException异常都会调用handleDuplicateSpittle()方法来处理异常
    @ControllerAdvice
    public class AppWideExceptionHandller {
        @ExceptionHandler(DuplicateSpittleException.class)
        public String handleDuplicateSpittle() {
            return "error/duplicate";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.5 跨重定向请求传递数据

    跨重定向请求传递数据
    使用URL模板以路径变量或查询参数的形式传递数据
    通过flash属性发送数据

    7.5.1 使用URL传递

    @RequestMapping(value="/register", method=POST)
    public String processRegistration(Spitter spitter, Model model) {
        spittleRepository.save(Spitter);
        model.adddAttribute("name", Spitter.getName());
        return "redirect:/spittles/{name}";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    7.5.2 使用flash传递

    @RequestMapping(value="/register", method=POST)
    public String processRegistration(Spitter spitter, Model model) {
        spittleRepository.save(spitter);
        model.adddAttribute("name", spitter.getName());
        model.adddFlashAttribute("spitter", spitter);
        return "redirect:/spittles/{name}";
    }
    
    @RequestMapping(value="/{name}", method=GET)
    public String showSpitterProfile(@PathVariable String name, Model model) {
        if (!model.contaionsAttribute("spitter")) {
            model.adAttribute(spittleRepository.findByName(name));
        }
        return "profile";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    Spring IOC复习与回顾
    Unity DOTS系列之Filter Baking Output与Prefab In Baking核心分析
    线程的生命周期
    找单身狗2
    23【状态设计模式】
    内部类杂记
    LINUX下查看CPU负载的所有命令
    1043 输出PATest
    基于python的pdf版本的PPT转换为office PPT
    Rb(redis blaster),一个为 redis 实现 non-replicated 分片的 python 库
  • 原文地址:https://blog.csdn.net/TheNew_One/article/details/134258365