上传与下载

一、Jackson解析

概述

jackson解析,是基于返回的json数据中属性的显示形式。

使用Jackson解析,需要导入依赖包。

应用

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @JsonProperty("new_id")
    private  Integer id; //改ID的别名
    @JsonIgnore  //忽略该属性
    private  String name;
    @JsonInclude(JsonInclude.Include.NON_NULL) //null值 属性不输出
    private  String password;
    //解析之后的日期格式
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date birth;

    @JsonInclude(value= JsonInclude.Include.NON_EMPTY)  // 若hobby长度为0或==null 忽略此属性
    private List<String> hobby;
}

自定义序列化

自定义序列化,表示可以自己定义属性的配置效果

//实体属性----
//主要针对属性进行格式处理; 不常用,可以在前端使用jstl格式库来处理
@JsonSerialize(using = MySerializer.class)
private Double salary; //10000.126 在输出此属性时,使用MySerializer输出
//序列化接口
public class MySerializer extends JsonSerializer<Double> {
    @Override
    public void serialize(Double value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
        // 将Double salary的值 四舍五入
        String number = BigDecimal.valueOf(value).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        // 输出 四舍五入后的值
        gen.writeNumber(number); //值会注入到User实体属性中
    }
}

二、异常解析器

概述

如果没有异常解析器,那么我们目标handler中如果有异常,每个handler中都要处理

如果有了异常解析器,则可以统一在解析器中进行处理异常。

配置

public class MyExResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        e.printStackTrace();//打印异常
        ModelAndView mav = new ModelAndView();
        //根据不同的异常类型,重定向到不同的处理页面
        if(e instanceof NullPointerException){
            mav.setViewName("redirect:/err1.jsp");
        }else if(e instanceof ArithmeticException){
            mav.setViewName("redirect:/err2.jsp");
        }else{
            mav.setViewName("redirect:/err3.jsp");
        }
        return mav;
    }
}

需要在mvc容器中产生bean:

<!-- 异常解析器的bean -->
<bean class="com.qf.ex.MyExResolver"></bean>

三、拦截器

概述

与web中的过滤器一致,在访问目标资源前的一道拦截技术

应用场景:可以统一的编码处理及权限验证

应用

案例:如果没有登录凭证,则无法进入到目标handler。

拦截器中的权限配置:

//拦截器的类
public class MyInter implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器...");
        //在访问目标handler之前进行的触发
        String username = (String) request.getSession().getAttribute("username");
        if(username==null){ //没有登录凭证,则跳转到登录
            response.sendRedirect("/login.jsp"); //重定向
            return  false;
        }
        return true; //此处如果返回false则进行拦截;返回true放行
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //在handler之后执行:进一步的响应定制
        System.out.println("post...");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //在页面渲染完毕之后,执行:资源回收
        System.out.println("after...");
    }
}

mvc容器中进行拦截路径的筛选:

