侧边栏壁纸
博主头像
coydone博主等级

记录学习,分享生活的个人站点

  • 累计撰写 306 篇文章
  • 累计创建 51 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

SpringMVC注解开发

coydone
2022-03-20 / 0 评论 / 0 点赞 / 329 阅读 / 12,540 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-10,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

解决中文乱码

前端编码:

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>
0

评论区