SpringMVC速通

SpringMVC速通,第1张

文章目录
    • 1 SpringMVC
      • 1.1 引言
      • 1.2 MVC架构
    • 2 开发流程
      • 2.1 步骤
      • 2.3 中文乱码问题
    • 3.请求参数接收
      • 3.1 基本类型参数
      • 3.2 实体类接收(推荐)
      • 3.3 数组接收
      • 3.4 集合接收
      • 3.5 路径接收
    • 4 跳转
      • 4.1 转发
      • 4.2 重定向
      • 4.3 细节
    • 5 传值
      • 5.1 request和session
      • 5.2 model
      • 5.3 @SessionAttributes
      • 5.4 ModelAndView
    • 6 静态资源
      • 6.1 解决方法1
      • 6.2 解决方法2
      • 6.3 解决方法3
    • 7 JSON处理
      • 7.1 导入依赖
      • 7.2 @ResponseBody
      • 7.3 @RestController
      • 7.4 @RequestBody
      • 7.5 Jackson常用注解
      • 7.6 FastJson
    • 8 异常解析器
    • 9 拦截器
      • 9.1 定义拦截器
      • 9.2 配置拦截器
    • 10 上传
      • 10.1 导入依赖
      • 10.2 表单
    • 11.下载
    • 12.验证码
    • 13.REST
      • 13.1 概念
      • 13.2 用法
    • 14 跨域问题
      • 14.1 域
      • 14.2 Ajax跨域问题
      • 14.3 解决方法
    • 15 SpringMVC执行流程
    • 实例、SSM实现登录
      • 一、准备数据库
      • 二、创建Maven项目并在pom中添加依赖
      • 三、在Resources目录下创建日志文件log4j.properties,以及数据库配置文件jdbc.properties
      • 四、给项目添加Web功能和配置Tomcat
      • 五、创建Bean包和User实体类
      • 六、创建Mapper包和用户映射器接口UserMapper
      • 七、创建service包和用户服务类 -UserService
      • 八、创建controller包和用户控制器 -UserController
      • 九、在Resources目录下创建mapper文件夹和用户映射器配置文件 UserMapper.xml
      • 十、在Resources目录下创建config文件夹以及Spring配置文件spring-config.xml、SpringMVC配置文件spring-mvc-config.xml
      • 十一、编辑Web部署描述文件 web.xml
      • 十二、创建前端页面
        • 1、login.css
        • 2、check.js
        • 3、login.jsp
        • 4.index.jsp
        • 5.management.jsp
        • 4.index.jsp
        • 5.management.jsp

1 SpringMVC 1.1 引言
  • java开源框架,Spring Framework的一个独立模块。
  • MVC框架,在项目中开辟MVc层次架构
  • 对控制器中的功能包装简化扩展践行工厂模式,功能架构在工厂之上
1.2 MVC架构

MVC : Model View Controller
模型 视图 控制器
模型:即业务模型,负责完成业务中的数据通信处理,对应项目中的service和dao
视图:渲染数据,生成页面。对应项目中的jsp
控制器:直接对接请求,控制MVC流程,调度模型,选择视图。对应项目中的Servlet


  • MVC是现下软件开发中的最流行的代码结构形态;
  • 人们根据负责的不同逻辑,将项目中的代码分成MVC 3个层次;层次内部职责单一,层次之间耦合度低;
  • 符合低耦合高内聚的设计理念。也实际有利于项目的长期维护。
2 开发流程 2.1 步骤

导入依赖


<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-webmvcartifactId>
    <version>5.3.14version>
dependency>

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <version>1.18.22version>
dependency>

配置前端控制器web.xml

右键项目名–>添加框架支持–>web

  • 作为一个MVC框架,首先要解决的是:如何能够收到请求!
  • 所以MVC框架大都会设计一款前端控制器,选型在Servlet或 Filter两者之一,在框架最前沿率先工作,接收所有请求。
  • 此控制器在接收到请求后,还会负责springMVc的核心的调度管理,所以既是前端又是核心。

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    
    <servlet>
        <servlet-name>mvcservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>

        
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:mvc.xmlparam-value>
        init-param>

        
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>mvcservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>
web-app>

配置后端控制器

@Controller //声明这是一个控制器
@RequestMapping("/hello")//访问路径,等价于url-pattern
public class HelloController {

    @RequestMapping( "/test1")//访问路径
    public String hello1(){
            System.out.println( "hello world" );
            return "hello"; //跳转:/index.jsp
    }

}

配置文件

在resource目录下创建mvc.xml

