解决中文乱码
前端编码:
JSP页面:
<% page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
HTML页面:
<meta charset="UTF-8">
服务器编码:
Tomcat的conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443” URIEncoding="UTF-8"/>
SpringMVC中在web.xml中配置过滤乱码的过滤器。
<!--配置解决乱的过滤器-->
<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>
使用注解配置控制器
1、在SpringMVC配置文件中导入context标签
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=”http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd”
2、在SpringMVC配置文件中,使用component-scan标签扫描SpringMVC注解配置:
<!--扫描包,被扫描的包被SpringMVC注解识别-->
<context:component-scan base-package="com.coydone.controller"></context:component-scan>
3、使用@Controller注解定义控制器
@Controller //指定当前类为控制器,此时无需实现Controller方法
public class LoginController {
//定义一系列处理请求的方法: 一个请求一个方法
}
4、使用@RequestMapping注解定义处理请求的方法
方式一:定义控制器方法返回ModelAndView
//@RequestMapping(value = "/请求路径") //配置请求路径
@RequestMapping(value = "/login2")
public ModelAndView handlerLogin(){
System.out.println("我可以处理请求啦...");
return null;
}
方法二(推荐):返回String表示视图页面
@RequestMapping("/login3")
public String login3(HttpSession session, String username, String password, Model model){
//处理请求代码…
return "index.jsp";//返回网页 默认就是请求转发跳转
}
在控制器方法中可以使用原生的Servlet API,只需要在参数列表中定义即可直接使用。参数列表中可以定义页面的请求参数,SpringMVC会自动帮我们获取。Model是我们要返回给页面的数据模型,通过它封装。如果页面传输的数据过多时,我们可以使用一个实体对象进行接收,SpringMVC会自动帮我们将参数封装到实体中,除了如时间日期类型的复杂参数需要我们手动封装,其它简单类型,SpringMVC会自动帮我们封装。
SpringMVC的参数绑定
1、利用Servlet API获取请求中的数据
@RequestMapping("/login4")
public ModelAndView login4(HttpServletRequest request, HttpSession session){
//1.利用servletapi获取请求参数
String uname=request.getParameter("uname");
String password=request.getParameter("password");
ModelAndView mav=null;
if(uname.equals("admin")&&password.equals("123")){
//使用session保存登入的人
session.setAttribute("loginname",uname);
//登入成功
mav=new ModelAndView("success.jsp");
}else {
//登入失败
mav=new ModelAndView("index.jsp");
}
return mav;
}
2、利用参数绑定获取请求中的数据:一个表单对象(请求中的参数)对应一个方法的参数,要求表单对象名称与参数名称相同。
@RequestMapping("/login5")
public ModelAndView login5(@RequestParam(value = "username",required = false) String username, String password,HttpSession session){
//利用@RequestParam注解指定请求参数与方法参数对应
//value指定请求参数名称 required表示参数 false可有可无,true一定传
//@RequestParam(value = "请求参数名称",required = false)
ModelAndView mav=null;
if(username.equals("admin")&password.equals("123")){
mav=new ModelAndView("success.jsp");
//使用session对象保存登入的人
session.setAttribute("loginname",username);
} else{
mav=new ModelAndView("index.jsp");
}
return mav; //跳转
}
3、将多个表单对象(请求中的参数)对应到实体参数中,要求表单对象名称与实体类的属性名称名称相同。
//实体
package com.coydone.entity;
import java.io.Serializable;
public class User implements Serializable {
private String username;
private String password;
//省略构造方法、getter()方法、setter()方法
}
@RequestMapping(value = "/login6")
public ModelAndView login6(HttpSession session,User user){}
如果当表单传入后台的数据比如有多选框,那么实体类型就需要使用数组。
视图解析器
配置SpringMVC的视图解析器
1、修改SpringMVC配置文件定义视图解析器
<!--配置SpringMVC视图解析器 prefix前缀 suffix后缀-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
2、在控制器方法中返回视图名称即可(针对请求转发跳转)
//结果:return "success.jsp"
return "success"; //返回视图名称(文件名)
3、以重定向的方式返回页面(控制器就不能使用model给页面返回数据、视图解析也不起作用了)。
// return "redirect:返回视图页面的路径";
//重定向跳转,不支持视图解析,所有要补全后缀名
return "redirect:index.jsp";
页面数据处理
1、页面无法加载静态资源,如JS文件。
<!--对静态资源放行-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--方式二-->
<!-- 设置静态资源不过滤
mvc:resources标签配置不过滤
location元素表示webapp目录下的包下的所有文件
mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
-->
<mvc:resources location="/css/" mapping="/css/**"/><!-- 样式 -->
<mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
<mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
2、SpringMVC进行参数绑定时,不支持日期(java.util.Date)转换。需做如下处理:
- 第一步:在实体属性上使用DateTimeFormat解决日期转换的支持。
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
- 第二步:在SpringMVC配置文件中添加注解驱动配置 。
<!--注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
3、页面时间格式的显示
Java中Date类型的时间格式可以通过jsp的jstl标签库中的fmt进行格式转换。
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<td>
<fmt:formatDate value="${student.birthday}" type="date" pattern="yyyy-MM-dd"/></td>
使用前端的时间控件时,需要传输到前端的数据是yyyy-MM-dd
格式,在时间控件中才会自动显示。
<tr>
<td>生日:</td>
<td>
<input type="date" name="birthday" value="<fmt:formatDate value="${student.birthday}" pattern="yyyy-MM-dd"></fmt:formatDate>">
</td>
</tr>
4、页面单选框显示,默认项为checked。
<tr>
<td>性别:</td>
<td>
<input type="radio" name="sex" value="男" <c:if test="${student.sex eq '男'}">checked</c:if>>男
<input type="radio" name="sex" value="女"<c:if test="${student.sex eq '女'}">checked</c:if>>女
</td>
</tr>
5、页面下拉框默认显示,默认项为selected。
<tr>
<td>年级:</td>
<td>
<select name="gid">
<c:forEach items="${grades}" var="grade">
<option value="${grade.gid}" <c:if test="${grade.gid==student.gid}"> selected </c:if>>${grade.gname}</option>
</c:forEach>
</select>
</td>
</tr>
6、前端参数传递
- 表单提交:表单使用name属性进行参数传递,前端传递的数据均为字符串String类型,SpringMVC控制器是通过name属性取值的。在表单中传递参数为post形式,id需要隐藏域。
<form action="/updateStudent" method="post">
<input type="hidden" name="id" value="101">
</form>
- URL提交:在超链接a标签中传递参数为get形式。
<a href="/deleteStudent?xh=${student.xh}">删除</a>
- Ajax提交:请求行、请求头、请求体都可以用来传值。
控制器接收数据
1、请求行传值(表单提交、URL提交、$.ajax()请求的URL传值
、$.post()/$.get()中的{}传值
)
@RequestParam 注解用于接收请求行传递的数据。
//接收请求行数据,前端name属性值与方法的接收参数不一致时使用 @RequestParam
RequestMapping("/add")
public void addBook (@RequestParam("name") String a,
@RequestParam( " author") String b,
@RequestParam("price" ) double c) {
}
//接收请求行数据,前端name属性值与方法的接收参数一致时@RequestParam可省略
RequestMapping("/add")
public void addBook (String name,
String author,double price) {
}
2、请求头传值(@RequestHeader注解用于接收请求行头传递的数据)
//ajax封装请求头数据
$.ajax({
...,
heads:{
token:"1222222"
},
...
})
RequestMapping("/list")
public void listBooks (@RequestHeader("token") String token) {
}
3、请求体传值(@RequestBody 注解用于接收请求行头传递的数据)
@RquestBody 将前端请求体提交的JSON格式数据转换成Java对象,依赖jackson包。
//ajax封装请求体数据
$.ajax({
contentType : "application/json" ,
data:JSON.stringify(obj)
})
RequestMapping( "/update" )
public void update(@RequestBody Book book){}
控制器响应前端请求
同步请求
处理同步请求的方法的返回类型定义为String或者ModelAndView,以实现页面的跳转。
//返回类型为String
RequestMapping("/add")
public String addBook(String name,String author,double price){
return "/tips.jsp"; //转发
//return "redirect:/tips.jsp" ; //重定向
}
//返回类型为ModelAndView
@RequestMapping("/add")
public ModelAndview addBook(String name,String author,double price){
ModelAndView modelAndView = new ModelAndView( "/tips.jsp" );//转发
ModelAndView modelAndView = new ModelAndView( "redirect:/tips.jsp" );//重定向
return modelAndView;
)
异步请求
利用out对象输出返回的JSON数据
//在ajax()中设置 dataType: "json", 设置预期服务器返回的数据类型为json
//或者在Controller中声明 response.setcontentType("application/json");
@RequestMapping("/getData")
public void getData(HttpServletResponse response) throws IOException {
//设置响应的编码
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
//1.返回字符串
//out.print("hello");
//2.返回json
out.print("[\"张三\",\"李四\",\"麻子\"]");
}
利用@ResponseBody注解返回异步数据
@ResponseBody作用:
用于获取请求体内容。直接使用得到是 key=value&key=value… 结构的数据。get 请求方式不适用。
@ResponseBody属性:
required:是否必须有请求体。默认值为true。当取值为 true 时,get 请求方式会报错。如果取值为false,get 请求得到是 null。
如果一个控制器类中的所有方法都是响应ajax请求,则可以直接在控制器类前添加@ResponseBody注解。
1、在pom.xml文件中添加json自动转换的依赖jackson。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.4</version>
</dependency>
2、修改SpringMVC配置文件添加mvc注解驱动
<!--注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
3、在控制器方法中添加@ResponseBody
注解表示返回的不在是页面,而是数据。
4、此时返回什么类型的数据,返回值就是什么。如返回多个学生,则使用List<Student>
。
//异步
@RequestMapping("/ajax")
@ResponseBody
public List<Student> ajax(){
//调用业务层方法,返回student集合
List<Student> students = studentService.getAllStudentAndGrade();
return students;
}
5、如果要格式化JSON中的Date类型数据,则在实体类中添加@JsonFormat
注解。
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;
其它注解
@RequestHeader:用于获取请求消息头。
- 属性:value:提供消息头名称;required:是否必须有此消息头。
@RequestMapping("/test")
public String test(@RequestHeader(value="Accept-Language",
required=false) String requestHeader){
System.out.println(requestHeader);
return "success";
}
@CookieValue:用于把指定 cookie 名称的值传入控制器方法参数。
- 属性:value:指定 cookie 的名称。required:是否必须有此 cooki
@RequestMapping("/test2")
public String test2(@CookieValue(value="JSESSIONID",required=false)
String cookieValue){
System.out.println(cookieValue);
return "success";
}
@ModelAttribute:该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。出现在参数上,获取指定的数据给参数赋值。
-
属性:value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 Map 结构的 key。
-
应用场景:当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。例如:我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。
@SessionAttribute:用于多次执行控制器方法间的参数共享。
- 属性:value:用于指定存入的属性名称;type:用于指定存入的数据类型。
//jsp页面
${username}
${sessionScope}
@SessionAttributes(value = {"username"})//把username存入到session域中
@Controller
public class TestSessionController {
@RequestMapping("/test01")
public String test01(Model model){
//把username存入request域中
model.addAttribute("username","admin");
return "testSession";
}
@RequestMapping("/test02")
//获取session域中的值
public String test02(ModelMap modelMap){
String username = (String) modelMap.get("username");
System.out.println(username);
return "testSession";
}
@RequestMapping("/test03")
//清除session
public String test03(SessionStatus status){
status.setComplete();
return "testSession";
}
}
日期格式处理
如果前端需要输入日期数据,在控制器中转换成Date对象,SpringMVC要求前端输入的日期格式必须为yyyy/MM/dd。
如果要求日期格式必须为指定的格式,而这个指定格式SpringMVC不接受,该如何处理呢?
自定义日期转换器
package com.coydone.utils;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
1.创建一个类实现Converter接口,泛型指定从什么类型转换为什么类型
2.实现convert转换方法
*/
public class MyDateConverter implements Converter<String, Date> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
public Date convert(String s) {
Date date = null;
try {
date = sdf.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
在SpringMVC配置文件中配置:
<!--声明MVC使用注解驱动-->
<mvc:annotation-driven conversion-service="converterFactory"/>
<bean id="converterFactory"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.coydone.utils.MyDateConverter"/>
</set>
</property>
</bean>
评论区