你真的了解LAMP/LNMP架构吗?(详解PHP和Apache和MariaDB之间的工作联系)以及安装php7,8版本。

Posted 让我三行代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你真的了解LAMP/LNMP架构吗?(详解PHP和Apache和MariaDB之间的工作联系)以及安装php7,8版本。相关的知识,希望对你有一定的参考价值。

前言:

昨天搭建个FileRun(个人网盘)实验,做个Lychee(图床)实验。这两个都要用到LAMP/LNMP实验,当我做到安装和配置php时,我脑子里就突然来有个自灵魂的拷问:这个PHP到底有什么用呢?为啥搭建个xxx系统都需要用到PHP?Apache可以和nginx我们可以任意选一个,mysql可以和MariaDB我们也可以任意选一个,唯独PHP永远都是PHP,LAMP/LNMP(除了Linux系统)就PHP没有换过。
在以往无论是搭建WordPress还是OwnCloud我就只会使用,比如:需要php的时候我就安装个php。需要个Nginx我就安装个Nginx…
但是当需要匹配php时,就会蒙圈。
直到昨天网上查下,其中奥秘令我茅塞顿开。

标题

参考友军文档:
https://blog.csdn.net/ziyifengfei/article/details/80078657
目前来说,网站页面主要分为静态页面和动态页面,纯静态页面组成的网站现在相对比较少见,大型网站一般使用的是动态网站建站技术,还有一部分网站是静态网页与动态网页共存。
本文以Apache服务器、php语言为例,详解动态网站的访问过程,下面直接切入本文主题。

第一个知识点:用户端访问服务器端的html文件

(1)通过本机配置好的DNS域名服务器地址寻找DNS服务器,将网站URL中的Web主机域名解析为Web服务器所在的Linux操作系统(Apache通常与Linux操作系统组合使用)中对应的IP地址。

(2)通过HTTP协议(超文本传输协议)去连接上述IP地址的服务器系统,通过默认80端口(默认的端口是80,也有其他端口,输入URL时一般不用输入端口)请求Apache服务器上相应目录下的html文件(如index.htm)。

(3)Apache服务器收到用户的访问请求后,在它管理的文档目录中找到并打开相应的html文件(如index.htm),将文件内容响应给客户端浏览器(即用户)。

(4)浏览器收到Web服务器的响应后,接收并下载服务器端的html静态代码,然后浏览器解读代码,最终将网页呈现出来(由于不同的浏览器对于代码的解读规则会不一样,所以不同浏览器对于相同的网页呈现的最终页面效果会有所差异)。

第二个知识点:用户端访问服务器端的php文件

(1)该步与上面访问html静态网页是一样的,通过DNS服务器解析出相应的Web服务器的IP地址。

(2)与上面访问html静态页面相似,不过最后请求的是Apache服务器上相应目录下的php文件,如index.php。

(3)Apache服务器本身不能处理php动态语言脚本文件,就寻找并委托PHP应用服务器来处理(服务器端事先得安装PHP应用服务器),Apache服务器将用户请求访问的php文件(如index.php)文件交给PHP应用服务器。

(4)PHP应用服务器接收php文件(如index.php),打开并解释php文件,最终翻译成html静态代码,再将html静态代码交还给Apache服务器,Apache服务器将接收到的html静态代码输出到客户端浏览器(即用户)。

(5)与上面访问html静态页面相同,浏览器收到Web服务器的响应后,接收并下载服务器端的html静态代码,然后浏览器解

读代码,最终将网页呈现出来。

第三个知识点:用户端访问服务器端的MySQL数据库
如果用户需要对MySQL数据库中的数据进行操作,那么就需要在服务器端安装数据库管理软件MySQL服务器,用来存储和管理网站数据。由于Apache服务器是无法连接和操作MySQL服务器,所以还需要安装php应用服务器,这样Apache服务器就委托php应用服务器去连接和操作数据库,在对数据库中的数据进行管理的时候,一般都需要用到结构化查询语句,即SQL语句。
(1)该步与上面访问php文件一样,通过DNS服务器解析出相应的Web服务器的IP地址。

