SpringMVC2

六. RESTful SpringMVC CRUD

注意:Handel需要添加@Controller

1. 显示信息

– URI:emps
– 请求方式:GET

jsp:
<a href="emps">List All Employees</a>

handle:
@RequestMapping("/emps")
    public String list(Map<String,Object> map){
        map.put("employees",employeeDao.getAll());
        return "list";
    }

通过RequestMapping结合视图跳转到list的jsp,将查询获得的信息存到map中,在jsp的中打印

list.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    <script type="text/javascript">
           $(function () {
                $(".delete").click(function () {
                    var href=$(this).attr("href");
                    $("form").attr("action",href).submit();
                    return false;
                })
            }
           )
    </script>
</head>
<body>

<form action="" method="POST">
    <input type="hidden" name="_method" value="DELETE">
</form>

<c:if test="${empty requestScope.employees}">
    没有任何员工信息
</c:if>
<c:if test="${!empty requestScope.employees}">
    <table border="1" cellpadding="10" cellspacing="0">
        <tr>
            <th>ID</th>
            <th>LastName</th>
            <th>Email</th>
            <th>Gender</th>
            <th>Department</th>
            <th>Edit</th>
            <th>Delete</th>
        </tr>
        <c:forEach items="${requestScope.employees}" var="emp">
            <tr>
                <td>${emp.id}</td>
                <td>${emp.lastName}</td>
                <td>${emp.email}</td>
                <td>${emp.gender==0?'Female':'Male'}</td>
                <td>${emp.department.departmentName}</td>
                <td><a href="emp/${emp.id}">Edit</a></td>
                <td><a class="delete" href="emp/${emp.id}">Delete</a></td>
            </tr>
        </c:forEach>
    </table>
</c:if>
<br/><br/>

<a href="emp">Add New Employee</a>
</body>
</html>
2.添加信息

– 显示添加页面:
• URI:emp
• 请求方式:GET

jsp:
<a href="emp">Add New Employee</a>

handle:
@RequestMapping(value = "/emp",method = RequestMethod.GET)
    public String input(Map<String,Object> map){
        map.put("departments",departmentDao.getDepartments());
        map.put("employee",new Employee());
        return "input";
    }

跳转到input.jsp填写表单,来获取添加的信息,获取的departments为表单中的需要的地址所有选项,employee用来绑定表单对应的对象。

3. 删除操作

– URL:emp/{id}
– 请求方式:DELETE

jsp:
<td><a class="delete" href="emp/${emp.id}">Delete</a></td>

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    <script type="text/javascript">
           $(function () {
                $(".delete").click(function () {
                    var href=$(this).attr("href");
                    $("form").attr("action",href).submit();
                    return false;
                })
            }
           )
    </script>

handle:
@RequestMapping(value = "/emp/{id}",method = RequestMethod.DELETE)
    public String delete(@PathVariable("id") Integer id){
        employeeDao.delete(id);
        return "redirect:/emps";
    }

delete方式只能由post提交方式返回,所以需要JavaScript来进行表单提交方式的修改,handle中拿到需要删除的id,删除后,重定向返回list.jsp

4. 修改操作:存在某个主键不可修改

– 显示修改页面:
• URI:emp/{id}
• 请求方式:GET

– 修改员工信息:
• URI:emp
• 请求方式:PUT

跳转到修改的表单提交页面

 @RequestMapping(value = "/emp/{id}",method = RequestMethod.GET)
    public String input(@PathVariable("id") Integer id,Map<String,Object> map){
        map.put("employee",employeeDao.get(id));
        map.put("departments",departmentDao.getDepartments());
        return "input";
    }

由前端传入的id从数据库得到对应对象传入map,然后跳转到input页面,input的选择标签会区分添加和修改,然后通过不同的表单提交方式转入不同的操作

handle中修改

@RequestMapping(value = "/emp",method = RequestMethod.PUT)
    public String update(Employee employee){
        employeeDao.change(employee);
        return "redirect:/emps";
    }

数据库修改以后,重定向跳转到表单

七.Spring 的表单标签和静态资源的处理

1.form标签

通过 SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显
为什么使用form标签
可以更快速的开发表单页面,而且可以更方便的进行表单值的回显 注意:
可以通过modelAttribute属性指定绑定的模型属性,若没有指定该属性,则默认从request域对象中读取command的表单bean

2.共有属性

SpringMVC 提供了多个表单组件标签,如 、 等,用以绑定表单字段的
属性值,它们的共有属性如下: – path:表单字段,对应 html 元素的 name 属性,支持级联属性 –
htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值 为 true – cssClass:表单组件对应的 CSS
样式类名 – cssErrorClass:表单组件的数据存在错误时,采取的 CSS 样式

