目录
2.MultipartFile 可以作为请求参数,根据名称会将多媒体组件封装在该类型的参数中
3.1定义拦截器 实现HandlerInterceptor接口
1.1 创建类 实现HandlerExceptionResolver接口
springmvc多媒视图解析器,快速的使用commons-fileupload进行文件上传,并且简化了传统commons-fileupload文件上传的代码编写
首先添加 commons-io.jar commons-fileupload.jar
- //文件上传 手动写
- @ResponseBody
- @PostMapping("/upload")
- public String testLoad(HttpServletRequest request,HttpServletResponse response) throws Exception {
- //多媒体enctype 无法使用 requestParameter("")
- //创建diskfileitemfactory处理文件的上传路径和大小限制;
- DiskFileItemFactory factory =new DiskFileItemFactory();
- // factory可选方法
- // factory.setSizeThreshold(1024*1024);//factory的set不用写有默认值
- // factory.setRepository(tmpFile);//设置临时仓库
- //准备完成后创建文件上载对象
- ServletFileUpload upload =new ServletFileUpload(factory);
- //将发送来的数据表单中的对象通过upload对象解析成FileitemList
- List
items = upload.parseRequest(request); - //遍历每个List中的对象判断需要上载的文件
- User user =new User();
- for (FileItem item : items) {
- //判断对象是否是表单中的普通类还是文件类
- if(item.isFormField()) {
- //普通组件
- // getFieldName是获得表单中输入框的name
- String name=item.getFieldName();
- String value=item.getString("UTF-8");//乱码处理
- if("userName".equals(name)) {
- user.setUserName(value);
- }
- if("userAge".equals(name)) {
- user.setUserAge(Integer.parseInt(value));
- }
- }else {
- //多媒体组件
- //获取客户端的文件名称
- String fileName =item.getName();
- String newFileName =UUID.randomUUID().toString();
- //UUID保证名称不同 + 获取文件后面的.后缀
- newFileName=newFileName+fileName.substring(fileName.lastIndexOf("."),fileName.length());
- //获取到真实路径 d:tomacat/项目名/
- String path=request.getRealPath("/");
- path=path+"upload/";
- File pathFile =new File(path);
- //如果不存在就创建
- if(!pathFile.exists()) {
- pathFile.mkdir();
- }
- //客户端写入文件
- item.write(new File(path+newFileName));
- }
- }
- return "success";
- }
注意:前端的from表单的enctype一定要是 multipart/from-date格式
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- html>
- <html>
- <head>
- <meta charset="UTF-8">
- <script src="js/jquery-3.6.0.js">script>
- <link rel="stylesheet" href="css/css1.css">
- <title>Insert title heretitle>
- head>
- <body>
- <form action="upload" method="POST" enctype="multipart/form-data">
- 用户名称 <input type="test" name="userName" /> <br>
- 年龄用户 <input type="test" name="userAge" /> <br>
- 身份照片<input type="file" name="cord" /> <br>
- <input type="submit" value="保存" />
- form>
- body>
-
- html>
问题
1.需要手动创建工厂并手动解析请求
2.非多媒体类型的请求 参数因为enctype的改变 ,导致传统的获取方式不能使用(即 request.parameter)
3.并且不能进行请求参数的封装
-
- <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
-
- <property name="defaultEncoding" value="UTF-8" >property>
-
- <property name="maxUploadSize" value="-1">property>
-
-
-
- bean>
- @ResponseBody
- @PostMapping("/upload2")
- //MultipartFile 可以作为请求参数 ,根据名称会将多媒体组件封装在该类型的参数中
- //名字与前端的 file的name相同
- public String testLoad2(MultipartFile cord ,User user,HttpServletRequest request,HttpServletResponse response) throws Exception {
- String fileName =cord.getOriginalFilename();
- String newFileName=UUID.randomUUID().toString();
- newFileName=newFileName+fileName.substring(fileName.lastIndexOf("."),fileName.length());
- String path=request.getRealPath("/");
- path=path+"upload/";
- File filePath=new File(path);
- //如果不存在就进行创建
- if(!filePath.exists()) {
- filePath.mkdir();
- }
- //写入
- cord.transferTo(new File(path+newFileName));
- return "success";
- }
多文件上传时,即使组件的名称和形参的名称一致,也需要增加@RequestParame
- @ResponseBody
- @PostMapping("/upload2")
- //MultipartFile 可以作为请求参数 ,根据名称会将多媒体组件封装在该类型的参数中
- //名字与前端的 file的name相同
- public String testLoad2(@RequestBody(name="cords") MultipartFile[] cords ,User user,HttpServletRequest request,HttpServletResponse response) throws Exception {
- for(MultipartFile cord:cords){
- String fileName =cord.getOriginalFilename();
- String newFileName=UUID.randomUUID().toString();
- newFileName=newFileName+fileName.substring(fileName.lastIndexOf("."),fileName.length());
- String path=request.getRealPath("/");
- path=path+"upload/";
- File filePath=new File(path);
- //如果不存在就进行创建
- if(!filePath.exists()) {
- filePath.mkdir();
- }
- //写入
- cord.transferTo(new File(path+newFileName));
- }
- return "success";
- }
可以通过配置的形式手动的修改视图解析器,默认采用jstl的视图解析器,springboot可以通过配置使用thymealf
要求:jsp全部放在web-inf中