(2)与上面访问php文件一样,请求访问Apache服务器上相应目录下的php文件。

(3)与上面访问php文件一样,PHP应用服务器接收Apache服务器的委托,收到相应的php文件。

(4)PHP应用服务器打开php文件,在php文件中通过对数据库连接的代码来连接本机或者网络上其他机器上的MySQL数据库,并在php程序中通过执行标准的SQL查询语句来获取数据库中的数据,再通过PHP应用服务器将数据生成html静态代码。

(5)浏览器收到Web服务器的响应后,接收并下载服务器端的html静态代码,然后浏览器解读代码,最终将网页呈现出来。

需要注意的是,文中(2)与(3)的区别是,一个访问了数据库,另一个没有访问数据库,所以在过程中有点差别。

总结:大的方面PHP有两种功能:
1、帮助Apache解析以.php结尾的文件(动态文件)
2、充当Apache和Mysql/MariaDB之间的桥梁,Apache想要和数据库通信,必须通过php。

安装PHP7、8版本

1、更新php的Yum仓库

yum install -y epel-release yum-utils
yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm

2、启用PHP 7.4 Remi 存储库:

yum-config-manager --enable remi-php74

3、安装PHP 7.4:

yum install -y php-fpm php     

4、查看增加了多少php仓库

[root@node3 yum.repos.d]# ll /etc/yum.repos.d/
-rw-r--r--  1 root root  446 Feb 15 05:37 remi-glpi91.repo
-rw-r--r--  1 root root  446 Feb 15 05:37 remi-glpi92.repo
-rw-r--r--  1 root root  446 Feb 15 05:37 remi-glpi93.repo
-rw-r--r--  1 root root  446 Feb 15 05:37 remi-glpi94.repo
-rw-r--r--  1 root root  855 Feb 15 05:37 remi-modular.repo
-rw-r--r--  1 root root  456 Feb 15 05:37 remi-php54.repo
-rw-r--r--  1 root root 1314 Feb 15 05:37 remi-php70.repo
-rw-r--r--  1 root root 1314 Feb 15 05:37 remi-php71.repo
-rw-r--r--  1 root root 1314 Feb 15 05:37 remi-php72.repo
-rw-r--r--  1 root root 1314 Feb 15 05:37 remi-php73.repo
-rw-r--r--  1 root root 1314 Mar 31 06:39 remi-php74.repo
-rw-r--r--  1 root root 1314 Feb 15 05:37 remi-php80.repo
-rw-r--r--  1 root root 1314 Mar 31 06:39 remi-php81.repo
-rw-r--r--  1 root root 2605 Feb 15 05:37 remi.repo
-rw-r--r--  1 root root  750 Feb 15 05:37 remi-safe.repo

可以看到有php70,71,72,73,74,80,81版本
上面要是的是使用php74版本
如果想要使用其它的php版本如何操作呢?

(1)先开启对应的yum仓库

