今日内容
零、 复习昨日
零、 复习昨日
1 maven项目编译后代码在target
2 发现代码都没有错,该写的都有,但是已启动服务器404,查看target,如果编译会后资源不全面,那就删除重新编译
3 重新看一下,如何使用mavne创建javaweb项目
一、参数绑定 【重点】
所谓参数绑定,就是前端发请求中的数据,可以直接在Controller的方法参数中接收.
即前端请求数据和后端方法参数绑定.
1.1 基本类型参数绑定[重点]
基本类型指,常用的几种类型: 基本类型+String+Date
前端页面
<h2>基本类型数据绑定</h2>
<a href="/base.do?id=1&username=张三&score=10.0">请求携带数据-基本类型</a>
<hr>
<form action="/base.do" method="get">id<input type="text" name="id"><br>username<input type="text" name="username"><br>score<input type="text" name="score"><br>birthday<input type="text" name="birthday"><br><input type="submit" value="基本类型">
</form>
后端接收
@Controller
public class DataController {/*** 基本类型自动封装* 要求是: 前端请求的参数名,后端方法的参数名要一致* 【特殊的】 日期,前端发送的日期格式如果是yyyy-MM-dd,springmvc无法默认绑定参数,* springmvc默认支持yyyy/MM/dd* 两种方案解决:* 1. 前端改,发出的日期格式就是yyyy/MM/dd即可* 2. 后端改,给日期参数加@DateTimeFormat(pattern = "yyyy-MM-dd")*/@RequestMapping("/base")public String base(int id, String username, double score, @DateTimeFormat(pattern = "yyyy-MM-dd") Date birthday){System.out.println("id = " + id);System.out.println("username = " + username);System.out.println("score = " + score);System.out.println("birthday = " + birthday);return "ok";}}
1.2 对象[重点]
场景: 注册/添加/更新
实体类
public class User {private int id;private String username;private String password;private double score;@DateTimeFormat(pattern = "yyyy-MM-dd")private Date birthday;// setget
}
前端
<h2>对象数据绑定</h2>
<form action="/obj.do" method="get">id<input type="text" name="id"><br>username<input type="text" name="username"><br>score<input type="text" name="score"><br>birthday<input type="date" name="birthday"><br><input type="submit" value="对象类型">
</form>
后端
/*** 自动绑定: 要求前端的请求中的参数要和对象的属性名一致*/@RequestMapping("/obj")public String obj(User user){System.out.println("user = " + user);return "ok";}
1.3 数组
场景: 批量删除需要同时接收多个id, (前端是复选框的)
前端
<h2>数组绑定</h2>
<form action="/array.do" method="get"><input type="checkbox" name="ids" value="1">1<input type="checkbox" name="ids" value="2">2<input type="checkbox" name="ids" value="3">3<input type="checkbox" name="ids" value="4">4<input type="submit" value="数组类型">
</form>
后端
/*** 自动绑定: 要求前端的请求中的参数要和方法参数名(数组名)一致*/@RequestMapping("/array")public String array(int[] ids){System.out.println("ids = " + Arrays.toString(ids));return "ok";}
1.4 List集合
List集合使用场景与数组是一样的
前端
<h2>List绑定</h2>
<form action="/list.do" method="get"><input type="checkbox" name="skill" value="Java">Java<input type="checkbox" name="skill" value="HTML">HTML<input type="checkbox" name="skill" value="Linux">Linux<input type="submit" value="List类型">
</form>
SpringMVC默认是不支持直接封装List的,解决方案
- 加注解@RequestParam,就可以【推荐】
- 间接的封装List — 创建一个实体类,定义List属性
方案一
@RequestMapping("/list")
public String list(@RequestParam List<String> skill){System.out.println("skill = " + skill);return "ok";
}
方案二
public class User {private int id;private String username;private double score;@DateTimeFormat(pattern = "yyyy-MM-dd")private Date birthday;private List<String> skill; // 定义集合属性// setget
}
@RequestMapping("/list")
// 在封装对象数据时,封装listpublic String list(User user){System.out.println("user-skill = " + user.getSkill());return "ok";}
1.5 Map集合
Map是键值对,键和值一一映射.
跟Java对象很类似,属性和属性值一一对应.
所以什么时候需要/可以使用Map来接收参数?
- 凡是可以用对象接收的都可以使用Map
- 需要接收两个参数时,可以map
SpringMVC默认不支持直接将参数封装进Map,需要使用@RequestParam
前端
<h2>Map绑定</h2>
<form action="/map.do" method="get">id<input type="text" name="id"><br>username<input type="text" name="username"><br>score<input type="text" name="score"><br>birthday<input type="date" name="birthday"><br><input type="submit" value="Map类型">
</form>
<h2>模糊查询-Map绑定</h2>
<form action="/map.do" method="get">address<input type="text" name="address"><br>floor<input type="text" name="floor"><br>deco<input type="text" name="deco"><br><input type="submit" value="模糊-Map类型">
</form>
name就是map的key
输入框的值就是map的value
后台
@RequestMapping("/map")public String map(@RequestParam Map<String,Object> map){System.out.println("map = " + map);return "ok";}
1.6 @RequestParam
当封装数据失败时使用该注解,该注解放在参数上
场景一:
前端参数和后端方法参数要一致才能封装数据,当不一致时可以使用@RequestParam来手动指定前端数据封装给参数
场景二:
默认情况下,后端方法的参数列表一旦设置了该参数,就必须传值,不传值就会报错
但是设置@RequestParam(required = false)时就可以不用传值也不报错
场景三:
当后端参数没有传值时,赋值默认值@RequestParam(defaultValue = “666666”)
二、数据乱码
之前自己写过全局编码格式拦截器
现在springmvc提供了编码格式拦截器,直接用即可
<!-- 编码格式拦截器 --><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
三、页面跳转
之前学过的servlet中跳转页面的功能
- 请求转发:
- forward
- req.getDispatcherServlet().forward(req,resp)
- 请求路径不变
- 是服务器内部请求
- 一次请求
- 请求域的数据可以共享
- 重定向
- redirect
- resp.sendRedirect();
- 请求路径改变
- 是浏览器行为
- 两次请求
- 请求域的不能共享
请求转发
注意: 默认在使用就是请求转发
在Controller的方法的返回值中写forward:路径即可完成跳转
例如: forward:/view/ok.html forward:/test.do
注意: 跳转后的路径要写完整
/*** 演示请求转发至其他页面* @return*/@RequestMapping("/forward")public String forward(){System.out.println("执行请求转发" );return "forward:/view/ok.html";}/*** 演示请求转发至其他请求* @return*/@RequestMapping("/forward2")public String forward2(){System.out.println("执行请求转发" );return "forward:/test.do";}
重定向
在Controller的方法的返回值中写redirect:路径即可完成跳转
例如: redirect:/view/ok.html redirect:/test.do
注意: 跳转后的路径要写完整
/*** 演示重定向至其他页面* @return*/@RequestMapping("/redirect")public String redirect(){System.out.println("执行重定向" );return "redirect:/view/ok.html";}/*** 演示重定向至其他请求* @return*/@RequestMapping("/redirect2")public String redirect2(){System.out.println("执行重定向" );return "redirect:/test.do";}
其他的请求转发和重定向的特点和之前学习的servlet是一样的,复习.
四、数据共享
数据共享是指: 数据域,即
- request域
- 只有在一次请求中有效,即请求转发后能取出
- session域
- 一次会话有效,只要会话不结束,无论请求转发还是重定向都能取出
package com.qf.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;/*** --- 天道酬勤 ---** @author QiuShiju* @desc 演示域对象(Request,Session)*/
@Controller
public class ScopeController {@RequestMapping("/req")public String requestAndSession(HttpServletRequest request, HttpSession session) {// 存入request.setAttribute("req","req-Value");session.setAttribute("se","se-Value");return "forward:/req2.do";}@RequestMapping("/req2")public String requestAndSession2(HttpServletRequest request, HttpSession session) {// 取出String v1 = (String) request.getAttribute("req");System.out.println("v1 = " + v1);String v2 = (String) session.getAttribute("se");System.out.println("v2 = " + v2);return "ok";}
}
五、静态资源处理
目前,前端控制器(DispatcherServlet)类映射的是==*.do==,前端的静态资源例如:html,js,css,图片 等都是不影响加载的
但是,如果前端控制器(DispatcherServlet)类映射的是==/==,那就是所有请求都要经过前端控制器,静态资源也不例外. 那么此时静态资源是无法完成映射.
此时就需要静态资源处理!!!
web.xml文件
<!-- 前端控制器 --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><!-- 此处要改成 / ,这样才能映射匹配到所有请求 --><url-pattern>/</url-pattern></servlet-mapping>
项目中定义一个css文件夹,定义一个css文件,在index.jsp页面中引入静态资源css,查看效果即可
springmvc.xml文件
<!-- 静态资源映射mapping="访问路径"location="本地资源位置""/**" 前端的任何请求去匹配后台处于"/"下的静态资源--><mvc:resources mapping="/**" location="/"/>
ps:
<mvc:default-servlet-handler/> 也行
六、拦截器 【重点】
6.1 作用
- 之前用来做编码格式过滤
- 登录认证
- 等等
6.2 定义拦截器
- 自定义类
- 实现接口
- 重写方法
- springmvc.xml配置
package com.qf.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** --- 天道酬勤 ---** @author QiuShiju* @desc 拦截器类*/
public class MyInterceptor implements HandlerInterceptor {/*** 目前Controller,执行前,执行拦截* 一般用于: 校验* @return 返回true,即认为放行,返回false不放行*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("前 pre" );// 写项目时,这里通过数据判断,来决定是返回true放行,还是返回false不放行return true;}/*** 在目标Controller方法执行完,但是afterCompletion方法前执行* 对目标方法的返回再处理,可以对响应再定制.*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("post" );}/*** 目标Controller的方法全部执行完执行* 一般: 资源回收*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("after" );}
}
以上方法是按需重写,一般来说用的是前置方法preHandle()
<!-- 配置拦截器 --><mvc:interceptors><mvc:interceptor><!-- mapping path: 要拦截的路径 --><!-- <mvc:mapping path="/user/**"/>--><mvc:mapping path="/**"/><!-- exclude-mapping 排除拦截的 --><mvc:exclude-mapping path="/login"/><mvc:exclude-mapping path="/test.do"/><!-- 指定拦截器类 --><bean class="com.qf.interceptor.MyInterceptor"/></mvc:interceptor></mvc:interceptors>
七、异常处理
以前处理异常
- 抛出
- 视图捕获
全靠自己在每个方法中处理异常
springmvc框架提供了一个全局的异常处理机制,可以处理Controller的所有异常
这种方法,集中管理异常
- 建类
- 实现接口
- 重写方法
- 配置
@Component // 配置到spring容器
public class MyExceptionHandler implements HandlerExceptionResolver {@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {ModelAndView mv = new ModelAndView( );if (ex instanceof ArithmeticException) {mv.setViewName("redirect:/view/500.html");} else if (ex instanceof AuthException) {mv.setViewName("redirect:/view/auth.html");}return mv;}
}
测试
后台Controller抛出异常,测试!
任务
重点: 参数绑定- 重复
删除数据发请求-接收
添加/注册/更新 -> 接收
批量删除 --> 接收其中使用的注解要会
------------------------
重新整合spring和mybatis--------------------------------------
思考:
写项目后端数据如何在页面展现?
方案1: 存储域,在jsp页面取值
方案2: 不用jsp,用html开发,后端数据如何给前端展现?