3.表单标签

• form:input、form:password、form:hidden、form:textarea :对应 HTML 表单的
text、password、hidden、textarea 标签 • form:radiobutton:单选框组件标签,当表单 bean
对应的 属性值和 value 值相等时,单选框被选中 • form:radiobuttons:单选框组标签,用于构造多个单选 框 –
items:可以是一个 List、String[] 或 Map – itemValue:指定 radio 的 value 值。可以是集合中
bean 的一个 属性值 – itemLabel:指定 radio 的 label 值 – delimiter:多个单选框可以通过
delimiter 指定分隔符 • form:checkbox:复选框组件。用于构造单个复选框 •
form:checkboxs:用于构造多个复选框。使用方式同 form:radiobuttons 标签 •
form:select:用于构造下拉框组件。使用方式同 form:radiobuttons 标签 •
form:option:下拉框选项组件标签。使用方式同 form:radiobuttons 标签 •
form:errors:显示表单组件或数据校验所对应的错误 –

4.处理静态资源

SpringMVC处理静态资源:
1.为什么会有这样的问题: 优雅的REST风格的资源URL不希望带.html或.do等后缀若将DispatcherServlet请求映射配置为/,则SpringMVC将捕获WEB容器的所有请求,包括静态的资源,SpringMVC会将他们当成一个普通请求处理,因找不到对应处理器将导致错误
2.解决: 在SpringMVC的配置文件中配置文件中配置

八.数据处理

1.数据类型转换
        表单提取的字符串怎么变成我们需要的对象的?
            Spring MVC 主框架将 ServletRequest 对象及目标方
            法的入参实例传递给 WebDataBinderFactory 实例,以创
            建 DataBinder 实例对象
            • 2. DataBinder 调用装配在 Spring MVC 上下文中的
            ConversionService 组件进行数据类型转换、数据格式
            化工作。将 Servlet 中的请求信息填充到入参对象中
            • 3. 调用 Validator 组件对已经绑定了请求消息的入参对象
            进行数据合法性校验,并最终生成数据绑定结果
            BindingData 对象
            • 4. Spring MVC 抽取 BindingResult 中的入参对象和校验
            错误对象,将它们赋给处理方法的响应入参
            •5.关于mvc:annotation-driven
             <mvc:annotation-driven /> 会自动注册RequestMappingHandlerMapping
            、RequestMappingHandlerAdapter 与ExceptionHandlerExceptionResolver 三个bean。
            • 还将提供以下支持:
            – 支持使用 ConversionService 实例对表单参数进行类型转换
            – 支持使用 @NumberFormat annotation、@DateTimeFormat注解完成数据类型的格式化
            – 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
            – 支持使用 @RequestBody 和 @ResponseBody 注解
2.数据类型格式化
        • 对属性对象的输入/输出进行格式化,从其本质上讲依然
        属于 “类型转换” 的范畴。
        • Spring 在格式化模块中定义了一个实现
        ConversionService 接口的
        FormattingConversionService 实现类,该实现类扩展
        了 GenericConversionService,因此它既具有类型转换的
        功能,又具有格式化的功能
        • FormattingConversionService 拥有一个
        FormattingConversionServiceFactroyBean 工厂类,
        后者用于在 Spring 上下文中构造前者
3.数据效验
        (1).如何效验?使用注解?
            ①.使用JSR 303验证标准
            ②.加入hibernate validator验证框架的jar包或者maven依赖
            ③.在SpringMVC配置文件中添加 <mvc:annotation-driven/>
            ④.需要在bean的属性上添加对应的注解
            ⑤.需要在目标方法bean类型的前面添加@Valid注解
        (2).验证出错转向到哪一个页面?
            注意:需效验的Bean对象和其绑定结果对象或错误对象时成对出现的,他们之间不允许声明其他的入参
        (3).错误消息?如果显示,如何把错误消息进行国际化

九.处理 JSON

步骤:
• 1. 加入 jar 包
• 2. 编写目标方法,使其返回 JSON 对应的对象或集合
• 3. 在方法上添加 @ResponseBody 注解

jsp:
<a href="testJson" id="testJson">Test Json</a>

 <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    <script type="text/javascript">
        $(function(){
            $("#testJson").click(
                function () {
                    var url=this.href;
                    var args={};
                    $.post(url,args,function (data) {
                        for(var i=0;i<data.length;i++){
                            var id=data[i].id;
                            var  lastName=data[i].lastName;
                            alert(id+": "+lastName)
                        }
                    })
                    return false;
                }
            )
        })