#先查看对用的仓库开启没有:disabled表示没有开启,enabled表示开启了
yum repolist all | grep php
...
remi-php71                           Remi's PHP 7.1 RPM reposito disabled
remi-php71-debuginfo/x86_64          Remi's PHP 7.1 RPM reposito disabled
remi-php71-test                      Remi's PHP 7.1 test RPM rep disabled
remi-php71-test-debuginfo/x86_64     Remi's PHP 7.1 test RPM rep disabled
remi-php72                           Remi's PHP 7.2 RPM reposito disabled
remi-php72-debuginfo/x86_64          Remi's PHP 7.2 RPM reposito disabled
remi-php72-test                      Remi's PHP 7.2 test RPM rep disabled
remi-php72-test-debuginfo/x86_64     Remi's PHP 7.2 test RPM rep disabled
remi-php73                           Remi's PHP 7.3 RPM reposito disabled
remi-php73-debuginfo/x86_64          Remi's PHP 7.3 RPM reposito disabled
remi-php73-test                      Remi's PHP 7.3 test RPM rep disabled
remi-php73-test-debuginfo/x86_64     Remi's PHP 7.3 test RPM rep disabled
remi-php74                           Remi's PHP 7.4 RPM reposito enabled:    436
remi-php74-debuginfo/x86_64          Remi's PHP 7.4 RPM reposito disabled
remi-php74-test                      Remi's PHP 7.4 test RPM rep disabled
remi-php74-test-debuginfo/x86_64     Remi's PHP 7.4 test RPM rep disabled
remi-php80                           Remi's PHP 8.0 RPM reposito disabled
remi-php80-debuginfo/x86_64          Remi's PHP 8.0 RPM reposito disabled
remi-php80-test                      Remi's PHP 8.0 test RPM rep disabled
remi-php80-test-debuginfo/x86_64     Remi's PHP 8.0 test RPM rep disabled
remi-php81                           Remi's PHP 8.1 RPM reposito enabled:    294
remi-php81-debuginfo/x86_64          Remi's PHP 8.1 RPM reposito disabled
remi-php81-test                      Remi's PHP 8.1 test RPM rep disabled
remi-php81-test-debuginfo/x86_64     Remi's PHP 8.1 test RPM rep disabled
...

然后开启仓库

yum-config-manager --enable remi-php81               #最后填写要开启仓库的名称,就通过上述命令查看

(2)安装相应的程序或组件
如果不知道安装的程序或组件可以,查看:

yum search php81          #查看找相应的组件,然后安装
php81-php-pecl-http-message-devel.x86_64 : php81-php-pecl-http-message developer files (headers)
php81-php-pecl-pcsc-devel.x86_64 : php81-php-pecl-pcsc developer files (header)
php81-php-pecl-psr-devel.x86_64 : php81-php-pecl-psr developer files (header)
php81-php-pecl-raphf-devel.x86_64 : php81-php-pecl-raphf developer files (header)
php81-php-pecl-xmldiff-devel.x86_64 : php81-php-pecl-xmldiff developer files (header)
php81-php-pecl-yaconf-devel.x86_64 : php81-php-pecl-yaconf developer files (header)
php81-php-zephir-parser-devel.x86_64 : php81-php-zephir-parser developer files (headers)
php81-php-zstd-devel.x86_64 : php81-php-zstd developer files (header)
php81-runtime.x86_64 : Package that handles php81 Software Collection.
php81-scldevel.x86_64 : Package shipping development files for php81
php81-syspaths.x86_64 : System-wide wrappers for the php81 package
php81.x86_64 : Package that installs PHP 8.1
php81-build.x86_64 : Package shipping basic build configuration
php81-php.x86_64 : PHP scripting language for creating dynamic web sites
php81-php-ast.x86_64 : Abstract Syntax Tree
php81-php-bcmath.x86_64 : A module for PHP applications for using the bcmath library
php81-php-brotli.x86_64 : Brotli Extension for PHP
php81-php-cli.x86_64 : Command-line interface for PHP
php81-php-common.x86_64 : Common files for PHP
php81-php-dba.x86_64 : A database abstraction layer module for PHP applications
php81-php-dbg.x86_64 : The interactive PHP debugger
php81-php-devel.x86_64 : Files needed for building PHP extensions
php81-php-embedded.x86_64 : PHP library for embedding in applications
php81-php-enchant.x86_64 : Enchant spelling extension for PHP applications
php81-php-ffi.x86_64 : Foreign Function Interface
php81-php-fpm.x86_64 : PHP FastCGI Process Manager
php81-php-gd.x86_64 : A module for PHP applications for using the gd graphics library
php81-php-geos.x86_64 : PHP module for GEOS
php81-php-gmp.x86_64 : A module for PHP applications for using the GNU MP library
php81-php-horde-horde-lz4.x86_64 : Horde LZ4 Compression Extension
php81-php-imap.x86_64 : A module for PHP applications that use IMAP
php81-php-intl.x86_64 : Internationalization extension for PHP applications
php81-php-ldap.x86_64 : A module for PHP applications that use LDAP
php81-php-libvirt.x86_64 : PHP language binding for Libvirt
php81-php-libvirt-doc.noarch : Document of php-libvirt
php81-php-litespeed.x86_64 : LiteSpeed Web Server PHP support
php81-php-lz4.x86_64 : LZ4 Extension for PHP
php81-php-maxminddb.x86_64 : MaxMind DB Reader extension
php81-php-mbstring.x86_64 : A module for PHP applications which need multi-byte string handling
php81-php-mysqlnd.x86_64 : A module for PHP applications that use MySQL databases
php81-php-oci8.x86_64 : A module for PHP applications that use OCI8 databases
php81-php-odbc.x86_64 : A module for PHP applications that use ODBC databases
php81-php-opcache.x86_64 : The Zend OPcache
php81-php-pdo.x86_64 : A database access abstraction module for PHP applications
php81-php-pdo-dblib.x86_64 : PDO dr