-
- <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
-
- <property name="prefix" value="/WEB-INF/">property>
- <property name="suffix" value=".jsp">property>
- bean>
拦截器(Interceptor),主要完成请求参数的解析、将页面表单参数赋值给值栈中响应的属性、执行功能检验、程序异常调试等工作
1.权限设置(filter)
2.性能监控(监控请求的执行时间和响应时间)
- 过滤器是基于函数回调的,而拦截器基于java反射
- 过滤器可以过滤所有,拦截器只能拦截请求
- 过滤器在请求的声明周期中只能执行一次,而拦截器可以多次执行
- 过滤器依赖于servlet容器,而拦截器不依赖于servlet容器
- 过滤器无法获取请求值栈中的信息,拦截器可以获取(ModelAndView)
其实不管是拦截器还是过滤器没什么大的区别,在条件允许的情况下,使用两者那个都可以
但是能使用拦截器的,不一定能使用过滤器(例如没有servlet容器的情况下,或者是计算响应时间等)
- package com.sofwin.interceptor;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- //拦截器
- public class UserInterceptor implements HandlerInterceptor {
-
- /**
- * 请求进入handler以前执行
- * 返回true 放行
- * 返回false 拦截请求 需要手动去处理
- * 参数1 request
- * 参数2 response
- * 参数3 handler 当前handler
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- System.out.println("pre==========="+handler.getClass().getName());
- return true;
- }
-
- /**
- * 即 方法执行完毕后--在执行这个方法
- * @param request
- * @param response
- * @param handler
- * @param modelAndView
- */
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) {
- System.out.println("postHandler。。。。。。。。"+modelAndView.getViewName());
- }
-
- /**
- * 响应完毕后执行这个方法
- */
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
- throws Exception {
- System.out.println("afterComletion======");
- }
-
-
- }
-
- <bean id="userInterceptor" class="com.sofwin.interceptor.UserInterceptor">bean>
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**"/>
-
- <mvc:exclude-mapping path="/a44"/>
- <ref bean="userInterceptor"/>
-
- mvc:interceptor>
- mvc:interceptors>
同一个请求被多个拦截器同时拦截,形参拦截器链。
拦截器链的执行顺序是按照 mvc:interceptors中子标签的声明顺序来确定的
拦截器是拦截不了jsp的页面的
拦截器只拦截@Controller注解的方法和类,对jsp没有拦截,另外需要注意的是,拦截器是会拦截静态资源的 比如html js css image 这类 ,虽然都是页面但是jsp不需要静态资源
1.将所有的jsp文件放入到WEB-INF文件夹下,这样用户就不能字节访问WEB-INF下的jsp文件了。springmvc的理念是通过Controller例的@RequestMapping来请求相关的jsp页面。
也就是说,jsp页面的访问需要通过controller来进行一次请求,因为会拦截对controller的请求,所以相当于拦截了jsp页面。
如果要做登录的验证,只需要将登录的页面和验证码的页面不拦截,其余页面拦截进行是否登录的验证即可。
2.另一种就是直接使用过滤器进行登录的验证 ---这里我们推荐使用过滤器的验证
使用filter会出现一个问题 过滤后也将静态资源也过滤的
我们是这样进行过滤的
- package com.sofwin.filter;
-
- import java.io.IOException;
-
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.annotation.WebFilter;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- /**
- * 用于过滤用户请求,未登录的请求不允许访问除登录外的其他视图
- * @author dell
- *
- */
- @WebFilter(urlPatterns = "/*")
- public class LoginFilter implements Filter{
-
- @Override
- public void destroy() {
-
-
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- //判断是否为静态资源 如果为静态资源,放行
- HttpServletRequest req=(HttpServletRequest)request;
- /* uri和url的区别
- * 输入的url地址为http://localhost:8080/testproject/test?32fr
- * uri为/testproject/test?32fr 是一个String
- * url为http://localhost:8080/testproject/test?32fr 是一个StringBuffer
- * */
- String uri = req.getRequestURI();
- //登录成功 session 放入 currentUser
- HttpSession session = req.getSession();
- Object user = session.getAttribute("currentUser");
- //静态资源的放行处理 indexOf(String str) ---> 返回指定子字符串(str)在此字符串(uri)中第一次出现处的索引。 如果此字符串中没有这样的字符出现,则返回 -1
- // js是先判断是否有.
- if(uri.indexOf("css")>-1||uri.indexOf("images")>-1||(uri.lastIndexOf(".")>-1)&&("js".equals(uri.substring(uri.lastIndexOf("."),uri.length())))) {
- chain.doFilter(request, response);
- }//登录页面 //验证码
- else if(uri.indexOf("login.jsp")>-1) {
- chain.doFilter(request, response);
- }//登录请求
- else if(uri.indexOf("LoginServlet")>-1) {
- chain.doFilter(request, response);
- }else if(user!=null) {
- //登录过 进行放行
- chain.doFilter(request, response);
- }else {
- //过滤请求
- //响应登录页面 让用户进行登录 ---使用重定向 放在一直是别的界一直进行过滤
- HttpServletResponse resp=(HttpServletResponse)response;
- resp.sendRedirect(req.getContextPath()+"/login.jsp");
- }
-
-
-
-
-
- }
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
-
- }
-
- }
如果前端控制器设置了静态资源进入,但是使用拦截器不设置,拦截器依旧会对静态资源进行拦截
因此我们设置如下进行静态资源的放行