<!-- 拦截器的配置... -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/json/**"/> <!--拦截json下的所有路径-->
        <mvc:exclude-mapping path="/json/login"/><!--不拦截login -->
        <!-- 绑定拦截器的bean -->
        <bean class="com.qf.inter.MyInter"></bean> 
    </mvc:interceptor>
</mvc:interceptors>

在目标handler中可以进行登录与测试:

@RequestMapping("/hello")
public String hello(){
    System.out.println("访问到目标handler");
    return  "ok";
}
@RequestMapping("/login")
public String login(HttpSession session){
    System.out.println("登录成功~");
    session.setAttribute("username","zs");
    return  "ok";
}

四、上传

概述

上传功能,需要从前端传二进制资源到服务器中

前端配置

<%--请求方式:post  enctype:编码类型为multipart/form-data --%>
<form action="/upload/test1" method="post" enctype="multipart/form-data">
   文件上传:<input type="file" name="source" /><br>
   <input type="submit" value="提交">
</form>

后端配置

后端控制层配置:

@RestController
@RequestMapping("/upload")
public class UploadController {
    @RequestMapping("/test1") //从file控件中得到二进制资源
    public String test1(MultipartFile source, HttpSession session) throws IOException {
        String fileName = source.getOriginalFilename(); //获取文件名
        //为了安全性,可以设置uuid名字前缀  xxdfff_a.jpg
        //String uuidName = UUID.randomUUID().toString()+"_"+fileName;

        System.out.println("fileName:"+fileName);
        //文件上传,往往上传到项目指定路径  获取真实路径-带盘符
        String realPath = session.getServletContext().getRealPath("/upload");
        System.out.println("真实路径:"+realPath);
        File dir = new File(realPath); //封装成File对象
        if(!dir.exists()){ //判断目录不存在,则创建
            System.out.println("不存在,则创建目录");
            dir.mkdirs();
        }
        source.transferTo(new File(dir,fileName));  //上传图片完成
        return "ok";
    }
}

mvc容器配置上传解析:

<!-- 上传解析器
      id必须是:“multipartResolver”
 -->
<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 最大可上传的文件大小  单位:byte  超出后会抛出MaxUploadSizeExceededException异常,可以异常解析器捕获 -->
    <property name="maxUploadSize" value="1048576"></property>
</bean>

导入上传的依赖:

<!-- 上传的依赖 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>
</dependencies>

五、下载

从服务器中下载资源。

前端

<a href="/download/test1?name=006.png">下载</a>

后端

@RestController
@RequestMapping("/download")
public class DownloadController {
    @RequestMapping("/test1")
    public void test1(String name, HttpSession session, HttpServletResponse response) throws IOException {
        System.out.println(name);
        //获取真实路径
        String realPath = session.getServletContext().getRealPath("/upload");
        System.out.println(realPath);
        String path = realPath+"/"+name;  //拼接

        //设置响应头  告知浏览器,要以附件的形式保存内容   filename=浏览器显示的下载文件名
        response.setHeader("content-disposition","attachment;filename="+name);
        //先读取到输入流,后写到响应的输出流
        IOUtils.copy(new FileInputStream(path),response.getOutputStream());
    }
}

六、验证码

导包

导入验证码包:

<!-- Kaptcha -->
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

映射路径

<!-- 配置映射路径 -->
<servlet>
    <servlet-name>cap</servlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
    <init-param>
        <param-name>kaptcha.border</param-name>
        <param-value>no</param-value>
    </init-param>
    <init-param>
        <param-name>kaptcha.textproducer.char.length</param-name>
        <param-value>4</param-value>
    </init-param>
    <init-param>
        <param-name>kaptcha.textproducer.char.string</param-name>
        <param-value>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</param-value>
    </init-param>
    <init-param>
        <param-name>kaptcha.background.clear.to</param-name>
        <param-value>211,229,237</param-value>
    </init-param>
    <init-param>
        <!-- session.setAttribute("captcha","验证码") -->
        <param-name>kaptcha.session.key</param-name>
        <param-value>captcha</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>cap</servlet-name>
    <url-pattern>/captcha</url-pattern>
</servlet-mapping>

前端展示与刷新

<%-- 验证码图片 --%>
<img src="/captcha" onclick="reload(this)"><br>

<script>
    function reload(obj){
        obj.src="captcha?date="+new Date();
    }
</script>

七、Rest

概述

是一种开发风格,遵从此风格开发软件,符合REST风格,则RESTFUL。

两个核心要求:

  • 每个资源都有唯一的标识(URL)
  • 不同的行为,使用对应的http-method

注意:Rest风格往往需要使用ajax传数据,返回字符串

handler

@RestController
public class UserController {
    //请求方式为get请求,路径为/users
    //@RequestMapping(value = "/users",method = RequestMethod.GET)
    @GetMapping("/users") //查询  等价于上面的注解
    public List<User> users(){
        List<User> list = new ArrayList<>();
        list.add(new User());
        return  list;
    }
    @PostMapping("/users") //添加操作
    public String addUser(User user){
        System.out.println("user-->"+user);
        return "ok";
    }
    @PutMapping("/users")  //修改操作
    public String updateUser(@RequestBody User user){
        System.out.println("update user-->"+user);
        return "update OK";
    }
    @GetMapping("/user/{id}") //查询单个对象  --路径传参
    public User user(@PathVariable Integer id){
        System.out.println("id-->"+id);
        User user = new User(id,"zs","123",null,null,null);
        return user;
    }
    @DeleteMapping("/delete/{id}")  //路径传参
    public String delete(@PathVariable Integer id){
        System.out.println("删除-->"+id);
        return "delete ok";
    }
}

ajax请求

function updateUser() {  //修改功能  put请求
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("put","/users",true);
    // 设置请求头
    xmlHttp.setRequestHeader("content-type","application/json");
    var user = {id:10,name:"zsf",password:"333"};
    xmlHttp.send(JSON.stringify(user));

    xmlHttp.onreadystatechange=function () {  //接收回调数据
        if(xmlHttp.readyState==4&&xmlHttp.status==200){
            alert(xmlHttp.responseText);
        }
    }
}
$(function(){ /*  删除功能*/
    $("#delete").click(function () {
        $.ajax({
            type:"delete",
            url:"/delete/1",
            success:function(data) {
                alert(date);
            }
        })
    })
})

八、SpringMVC执行流程

浏览器发请求,到达前端控制器–>HandlerMapping映射处理(包含处理器和拦截器)–>HandlerAdapter进行handler适配,并到达目标handler,然后返回ModelAndView对象–>视图解析对象—>重定向或转发跳转–>渲染到JSP文件。

九、总结与作业

总结

1.Jackson解析
概述-按规则显示属性;应用
2.异常解析器
好处-统一handler的异常处理;配置
3.拦截器(重点)
概述-过滤器;应用-权限验证
4.上传(重点)
前端配置-post,二进制编码,file类型;
后端配置-上传解析器,上传功能处理
5.下载
将资源先读后写
6.验证码
导包,映射路径配置,前端展示操作
7.Rest(重点)
概述;handler处理-增删改查编写,ajax请求-put,delete

作业

1.使用Rest风格完成Student的增删改查

晨考

1.异常解析器的作用
2.拦截器的作用
3.上传的客户端需要注意什么?
4.Rest风格是怎样的一种规范?

截屏2023-10-16 09.02.18