如果安装的是php81,那么启动命令:

systemctl restart php81-php-fpm

你真的了解吗?一文详解底层原理!

前言

一、SpringMVC简介

1.1、SpringMVC引言

为了使Spring有可插入的MVC架构,SpringFrameWork在Spring基础上开发SpringMVC框架,从而在使用Spring进行WEB开发时可以选择使用Spring的SpringMVC框架作为web开发的控制器框架

1.2、SpringMVC的优势

SpringMVC是一个典型的轻量级MVC框架,在整个MVC架构中充当控制器框架,相对于之前的struts2框架,SpringMVC运行更快,其注解式开发更高效灵活

  1. 可以和Spring框架无缝整合。
  2. 运行效率远远高于struts2框架。
  3. 注解式开发更高效。

二、SpringMVC入门

2.1、环境搭建

2.1.1、引入依赖

依赖就忽略了,我放在了评论区!

2.1.2、编写配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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"
  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">

<!--  1. 开启注解扫描-->
  <context:component-scan base-package="com.lin.controller"/>
<!--  2. 配置处理器映射器-->
<!--  <bean  />-->
<!--  3. 开启处理器适配器-->
<!--  <bean  />-->
<!--  上面两段配置被下面的一句话所替代(封装)-->
  <mvc:annotation-driven />
  <!--  4. 开启视图解析器-->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
</beans>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.

2.1.3、配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

<!--  配置springmvc的核心servlet-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
<!--      告诉springmvc配置文件的位置-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
<!--    拦截所有请求-->
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.

2.1.4、编写控制器

package com.lin.controller;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author XiaoLin
 * @date 2021/2/17 17:09
 */
@Controller
public class HellowController {

  /**
      * @Description:第一个springmvc测试类
      * @author XiaoLin
      * @date 2021/2/17
      * @Param: [username, password]
      * @return java.lang.String
      */
     /*
      RequestMapping的修饰范围:可以用在类上和方法上,他的作用如下:
      1. 用在方法上可以给当前方法加入指定的请求路径
      2. 用在类上可以给类中的所有方法都加入一个统一的请求路径,在这个方法访问之前都必须加上
      */
  @RequestMapping("/hello")
  public String hello(String username,String password){
    System.out.println("hello");
    return "index";
  }
}
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.

2.2、注解详解

2.2.1、@Controller

该注解用来类上标识这是一个控制器组件类并创建这个类实例,告诉spring我是一个控制器。

2.2.2、@RequestMapping

这个注解可以作用在方法上或者是类上,用来指定请求路径。

2.3、SpringMVC的跳转方式

传统的Servlet开发跳转方式有两种:

  1. forward:forward跳转,是在服务器内部跳转,所以是一次请求,地址栏不变。跳转时可以携带数据进行传递(使用request作用域进行传递)。
  2. redirect:redirect跳转是客户端跳转,所以是多次请求,地址栏会改变,跳转时不可以携带数据传递。