默认名称:核心控制器名-servet.xml默认位置:WEB-INF随意名称: mvc.xml

随意位置:resources但需要配置在核心控制器中


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    <context:component-scan base-package="net.lj"/>

    
    <mvc:annotation-driven>mvc:annotation-driven>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
        <property name="prefix" value="/">property>
        
        <property name="suffix" value=".jsp">property>
    bean>
beans>

运行Tomcat测试

http://localhost:8080/

http://localhost:8080/hello/test1

2.3 中文乱码问题

页面字符集统一

JSP   <%@ page contentType="text/html;charset=UTF-8" language="java" %>
HTML  

tomcat中字符集设置,对get请求中,中文参数乱码有效

Tomcat配置:URIEncoding=utf-8

设置此filter,对post请求中,中文参数乱码有效


<filter>
    <filter-name>Character Encodingfilter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    <init-param>
        <param-name>encodingparam-name>
        <param-value>utf-8param-value>
    init-param>
filter>
<filter-mapping>
    <filter-name>Character Encodingfilter-name>
    <url-pattern>/*url-pattern>
filter-mapping>
3.请求参数接收 3.1 基本类型参数

请求参数与方法形参同名

  • springMVC默认可以识别的日期字符串格式为: YYYY/MM/dd HH:mm:ss
  • 通过@DateTimeFormat可以修改默认日志格式
// http://xxxx/test1?id=1&name=shine&gender=true&birth=2020/12/12 12:13:20
@RequestMapping("test1")
public String test1(Integer id, String name, Boolean gender, Date birth) {
    System.out.println("test1");
    System.out.println(id+","+name+","+gender+","+birth);
    return "hello";
}
3.2 实体类接收(推荐)

传入值与类属性同名

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Boolean gender;
    private Date birth;
}
// http://xxxx/test1?id=1&name=shine&gender=true&birth=2020/12/12 12:13:20
@RequestMapping("test2")
public String test2(User user) {
    System.out.println("test2");
    System.out.println(user);
    return "hello";
}
3.3 数组接收
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

    
        Title
    
    
        
足球 篮球 排球
// http://xxxx/param/test3?hobby=football&hobby=basketball&hobby=volleyball
@RequestMapping("test3")
public String test3(String[] hobby) {
    System.out.println("test3");
    for (String s : hobby) {
        System.out.println(s);
    }
    return "hello";
}
3.4 集合接收
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

    
        Title
    
    
        
id:
name:
gender:

id:
name:
gender:
//http://x/test4?users[0].id=1&users[0].name=shine&users[0].gender=true&users[1].id=2.users[1].name=zhangsan
@RequestMapping("test4")
public String test4(UserList userList) {
    for (User user : userList.getUsers()) {
        System.out.println(user);
    }
    return "hello";
}
3.5 路径接收
// {id}等价于*  test5/1  test5/2  test5/XXXX
@RequestMapping("test5/{id}")
public String test5(@PathVariable("id") Integer id) {
    System.out.println(id);
    return "hello";
}

//  test5/1/2  test5/2/3  test5/XXXX/xxx
@RequestMapping("test6/{id}/{name}")
public String test6(@PathVariable("id") Integer id,@PathVariable("name") String name2) {
    System.out.println(id);
    System.out.println(name2);
    return "hello";
}
4 跳转 4.1 转发
@RequestMapping("test1")
public String test1(){
    System.out.println("test1");
    //return "hello"; //转发
    return "forward:/hello"; //转发
}

@RequestMapping("test2")
public String test2(){
    System.out.println("test2");
    //return "forward:/test1"; //转发到test1
    return "forward:test1"; //相对路径
}
4.2 重定向
@RequestMapping("test3")
public String test3(){
    System.out.println("test3");
    return "redirect:/hello";
}

@RequestMapping("test4")
public String test4(){
    System.out.println("test4");
    //return "redirect:test3";//相对路径
    return "redirect:/test3";//绝对路径
}
4.3 细节
  • 在增删改之后,为了防止请求重复提交,重定向跳转
  • 在查询之后,可以做转发跳转
5 传值

C得到数据后,跳转到v,并向传递数据。进而V中可以渲染数据,让用户看到含有数据的页面

  • 转发跳转:Request作用域
  • 重定向跳转:Session作用域

导入依赖


<dependency>
    <groupId>javax.servletgroupId>
    <artifactId>javax.servlet-apiartifactId>
    <version>3.1.0version>
    <scope>providedscope>
dependency>

<dependency>
    <groupId>javax.servletgroupId>
    <artifactId>jstlartifactId>
    <version>1.2version>
dependency>

<dependency>
    <groupId>javax.servletgroupId>
    <artifactId>jsp-apiartifactId>
    <version>2.0version>
    <scope>providedscope>
dependency>
5.1 request和session
@RequestMapping("test1")
public String test1(HttpServletRequest request, HttpSession session) {
    System.out.println("test1");
    request.setAttribute("name", "张三");
    session.setAttribute("age", "18");
    return "data";
}
name:${requestScope.name}
age:${sessionScope.age}
5.2 model
@RequestMapping("test2")
public String test2(Model model) {
    System.out.println("test2");
    model.addAttribute("gender", true);
    return "data2";
}
gender:${requestScope.gender}
5.3 @SessionAttributes
@Controller
@SessionAttributes(names = {"city","street"})
public class DataController {

    @RequestMapping("test2")
    public String test2(Model model) {
        System.out.println("test2");
        model.addAttribute("city", "北京");
        model.addAttribute("street", "长安街");
        return "data2";
    }
    
    @RequestMapping("test3")
    public String test3(SessionStatus status) {
        //清空所有通过model存入的session
        status.setComplete();
        return "data2";
    }
}
city:${sessionScope.city}
street:${sessionScope.street}
5.4 ModelAndView
//ModelAndView跳转并传递数据
@RequestMapping("test4")
public ModelAndView test4() {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("forward:/hello.jsp");
    modelAndView.addObject("clz", "001");
    return modelAndView;
}
clz:${requestScope.clz}
6 静态资源

静态资源: html,js文件,css文件,图片文件

静态文件没有url-pattern,所以默认是访问不到的,之所以可以访问,是因为,tomcat中有一个全局的servlet:org.apache.catalina.servlets.DefaultServlet,它的url-pattern是"/",是全局默认的Servlet.
所以每个项目中不能匹配的静态资源的请求,有这个Servlet来处理即可。

但,在SpringMVC中DispatcherServlet也采用了“P”作为url-pattern,则项目中不会再使用全局的Serlvet,则静态资源不能完成访问。

6.1 解决方法1

DispathcerServlet采用其他的url-pattern

此时,所有访问handler的路径都要以.action结尾!!

<servlet>
    <servlet-name>mvcservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
servlet>
<servlet-mapping>
    <servlet-name>mvcservlet-name>
    <url-pattern>*.actionurl-pattern>
servlet-mapping>
6.2 解决方法2

DispathcerServlet的url-pattern依然采用"/",但追加配置



<mvc:default-servlet-handler/>
6.3 解决方法3


<mvc:resources mapping="/html/**" location="/HTML/"/>
7 JSON处理

springMVC默认的Json解决方案选择是Jackson,所以只需要导入jackson的jar,即可使用。

7.1 导入依赖
<dependency>
    <groupId>com.fasterxml.jackson.coregroupId>
    <artifactId>jackson-databindartifactId>
    <version>2.13.1version>
dependency>
7.2 @ResponseBody

将handler的返回值转换成JSON,并将JSON响应给客户端

当返回值本身不是字符串时,将返回值转换为JSON

@RequestMapping("test1")
@ResponseBody
public User test1(){
    System.out.println("test1");
    User user = new User(1, "张三");
    return user;
}

@RequestMapping("test2")
@ResponseBody
public List<User> test2(){
    System.out.println("test1");
    User user = new User(1, "张三");
    User user2 = new User(2, "李四");
    List<User> users = Arrays.asList(user, user2);
    return users;
}
7.3 @RestController

当类中方法都需要加上@ResponseBody时,可以用@RestController替代Controller

7.4 @RequestBody




//接收数据
@RequestMapping("test4")
public String test4(@RequestBody User user) {
    System.out.println(user);
    return "ok";
}
7.5 Jackson常用注解
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @JsonProperty("id2") //属性改名
    private Integer id;
    @JsonIgnore
    private String name;  //name属性将不再出现在JSON中
    @JsonFormat(pattern = "yyy-MM-dd hh:mm:ss",timezone = "GMT+8")
    private Date birth; //格式化了Date
    //@JsonInclude(JsonInclude.Include.NON_NULL)//如果空值将会被排除在JSON之外
    @JsonInclude(JsonInclude.Include.NON_EMPTY)//不是null且长度不为0就被包含在JSON中
    private List<String> hobby;
    
    @JsonSerialize(using = MySerializer.class)
	private Double salary = 10000.126;//在输出此属性时,使用MySerializers输出
}
public class MySerializer extends JsonSerializer<Double> {
    @Override
    public void serialize(Double value, JsonGenerator gen,
                          SerializerProvider serializer) throws IOException {
        //将Double salary的值四舍五入
        String number = BigDecimal.valueOf(value).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        //输出 四舍五入的值
        gen.writeNumber(number);
    }
}
7.6 FastJson

导入依赖

<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>fastjsonartifactId>
    <version>1.2.52.sec06version>
dependency>

安装FastJson

<mvc:annotation-driven>
    
    <mvc:message-converters>
        <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
            
            <property name="supportedMediaTypes">
                <list>
                    <value>application/jsonvalue>
                list>
            property>
        bean>
    mvc:message-converters>
mvc:annotation-driven>

使用

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User2 {
    @JSONField (serialize = false) //属性不仅如此序列号
    private Integer id;
    @JSONField (name="NAME",serialzeFeatures = SerializerFeature.WriteNullStringAsEmpty)
    private String name ; //改属性名称,属性值为空,输出一个“ ”
    @JSONField (serialzeFeatures = SerializerFeature.WriteMapNullValue)
    private String city; //如果值为空输出null
    @JSONField ( format="yyyy/MM/dd")
    private Date birth;
    
    
    @JSONField(serializeUsing = MySerializer2.class)
    private Double salary; //元
}
public class MySerializer2 implements ObjectSerializer {
    public void write(JSONSerializer jsonSerializer, Object object, Object o1,
                      Type type, int i) throws IOException {
        Double value = (Double) object;
        String text = value + "元";
        jsonSerializer.write(text);
    }
}

常用注解

  • 日期格式化:@JSONField(format=“yyyy/MM/dd”)属性名修改:@JSONField(name=“birth”)
  • 忽略属性:@JSONField(serialize = false)
  • 包含null值: @JSONField(serialzeFeatures = SerializerFeature.WriteMapNulValue)默认会忽略所有null值,有 此注解会输出null@JSONField(serialzeFeatures = SerializerFeature.WriteNullStringAsEmpty) null的String输出为""
  • 自定义序列化: @JSONField(serializeUsing = MySerializer2.class)
8 异常解析器

Controller中的每个Handler自己处理异常

此种处理方案,异常处理逻辑,分散在各个handler中,不利于集中管理

/**
 * 异常解析器
 * 执行时机:任何一个handler抛出异常时
 */