servlet 控制层
- //访问 登录界面
- @GetMapping("login")
- public String testlogin() {
- return "login";
- }
- //进行检查
- @GetMapping("checklogin")
- public String testlogin1(String userName,String password,HttpServletRequest request) {
- if("zhangsan".equals(userName)&&"123".equals(password)) {
- request.getSession().setAttribute("user", "user");
- return "user/list";
- }
- return "login";
- }
登录页面
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- html>
- <html>
- <head>
- <link rel="stylesheet" href="css/css1.css">
- <meta charset="UTF-8">
- <title>Insert title heretitle>
- head>
- <body>
- <form action="checklogin" method="get">
- 账号 <input type="text" name="userName" /><br/>
- 密码 <input type="text" name="password" /><br/>
- <input type="submit" value="登录"/>
- form>
-
- body>
- html>
登录成功页面
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- html>
- <html>
-
- <head>
- <meta charset="UTF-8">
- <title>Insert title heretitle>
- head>
- <body>
- 登录成功
- body>
- html>
配置文件
-
- <bean id="userInterceptor" class="com.sofwin.interceptor.UserInterceptor">bean>
- <bean id="minorInterceptor" class="com.sofwin.interceptor.MinorInterceptor">bean>
-
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**"/>
-
- <mvc:exclude-mapping path="/login"/>
- <mvc:exclude-mapping path="/checklogin"/>
- <mvc:exclude-mapping path="/**/*.css"/>
- <mvc:exclude-mapping path="/**/*.js"/>
- <ref bean="userInterceptor"/>
- mvc:interceptor>
- mvc:interceptors>
- package com.sofwin.interceptor;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- //对请求时间和响应时间进行监视的方法
- public class MinorInterceptor implements HandlerInterceptor {
- private Long requestTime=0L; //请求时间
- private Long responseTime=0L; //响应时间
- private Long beginTime=0L; //开始时间
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
- throws Exception {
- responseTime=System.currentTimeMillis()-beginTime;
- System.out.println(request.getRequestURI()+"的响应时间为:"+responseTime);
- HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
- ModelAndView modelAndView) throws Exception {
- requestTime=System.currentTimeMillis()-beginTime;
- System.out.println(request.getRequestURI()+"的请求时间为:"+requestTime);
- beginTime=System.currentTimeMillis();
- }
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- System.out.println("pre -------");
- beginTime =System.currentTimeMillis();
-
- return true;
- }
-
- }
-
- <bean id="userInterceptor" class="com.sofwin.interceptor.UserInterceptor">bean>
- <bean id="minorInterceptor" class="com.sofwin.interceptor.MinorInterceptor">bean>
-
- <mvc:interceptors>
- <mvc:interceptor>
-
- <mvc:mapping path="/**"/>
- <ref bean="minorInterceptor"/>
- mvc:interceptor>
- mvc:interceptors>
用来进行统一的异常处理===jsp中exception对象
当项目在运行过程中发生异常,会自动被定义的全局异常处理器接收,处理并响应对应的异常页面
注意:全局异常处理器只能处理服务器的异常。 客户端的异常处理不了