2.3.1、Controller ——>前台页面

2.3.1.1、forward

通过测试我们可以发现,SpringMVC默认的就是使用请求转发的方式来进行跳转到前台页面的;

@Controller
@RequestMapping("forwoartAndRedirect")
public class TestForwoartAndRedirect {

  @RequestMapping("test")
  public String test(){
    System.out.println("test");
    return"index";
  }
}1.2.3.4.5.6.7.8.9.10.
2.3.1.2、redirect

如果我们想使用重定向的方式来进行跳转的话,需要使用SpringMVC提供给我们的关键字——redirect:来完成。

语法:return “redirect:/视图全路径名”;

**注意:**在redirect:后接页面的不是逻辑名,而是全路径名。因为redirect跳转不会经过视图解析器。

2.3.1Controller ——>Controller

2.3.1.1、forward

如果我们想使用请求转发的方式跳转到相同(不同)Controller的不同方法的时候,我们也需要使用SpringMVC提供的关键字:forward:。

语法:return:“forward: /需要跳转的类上的@RequestMapping的值/需要跳转的方法上的@RequestMapping的值;”

2.3.1.2、redirect

如果我们想使用重定向的方式跳转到相同(不同)Controller的不同方法的时候,我们也需要使用SpringMVC提供的关键字:redirect:。

语法:return:“redirect: /需要跳转的类上的@RequestMapping的值/需要跳转的方法上的@RequestMapping的值;”

2.4、SpringMVC的参数接收

2.4.1、Servlet接收参数的方式

在传统的Servlet开发,我们一般都是用这种方式来进行接收请求参数的。

// 接收名字为name的参数
request.getParameter(name)1.2.

他有几个需要注意的点:

  1. 参数要求是表单域的name属性。
  2. getParameter方法用于获取单个值, 返回类型是String。
  3. getParameterValues方法用于获取一组数据, 返回结果是String[]。
  4. 冗余代码较多, 使用麻烦, 类型需要自己转换。

2.4.2、SpringMVC的参数接收

SpringMVC使用的是控制器中方法形参列表来接收客户端的请求参数,他可以进行自动类型转换,要求传递参数的key要与对应方法的形参变量名一致才可以完成自动赋值。他的优势很明显:

  1. 简化参数接收形式(不需要调用任何方法, 需要什么参数, 就在控制器方法中提供什么参数)。
  2. 参数类型不需要自己转换了。日期时间(默认为yyyy/MM/dd)得注意,需要使用@DateTimeFormat注解声明日期转换时遵循的格式, 否则抛出400异常。
2.4.2.1、基本数据类型

要求传递参数的key要与对应方法的形参变量名一致才可以完成自动赋值。

2.4.2.2、对象类型

如果我们需要接收对象类型的话,直接将需要接收的对象作为控制器的方法参数声明即可。SpringMVC会自动封装对象,若传递参数key与对象中属性名一致,就会自动封装成对象。

2.4.2.3、数组类型

如果我们需要接收数组类型的时候,只需将要接收的数组类型直接声明为方法的形式参数即可。

2.4.2.4、集合类型

SpringMVC不能直接通过形式参数列表的方式接收集合类型的参数,如果需要接收集合类型的参数必须将集合放入一个对象中,并且提供get/set方法,才可以。推荐放入VO对象中进行封装,进而使用对象类型来进行接收。

2.5、SpringMVC接收参数中文乱码问题

2.5.1、GET请求

GET请求方式出现乱码需要分Tomcat版本进行讨论:

  1. Tomcat8.x版本之前:默认使用server.xml中的URIEncoding="ISO-8859-1"编码,而不是"UTF-8"编码,进而会出现中文乱码。
  2. Tomcat8.x版本之后:默认使用server.xml中的URIEncoding=“UTF-8”,所以不会出现中文乱码问题。