public class MyExceptionResolve implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        if (e instanceof MyException1) {
            //error1.jsp
            modelAndView.setViewName("redirect:/error1");
        } else if (e instanceof MyException2){
            //error2.jsp
            modelAndView.setViewName("redirect:/error12");
        } else if (e instanceof MyException3){
            //error3.jsp
            modelAndView.setViewName("redirect:/error3");
        }
        return modelAndView;
    }
}

<bean class="net.lj.resolve.MyExceptionResolve"/>
//在需要的方法处使用
throw new MyException1("test1")
9 拦截器

作用:抽取handler中的冗余功能

9.1 定义拦截器

执行顺序: preHandle–postHandle–afterCompletion

public class MyInterceptor implements HandlerInterceptor {
    //判断登录状态
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        if (session.getAttribute("state") != null) {
            return true;//放行,执行后续handler
        }
        //中断之前响应请求
        response.sendRedirect("/login.jsp"); //登录
        return false;//终端请求,不再执行handler
    }

    //handler之后,响应之前执行
    //用于改动请求中数据
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    //在视图渲染完毕后执行
    //资源回收
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}
9.2 配置拦截器

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/inter/test1 " />
        <mvc:mapping path= "/inter/test2" />
        <mvc:mapping path="/inter/test*" /> 
        <mvc:mapping path= "/inter/**" />
        <mvc:exclude-mapping path=" /inter/a/**"/>
        <bean class="net.lj.interceptor.MyInterceptor"/>
    mvc:interceptor>