</script>

handle:
@ResponseBody
@RequestMapping("/testJson")
 public Collection<Employee> testJson(){
     return employeeDao.getAll();
 }

直接返回json对象给jsp进行alter打印

@RequestBody、@ResponseBody 示例

jsp:
<form action="testHttpMessageConverter" method="post" enctype="multipart/form-data">
        File:<input type="file" name="file"/><br/>
        Desc:<input type="text" name="desc"/><br/>
        <input type="submit" value="Submit">
</form>

handle:
 @ResponseBody
    @RequestMapping("/testHttpMessageConverter")
    public String testHttpMessageConverter(@RequestBody String body){
        System.out.println(body);
        return "hello world! "+new Date();
    }

十.国际化

1.国际化概述

默认情况下,SpringMVC 根据 Accept-Language 参数 判断客户端的本地化类型。
当接受到请求时,SpringMVC 会在上下文中查找一个本 地化解析器(LocalResolver),找到后使用它获取请求所对应的本地化类型信息。
SpringMVC 还允许装配一个动态更改本地化类型的拦截 器,这样通过指定一个请求参数就可以控制单个请求的本地化类型。

关于国际化:
1.在页面上能够根据浏览器语言设置的情况对文本(不是内容),时间,数值进行本地化处理
2.可以在bean中获取国际化资源文件Locale对应的消息
3.可以通过超链接切换Locale,而不再依赖于浏览器的语言设置情况

     解决:
        1.使用JSTL的fmt标签
        2.在bean中注入ResourceBundleMessageSource的示例,使用其对应的getMessage方法即可
        3.配置LocalResolver和LocaleChangeInterceptor
<!--配置国际化资源文件-->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n"/>
    </bean>

    <mvc:view-controller path="/i18n" view-name="i18n"/>
    <mvc:view-controller path="/i18n2" view-name="i18n2"/>

十一.文件上传

Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 
MultipartResolver 实现的。Spring 用Jakarta Commons FileUpload 
技术实现了一个MultipartResolver 实现类:CommonsMultipartResovler

Spring MVC 上下文中默认没有装配 MultipartResovler,因此默认情况下
不能处理文件的上传工作,如果想使用 Spring的文件上传功能,需现在上下文
中配置 MultipartResolver
1.配置 MultipartResolver
• defaultEncoding: 必须和用户 JSP 的 pageEncoding 属性
一致,以便正确解析表单的内容
• 为了让 CommonsMultipartResovler 正确工作,必须先
将 Jakarta Commons FileUpload 及 Jakarta Commons io
的类包添加到类路径下。

 <!--配置commonsMultipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="maxInMemorySize" value="1024000"/>
    </bean>
jsp:
<form action="testFileUpload" method="post" enctype="multipart/form-data">
        File:<input type="file" name="file"/><br/>
        Desc:<input type="text" name="desc"/><br/>
        <input type="submit" value="Submit">
    </form>

handle:
@RequestMapping("/testFileUpload")
    public String testFileUpload(@RequestParam("desc") String desc, @RequestParam("file")MultipartFile file) throws IOException {
        System.out.println("desc: "+desc);
        System.out.println("originalFilename: "+file.getOriginalFilename());
        System.out.println("inputStream: "+file.getInputStream());
        return "success";
    }

十二.拦截器

Spring MVC也可以使用拦截器对请求进行拦截处理,用户
可以自定义拦截器来实现特定的功能,自定义的拦截器必
须实现HandlerInterceptor接口
– preHandle():这个方法在业务处理器处理请求之前被调用,在该
方法中对用户请求 request 进行处理。如果程序员决定该拦截器对
请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去
进行处理,则返回true;如果程序员决定不需要再调用其他的组件
去处理请求,则返回false。
– postHandle():这个方法在业务处理器处理完请求后,但
是DispatcherServlet 向客户端返回响应前被调用,在该方法中对
用户请求request进行处理。
– afterCompletion():这个方法在 DispatcherServlet 完全处理完请
求后被调用,可以在该方法中进行一些资源清理的操作。

配置自定义拦截器

<mvc:interceptors>
        <!--自定义拦截-->
        <!--配置自定义的拦截器-->
        <bean class="com.itlc.springMVC.interceptors.FirstInterceptor"/>

        <!--配置拦截器作用(不作用)的路径-->
        <mvc:interceptor>
            <!--配置SecondInterceptor作用的路径-->
            <mvc:mapping path="/emps"/>
            <!--配置SecondInterceptor不作用的路径-->
            <mvc:exclude-mapping path="/emp"/>
            <bean class="com.itlc.springMVC.interceptors.SecondInterceptor"/>
        </mvc:interceptor>

        <!--配置LocaleChangeInterceptor-->
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    </mvc:interceptors>