2.5.2、POST请求

SpringMVC中默认没有对POST请求进行任何编码处理,所以无论什么版本直接接收POST请求都会出现中文乱码。

2.5.2.1、自定义过滤器解决POST乱码请求

在Servlet阶段,我们学过过滤器,我们可以自定义过滤器来进行过滤编码。

package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定义编码filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.
 <!--配置post请求方式中文乱码的Filter-->
  <filter>
    <filter-name>charset</filter-name>
    <filter-class>com.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>1.2.3.4.5.6.7.8.9.10.11.12.13.14.
2.5.2.2、使用CharacterEncodingFilter解决POST乱码请求
  <!--配置post请求方式中文乱码的Filter-->
  <filter>
    <filter-name>charset</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>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.
package com.filter;

import javax.servlet.*;
import java.io.IOException;

//自定义编码filter
public class CharacterEncodingFilter  implements Filter {

    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.encoding = filterConfig.getInitParameter("encoding");
        System.out.println(encoding);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding);
        response.setCharacterEncoding(encoding);
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

2.6、SpringMVC中数据传递机制

2.6.1、什么事数据传递机制

数据传递机制主要包含三个问题:

  1. 数据如何存储?
  2. 如何在页面中获取数据?
  3. 在页面中获取的数据该如何展示?

2.6.2、Servlet的数据传递机制

在以前的Servlet开发中,我们一般是将数据放入作用域(request、session、application),如果数据是单个的直接用EL表达式在前端进行展示,如果是集合或者数组,可以用EL表达式➕JSTL标签进行遍历后在前端进行展示。

三、前端控制器

3.1、什么是前端控制器

在 MVC 框架中都存在一个前端控制器,在 WEB 应用的前端(Front)设置一个入口控制器(Controller),是用来提供一个集中的请求处理机制,所有的请求都被发往该控制器统一处理,然后把请求分发给各自相应的处理程序。一般用来做一个共同的处理,如权限检查,授权,日志记录等。因为前端控制的集中处理请求的能力,因此提高了可重用性和可拓展性。

在没有前端控制器的时候,我们是这样传递和处理请求的。

有了前端控制器之后,我们变成了这样。

3.2、代码实现

Spring MVC 已经提供了一个 DispatcherServlet 类作为前端控制器,所以要使用 Spring MVC 必须在web.xml 中配置前端控制器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
  <!-- Spring MVC 前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-
      class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 指定 Spring 容器启动加载的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:mvc.xml</param-value>
    </init-param>
    <!-- Tomcat 启动初始化 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.

3.3、注意

load-on-startup 元素是可选的:若值为 0 或者大于 0 时,表示容器在应用启动时就构建 Servlet 并调用其 init 方法做初始化操作(非负数的值越小,启动该 Servlet 的优先级越高);若值为一个负数时或者没有指定时,则在第一次请求该 Servlet 才加载。配置的话,就可以让 SpringMVC 初始化的工作在容器启动的时候完成,而不是丢给用户请求去完成,提高用户访问的体验性。

3.4、映射路径