- package com.sofwin.exception;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.HandlerExceptionResolver;
- import org.springframework.web.servlet.ModelAndView;
- @Component
- //全局异常处理器 ---所有的异常全部抛出 由全局异常处理器来进行处理
- public class ExceptionHandler implements HandlerExceptionResolver{
-
- @Override
- public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
- Exception ex) {
- //因为有视图解析器 所以我们不用加jsp等
- ModelAndView modelAndView =new ModelAndView("exception");
- if(ex instanceof SofwinException) {
- SofwinException sf=(SofwinException)ex;
- modelAndView.addObject("msg",sf.getMsg());
- modelAndView.addObject("cord",sf.getCord());
- }
- else {
- modelAndView.addObject("msg","对不起,网络问题,请稍后访问");
- modelAndView.addObject("cord","2222");
- }
- return modelAndView;
- }
-
- }

- package com.sofwin.exception;
-
- public class SofwinException extends Exception {
- private String msg;
- private String cord;
- public String getMsg() {
- return msg;
- }
- public void setMsg(String msg) {
- this.msg = msg;
- }
- public String getCord() {
- return cord;
- }
- public void setCord(String cord) {
- this.cord = cord;
- }
- public SofwinException(String msg, String cord) {
- this.msg = msg;
- this.cord = cord;
- }
- public SofwinException() {
- super();
- }
-
- }
- @ResponseBody
- @GetMapping("ttt")
- public String test66(Integer a, Integer b ) throws SofwinException {
-
- if(b==0) {
- throw new SofwinException("空指针", "111");
- }
-
- float res=a/b;
- System.out.println("视图解析器");
- return "www";
- }
在可以预知的地方主动抛出异常
在不可预知的地方设置通用的提示