自定义类

public class FirstInterceptor implements HandlerInterceptor{

    /*
        该方法在目标方法之前被调用。
        若返回值为true,则继续调用后续的拦截器和目标方法
        若返回值为false,则不会再调用后续的拦截器和目标方法

        可以考虑做权限,日志,事务等。
    */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("1preHandle");
        return true;
    }

    /*
        调用目标方法之后,但渲染视图之前

        可以对请求域中的属性或视图做出修改
    */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("1postHandle");
    }

    /*
       渲染视图之后调用

       释放资源
   */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("1afterCompletion");
    }
}

十三.异常处理

Spring MVC 通过 HandlerExceptionResolver 处理程序
的异常,包括 Handler 映射、数据绑定以及目标方法执行
时发生的异常。
SpringMVC 提供的 HandlerExceptionResolver 的实现类

jsp:
 <a href="testExceptionHandlerExceptionResolver?i=0">Test ExceptionHandlerExceptionResolver</a>


handle:
@ExceptionHandler({ArithmeticException.class})
    public ModelAndView handleArithmeticException(Exception ex){
        System.out.println("Arithmetic异常:" + ex);
        ModelAndView mv=new ModelAndView("error");
        mv.addObject("exception",ex);
        return mv;
    }

    @ExceptionHandler({RuntimeException.class})
    public ModelAndView handleArithmeticException2(Exception ex){
        System.out.println("Runtime异常:" + ex);
        ModelAndView mv=new ModelAndView("error");
        mv.addObject("exception",ex);
        return mv;
    }

 @RequestMapping("/testExceptionHandlerExceptionResolver")
    public String testExceptionHandlerExceptionResolver(@RequestParam("i") Integer i){
        System.out.println(10/i);
        return "success";
    }

若无@ExceptionHandler配置,并标签内部参数对应异常的方法,浏览器报404;若有,则跳到这个方法中对异常进行处理。
1.在@ExceptionHandler方法的入参中可以加入Exception类型的参数,该参数即对应发生的异常对象
2.@ExceptionHandler方法的入参中不能传入Map,若希望把异常信息传到页面上,需要使用
ModelAndView作为返回值
3.@ExceptionHandler方法标记的异常有优先级的问题,在当前Handle中匹配程度最高的
ExceptionHandler优先
4.@ControllerAdvice:如果在当前Handle中找不到@ExceptionHandler方法来处理当前方法产生的异常,则会去@ControllerAdvice标记的类中查找@ExceptionHandler标记的方法来处理异常

2.ResponseStatusExceptionResolver
• 在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。
• 定义一个 @ResponseStatus 注解修饰的异常类

//加入@ResponseStatus可以设置状态码的错误信息
@ResponseStatus(value = HttpStatus.FORBIDDEN , reason = "lalalal")
public class MyException extends RuntimeException {
    private static final long serialVersionUID=1L;
}

若在处理器方法中抛出了上述异常:若ExceptionHandlerExceptionResolver 不解析述异常。由于触发的异常 UnauthorizedException 带有@ResponseStatus注解。因此会被ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 代码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。

3.SimpleMappingExceptionResolver
• 如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常。

十四.在Spring环境下使用SpringMVC

需要Spring整合SpringMVC吗?
还是否需要再加入Spring的IOC容器?
是否需要web.xml文件中配置启动Spring IOC容器的ContextLoaderListener?

    需要:通常情况下,类似于数据源,事务,整合其他框架都是放在Spring的配置文件中的,
    而不是放在SpringMVC的配置文件中,实际上放入Spring配置文件对应的IOC容器中的还有
    Service和Dao。

    不需要:都放在SpringMVC的配置文件中也可以,也可以分多个Spring的配置文件,然后使
    用import节点导入其他的配置文件

问题:若Spring的IOC容器和SpringMVC的IOC容器扫描的包有重合的部分,就会导致有的bean
会被创建两次。
解决方法:
1.使Spring的IOC容器和使SpringMVC的IOC容器扫描的包没有重合的部分
2.使用exclude-filter和include-filter子节点来规定只能扫描的注解
选择第二种方法。

 <!--配置扫描器-->
    <context:component-scan base-package="com.itlc.springMVC3">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>

注意:SpringMVC的IOC容器中的bean来引用Spring IOC容器中的bean
反过来了? 不行,Spring的IOC容器中的bean不能来引用SpringMVC IOC容器中的bean
只有控制层能引用业务层,业务层不能引用控制层

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值