配置前端控制器的映射路径一般有以下的三种形式:

  1. 配置如 .do、.htm 是最传统方式,可以访问静态文件(图片、 JS、 CSS 等),但不支持 RESTful风格。
  2. 配置成 /,可以支持流行的 RESTful 风格,但会导致静态文件(图片、 JS、 CSS 等)被拦截后不能访问。
  3. 配置成 /*,是错误的方式,可以请求到 Controller 中,但跳转到调转到 JSP 时被拦截,不能渲染JSP 视图,也会导致静资源访问不了。

3.4.1、访问静态资源和 JSP 被拦截的原因

    Tomcat 容器处理静态资源是交由内置 DefaultServlet 来处理的(拦截路径是 /),处理 JSP 资源是交由内置的 JspServlet 处理的(拦截路径是*.jsp | *.jspx)。
    启动项目时,先加载容器的 web.xml,而后加载项目中的 web.xml。当拦截路径在两者文件中配置的一样,后面会覆盖掉前者。
    所以前端控制器配置拦截路径是 / 的所有静态资源都会交由前端控制器处理,而拦截路径配置 /*,所有静态资源和 JSP 都会交由前端控制器处理。1.2.3.

3.4.2、如何解决

3.4.2.1、方式一

在 web.xml 中修改,修改前端控制器的映射路径修改为*.do,但注意,访问控制器里的处理方法时,请求路径须携带 .do。

<servlet-mapping>
	<servlet-name>dispatcherServlet</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>	1.2.3.4.
3.4.2.2、方式二

在 mvc.xml中加入一段配置,这个配置会在 Spring MVC 上下文中创建存入一个
DefaultServletHttpRequestHandler 的 bean,它会 对进入DispatcherServlet的请求进行筛查,若不是映射的请求,就将该请求交由容器默认的 Servlet处理。

<mvc:default-servlet-handler/>1.

3.5、@ModelAttribute注解

在形参中的对象(必须是自定义类型),SpringMVC会默认将他存入Model中,名称是参数的类名首字母小写,有些时候,这个类会显得格外长,但是我们又有这种需求,比方说:查询条件的回显。我们只需在自定义类的前面加@ModelAttribute,里面写我们需要修改的key的名称即可。

package cn.wolfcode.web.controller;
	@Controller
	public class RequestController {
		@RequestMapping("/req7")
			public String resp7(@ModelAttribute("u") User user) {
			return "m";
		}
}1.2.3.4.5.6.7.8.

四、处理响应

SpringMVC的作用是请求和处理响应,响应处理是指怎么编写控制器里面的处理方法接受请求做响应,找视图文件和往作用域中存入数据。要处理方法要做响应,一般处理方法返回的类型为 ModelAndView 和 String。

4.1、返回 ModelAndView

方法中返回 ModelAndView 对象,此对象中设置模型数据并指定视图。前端依旧是使用JSTL+CgLib来进行取值。他有两个常用方法:

  1. addObject(String key, Object value):设置共享数据的 key 和 value。
  2. addObject(Object value):设置共享数据的 value,key 为该 value 类型首字母小写。
package cn.linstudy.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ResponseController {
  // 提供方法处理请求,localhost/resp1
  @RequestMapping("/resp1")
  public ModelAndView resp1() {
// 通过创建这个类对象,告诉 Spring MVC 找什么视图文件, 往作用域或者说往模型中存入什么数据
    ModelAndView mv = new ModelAndView();
// 往作用域或者模型中存入数据
    mv.addObject("msg", "方法返回类型是 ModelAndView");
// 找视图
    mv.setViewName("/WEB-INF/views/resp.jsp");
    return mv;
  }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.

4.2、返回String

返回 String 类型(使用广泛),此时如果我们需要共享数据,那么就需要用到HttpServlet对象,Spring帮我们封装好了一个对象:Model 。组合使用,用其往作用域或模型中存入数据。

package cn.instudy.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ResponseController {
  // 提供方法处理请求,localhost/resp2
  @RequestMapping("/resp2")
  public String resp2(Model model) {
// 往作用域或者模型中存入数据
    model.addAttribute("msg", "方法返回类型是 String");
// 返回视图名
    return "/WEB-INF/views/resp.jsp";
  }
}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.

4.3、改进

我们会发现,如果我们需要写返回界面的话需要不断地写前缀和后缀,这个时候需要进行消除消除视图前缀和后缀,我们只需在Spring中进行配置视图解析器即可。

以上是关于你真的了解LAMP/LNMP架构吗?(详解PHP和Apache和MariaDB之间的工作联系)以及安装php7,8版本。的主要内容,如果未能解决你的问题,请参考以下文章

LAMP+LNMP LAMP架构概述

你真的了解分层架构吗?

LAMP,LNMP 环境编译参数配置详解

你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构

你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构

你真的了解什么是CQRS吗?