mvc:interceptors>
10 上传 10.1 导入依赖
<dependency>
    <groupId>commons-iogroupId>
    <artifactId>commons-ioartifactId>
    <version>2.6version>
dependency>
<dependency>
    <groupId>commons-fileuploadgroupId>
    <artifactId>commons-fileuploadartifactId>
    <version>1.4version>
    <exclusions>
        <exclusion>
            <groupId>javax.servletgroupId>
            <artifactId>servlet-apiartifactId>
        exclusion>
    exclusions>
dependency>
10.2 表单
file:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    
bean>
public class UploadController {

    @RequestMapping("/test1")
    public String test1(MultipartFile source, HttpSession session) throws Exception{
        System.out.println("test1");
        //获取上传文件的原始名称
        String filename = source.getOriginalFilename();
        //生成唯一名称
        String uniqueFileName = UUID.randomUUID().toString();
        //获取文件后缀,扩展名
        String ext = FilenameUtils.getExtension(filename);
        //拼接完整文件名
        String uniqueFileName2 = uniqueFileName + "." + ext;

        //获取上传文件的类型
        String contentType = source.getContentType();
        System.out.println(filename);
        System.out.println(contentType);

        //保存文件
        //source.transferTo(new File("d:/abc.js"));
        String realPath = session.getServletContext().getRealPath("/upload");
        System.out.println(realPath);
        source.transferTo(new File(realPath + "\" + uniqueFileName2));
        return "index";
    }
}
public class MyInterceptor implements HandlerInterceptor {
    private Long maxFileUploadSize;

    public Long getMaxFileUploadSize() {
        return maxFileUploadSize;
    }

    public void setMaxFileUploadSize(Long maxFileUploadSize) {
        this.maxFileUploadSize = maxFileUploadSize;
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断上传文件大小
        ServletRequestContext servletRequestContext = new ServletRequestContext(request);
        long l = servletRequestContext.contentLength();
        if (l > 1048576) {
            throw new MaxUploadSizeExceededException(1048576);
        }
        return true;
    }
}


<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/test1"/>
        <bean class="net.lj.interceptor.MyInterceptor">
            <property name="maxFileUploadSize" value="1048576"/>
        bean>
    mvc:interceptor>
mvc:interceptors>
11.下载
<a href="${pageContext.request.contextPath}/download1?name=jquery-3.5.1.min.js">下载a>
@RequestMapping("/download1")
public void test1(String name, HttpSession session, HttpServletResponse response)throws IOException {
    String realPath = session.getServletContext().getRealPath("/upload");
    String filePath = realPath + "//" + name;

    //没置响应头﹑告知浏览器,要以附件的形式保存内容  filename=浏览器显示的下载文件名
    response.setHeader("content-disposition","attachment;filename="+name);
    //响应
    IOUtils.copy(new FileInputStream(filePath), response.getOutputStream());
}
12.验证码

导入依赖


<dependency>
    <groupId>com.github.pengglegroupId>
    <artifactId>kaptchaartifactId>
    <version>2.3.2version>
    
    <exclusions>
        <exclusion>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
        exclusion>
    exclusions>
dependency>

web.xml中配置servlet

<servlet>
    <servlet-name>capservlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServletservlet-class>
    <init-param>
        <param-name>kaptcha.borderparam-name>
        <param-value>noparam-value>
    init-param>
    <init-param>
        <param-name>kaptcha.textproducer.char.stringparam-name>
        <param-value>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789param-value>
    init-param>
    <init-param>
        <param-name>kaptcha.background.clear.toparam-name>
        <param-value>211,229,237param-value>
    init-param>
    <init-param>
        
        <param-name>kaptcha.session.keyparam-name>
        <param-value>kaptchaparam-value>
    init-param>
servlet>
<servlet-mapping>
    <servlet-name>capservlet-name>
    <url-pattern>/captchaurl-pattern>
servlet-mapping>
Constant默认值描述
kaptcha.borderyes图片边框,合法值:yes , no
kaptcha.border.colorblack边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue
kaptcha.border.thickness1边框厚度,合法值:>0
kaptcha.image.width200图片宽
kaptcha.image.height50图片高
kaptcha.producer.implcom.google.code.kaptcha.impl.DefaultKaptcha图片实现类
kaptcha.textproducer.implcom.google.code.kaptcha.text.impl.DefaultTextCreator文本实现类
kaptcha.textproducer.char.stringabcde2345678gfynmnpwx文本集合,验证码值从此集合中获取
kaptcha.textproducer.char.length4验证码长度
kaptcha.textproducer.font.namesArial, Courier字体
kaptcha.textproducer.font.size40px.字体大小
kaptcha.textproducer.font.colorblack字体颜色,合法值: r,g,b 或者 white,black,blue
kaptcha.textproducer.char.space2文字间隔
kaptcha.noise.implcom.google.code.kaptcha.impl.DefaultNoise干扰实现类
kaptcha.noise.colorblack干扰 颜色,合法值: r,g,b 或者 white,black,blue
kaptcha.obscurificator.implcom.google.code.kaptcha.impl.WaterRipple图片样式: 水纹com.google.code.kaptcha.impl.WaterRipple, 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy, 阴影com.google.code.kaptcha.impl.ShadowGimpy
kaptcha.background.implcom.google.code.kaptcha.impl.DefaultBackground背景实现类
kaptcha.background.clear.fromlight grey背景颜色渐变,开始颜色
kaptcha.background.clear.towhite背景颜色渐变, 结束颜色
kaptcha.word.implcom.google.code.kaptcha.text.impl.DefaultWordRenderer文字渲染器
kaptcha.session.keyKAPTCHA_SESSION_KEYsession key
kaptcha.session.dateKAPTCHA_SESSION_DATEsession date

编辑前端页面

<form action="${pageContext.request.contextPath}/testCaptcha">
    <img src="${pageContext.request.contextPath}/captcha" id="cap" onclick="refresh()"/>
    <input type="text" name="captcha">
    <br>
    <input type="submit" value="提交">
form>
<script>
    function refresh() {
        var img = document.getElementById("cap");
        img.src = "${pageContext.request.contextPath}/captcha?" + new Date().getTime();
    }
script>

编辑比对方法

@RequestMapping("testCaptcha")
public String testCaptcha(String cap, HttpSession session) {
    //比对
    String realCap = (String) session.getAttribute("captcha");
    if (realCap.equalsIgnoreCase(cap)) { //忽略大小写
        return "index";
    }
    return "error1";
}
13.REST 13.1 概念

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

两个核心要求:

  • 每个资源有唯一标识
  • 不同的行为,使用对应的http-method
访问标识资源
http://localhost:8989/xxx/users所有用户
http://localhost:8989/xxx/users/1用户1
http://localhost:8989/xxx/users/1/orders用户1的所有订单
请求方式标识意图
GEThttp://localhost:8989/xxx/users查询所有用户
POSThttp://localhost:8989/xxx/users在所有用户中增加一个
PUThttp://localhost:8989/xxx/users在所有用户中修改一个
DELETEhttp://localhost:8989/xxx/users/1删除用户1
GEThttp://localhost:8989/xxx/users/1查询用户1
GEThttp://localhost:8989/xxx/users/1/orders查询用户1的所有订单
POSThttp://localhost:8989/xxx/users/1/orders在用户1的所有订单中增加一个

优点:

  • 看URL知道要什么
  • 看http-method知道干什么
13.2 用法

Controller方法

@RestController
public class MyRestController {

    @GetMapping("/users") //规定请求方法是GET,若请求路径正确但不是GET请求,失败!
    public List<User> queryUsers() {
        System.out.println("query users");
        User user1 = new User(1, "张三");
        User user2 = new User(2, "李四");
        return Arrays.asList(user1, user1);
    }

    @GetMapping("/user/{id}")
    public User queryOne(@PathVariable Integer id) {
        System.out.println("=====" + id);
        return new User(1, "张三");
    }

    @DeleteMapping("/user/{id}")
    public String deleteOne(@PathVariable Integer id) {
        System.out.println("delete:====" + id);
        return "ok";
    }

    @PostMapping("/users")
    public String insertUser(@RequestBody User user) {
        System.out.println("insert==" + user);
        return "ok";
    }

    @PutMapping("/users")
    public String updateUser(@RequestBody User user) {
        System.out.println("update" + user);
        return "ok";
    }
}

前端页面请求







14 跨域问题 14.1 域

域:协议+IP+端口

  • http://localhost:8989
  • http://localhost:8080
  • http://www.baidu.com:80
14.2 Ajax跨域问题
  • Ajax发送请求时,不允许跨域,以防用户信息泄露。
  • 当Ajax跨域请求时,响应会被浏览器拦截(同源策略),并报错。即浏览器默认不允许ajax跨域得到响应内容。
  • 互相信任的域之间如果需要ajax访问,(比如前后端分离项目中,前端项目和后端项目之间),则需要额外的设置才可正常请求。
14.3 解决方法

允许其他域访问
在被访问方的Controller类上,添加注解

Ajax请求的url写完整绝对路径

@CrossOrigin("http://localhost:8080")  //允许此域访问
public class SysUserController(){
    ...
}

携带对方cookie,使得session可用

在访问方,Ajax中添加属性

$.ajax({
    type: "post",
    url: "http://localhost:8989/users/200", //完整路径
    xhrFields:{
    //跨域携带cookie
    withCredentials: true
    },
    success:function (ret) {
        ...
    }
});var xhr = new XMLHttpRequest();
//跨域携带cookie
xhr.withCredentials = true;
15 SpringMVC执行流程

实例、SSM实现登录 一、准备数据库
CREATE DATABASE shop CHARSET=UTF8;
USE shop;

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL,
  `password` varchar(20) DEFAULT NULL,
  `telephone` varchar(11) DEFAULT NULL,
  `register_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `popedom` int(11) DEFAULT NULL COMMENT '0:管理员;1:普通用户',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

INSERT INTO `t_user` VALUES ('1', 'root', '12345', '15734345678', '2016-12-02 08:40:35', '0');
INSERT INTO `t_user` VALUES ('2', 'admin1', '11111', '13956567889', '2016-12-20 09:51:43', '1');
INSERT INTO `t_user` VALUES ('3', 'admin2', '22222', '13956678907', '2016-12-20 09:52:36', '1');
INSERT INTO `t_user` VALUES ('4', 'admin3', '33333', '15890905678', '2016-12-05 09:52:56', '1');
二、创建Maven项目并在pom中添加依赖
<dependencies>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-coreartifactId>
        <version>${spring.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-beansartifactId>
        <version>${spring.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-contextartifactId>
        <version>${spring.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-testartifactId>
        <version>${spring.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-jdbcartifactId>
        <version>${spring.version}version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.49version>
    dependency>
    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druidartifactId>
        <version>1.1.24version>
    dependency>
    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.5.5version>
    dependency>
    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatis-springartifactId>
        <version>2.0.5version>
    dependency>
    
    <dependency>
        <groupId>log4jgroupId>
        <artifactId>log4jartifactId>
        <version>1.2.17version>
    dependency>
    
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.13version>
        <scope>testscope>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-webartifactId>
        <version>${spring.version}version>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-webmvcartifactId>
        <version>${spring.version}version>
    dependency>
    
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>jstlartifactId>
        <version>1.2version>
    dependency>
    
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>javax.servlet-apiartifactId>
        <version>3.1.0version>
        <scope>providedscope>
    dependency>
dependencies>
三、在Resources目录下创建日志文件log4j.properties,以及数据库配置文件jdbc.properties
log4j.rootLogger=WARN, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/shop?useSSL=false
jdbc.username = root
jdbc.password = 123456
四、给项目添加Web功能和配置Tomcat

1、右键项目名—>Add Framework Support…—>勾选Web Application,ok确认

2、右上角Add Configuration…,之后再左上角点击“+”选择Tomcat Server中的Local

3、配置Tomcat路径(已下载的),最后点击右下角修复(Fix)。

需要注意点击Fix后d出内容的名称,因为它会加在上一个面板的URL上(删掉不加也行,高兴就好)

五、创建Bean包和User实体类
package net.lj.shop.bean;

import java.util.Date;

/**
 * 用户实体类
 */
public class User {
    private int id;
    private String username;
    private String password;
    private String telephone;
    private Date registerTime;
    private int popedom;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Date getRegisterTime() {
        return registerTime;
    }

    public void setRegisterTime(Date registerTime) {
        this.registerTime = registerTime;
    }

    public int getPopedom() {
        return popedom;
    }

    public void setPopedom(int popedom) {
        this.popedom = popedom;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", telephone='" + telephone + '\'' +
                ", registerTime=" + registerTime +
                ", popedom=" + popedom +
                '}';
    }
}
六、创建Mapper包和用户映射器接口UserMapper
package net.lj.shop.mapper;

import net.lj.shop.bean.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

/**
 * 用户映射器接口
 */
@Mapper
public interface UserMapper {
    User login(@Param("username") String username, @Param("password") String password);
}
七、创建service包和用户服务类 -UserService
package net.lj.shop.service;

import net.lj.shop.bean.User;
import net.lj.shop.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 用户服务类
 */
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User login(String username, String password) {
        return userMapper.login(username, password);
    }
}
八、创建controller包和用户控制器 -UserController
package net.lj.shop.controller;

import net.lj.shop.service.UserService;
import net.lj.shop.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpSession;

/**
 * 用户控制器
 */
@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        HttpSession session) {
        // 调用用户服务对象的登录方法
        User user = userService.login(username, password);
        // 判断用户是否登录成功
        if (user != null) {
            // 将登录用户名写入会话
            session.setAttribute("username", username);
            // 删除会话里可能存在的登录错误提示信息
            if (session.getAttribute("loginMsg") != null) {
                session.removeAttribute("loginMsg");
            }
            // 判断用户角色,跳转到不同页面
            if (user.getPopedom() == 0) {
                // 跳转到后台管理页面
                return "backend/management"; // 逻辑视图名
            } else {
                // 跳转到前台首页
                return "frontend/index"; // 逻辑视图名
            }
        } else {
            // 将登录错误信息写入会话
            session.setAttribute("loginMsg", "用户名或密码错误!");
            // 跳转到前台登录页面
            return "frontend/login"; // 逻辑视图名
        }
    }

    @RequestMapping("/logout")
    public String logout(HttpSession session) {
        // 删除会话里保存的用户名信息
        session.removeAttribute("username");
        // 结束会话
        session.invalidate();
        // 跳转到前台登录页面
        return "frontend/login"; // 逻辑视图名
    }
}
九、在Resources目录下创建mapper文件夹和用户映射器配置文件 UserMapper.xml

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="net.lj.shop.mapper.UserMapper">
    
    <resultMap id="userMap" type="net.lj.shop.bean.User">
        <result property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="password" column="password"/>
        <result property="telephone" column="telephone"/>
        <result property="registerTime" javaType="java.util.Date" column="register_time" jdbcType="TIMESTAMP"/>
        <result property="popedom" column="popedom"/>
    resultMap>

    
    <select id="login" resultMap="userMap">
        SELECT * FROM t_user WHERE username = #{username} AND password = #{password};
    select>
mapper>

十、在Resources目录下创建config文件夹以及Spring配置文件spring-config.xml、SpringMVC配置文件spring-mvc-config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    
    <context:component-scan base-package="net.lj.shop"/>

    
    <context:property-placeholder location="classpath:jdbc.properties"/>

    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        
        
        <property name="initialSize" value="10"/>
        <property name="minIdle" value="10"/>
        <property name="maxActive" value="200"/>

        
        <property name="maxWait" value="6000"/>

        
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>

        
        <property name="minEvictableIdleTimeMillis" value="300000"/>

        <property name="validationQuery" value="SELECT 'x'"/>
        <property name="testWhileIdle" value="true"/>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="false"/>

        
        <property name="poolPreparedStatements" value="true"/>
        <property name="maxPoolPreparedStatementPerConnectionSize" value="100"/>

        
        <property name="filters" value="stat"/>
    bean>

    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        
        <property name="dataSource" ref="dataSource"/>
        
        <property name="mapperLocations" value="classpath:mapper/UserMapper.xml"/>
    bean>

    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        
        <property name="basePackage" value="net.lj.shop.mapper"/>
    bean>
beans>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    <mvc:resources mapping="/css/**" location="/WEB-INF/css/"/>
    <mvc:resources mapping="/js/**" location="/WEB-INF/js/"/>
    <mvc:resources mapping="/images/**" location="/WEB-INF/images/"/>

    
    <mvc:annotation-driven/>

    
    <mvc:view-controller path="user/login" view-name="frontend/login" />

    
    <context:component-scan base-package="net.lj.shop.controller"/>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:viewClass="org.springframework.web.servlet.view.JstlView"
          p:prefix="/WEB-INF/views/"
          p:suffix=".jsp"/>

    
    <context:component-scan base-package="net.lj.shop">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    context:component-scan>
beans>
十一、编辑Web部署描述文件 web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <display-name>simonshopdisplay-name>
    <welcome-file-list>
        <welcome-file>/WEB-INF/views/frontend/login.jspwelcome-file>
    welcome-file-list>

    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>

    
    <context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath:config/spring-config.xmlparam-value>
    context-param>

    
    <servlet>
        <servlet-name>DispatcherServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:config/spring-mvc-config.xmlparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>

    <servlet-mapping>
        <servlet-name>DispatcherServletservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

    
    <filter>
        <filter-name>Character Encodingfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>UTF-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>Character Encodingfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>
web-app>
十二、创建前端页面

1、login.css
/* 样式 */
body {
    margin: 0px;
    text-align: center;
    background: #cccccc;
}
2、check.js
/**
 * 检验登录表单
 *
 * @returns {Boolean}
 */
function checkLoginForm() {
    // 获取用户名文本框
    var username = document.getElementById("username");
    // 获取密码文本框
    var password = document.getElementById("password");
    // 非空校验
    if (username.value == "") {
        alert("用户名不能为空!");
        // 让用户名文本框获得焦点
        username.focus();
        return false;
    }
    if (password.value == "") {
        alert("密码不能为空!");
        // 让密码文本框获得焦点
        password.focus();
        return false;
    }
    return true; // 表明可以提交数据到服务器端
}
3、login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>





    用户登录
    
    
    

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/langs/877593.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-13
下一篇2022-05-13

发表评论

登录后才能评论

评论列表(0条)