SpringMVC 的学习冒险之旅

Posted Coder.追

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC 的学习冒险之旅相关的知识,希望对你有一定的参考价值。

       哈喽~大家好呀,前段时间将 Spring 框架篇结束,从这篇开始,开始了我们 SpringMVC 的学习之旅了,这篇来看看SpringMVC 项目起步讲解吧。

 🥇个人主页:个人主页​​​​​             

🥈 系列专栏:【Java框架】   

🥉与这篇相关的文章:            

  

【JAVAEE框架】MyBatis与Spring的整合(上)【JAVAEE框架】MyBatis与Spring的整合(上)_程序猿追的博客-CSDN博客
【JAVAEE框架】浅谈 AOP 及代码实现【JAVAEE框架】浅谈 AOP 及代码实现_程序猿追的博客-CSDN博客
【JAVAEE框架】浅谈 Spring 框架的两大核心思想 AOP 与 IOP【JAVAEE框架】浅谈 Spring 框架的两大核心思想 AOP 与 IOP_程序猿追的博客-CSDN博客

目录

一、前言

二、入门程序

三、有参数的传递


一、前言

As everyone knows,在JavaEE 体系结构包括四层,从上到下分别是应用层、Web层、业务层、持久层SpringMVC 是 Web 层的框架,Spring 是业务层的框架,MyBatis 是持久层的框架

经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。

MVC流程如图所示

​​

💡SpringMVC架构流程如图所示

💡SpringMVC 的核心架构

💡 SpringMVC 体系结构

❓​SpringMVC 体系结构流程是怎样的呢?

✅具体流程:

1、用户在页面进行操作,浏览器发送请求,发送到 DispatcherServlet(前端控制器),前端控制器收到后自己不处理,去交给其他解析器去解析

2、DispatcherServlet 将请求发给 HandlerMapping(处理器映射器),处理器映射器将请求映射为 HandlerExecutionChain 对象

3、DispatcherServlet 到 HandlerAdapter(处理器适配器),处理器适配器将会把处理器包装为适配器,从而就有了支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;

4、HandlerAdapter 到 Handler,调用处理器相应功能处理方法,经过数据的一些处理,并返回一个 ModelAndView(模型数据、逻辑视图名)

5、ModelAndView 对象(Model 部分是业务对象返回的模型数据,View 部分为逻辑视图名)到 ViewResolver(视图解析器), 视图解析器将把逻辑视图名解析为具体的 View;

6、View ——> 渲染,View会根据传进来的 Model 模型数据进行渲染,此处的 Model 实际是一个Map 数据结构;

7、View 渲染之后,由 View 返回响应给用户,相应的页面展现给用户看,到此一个流程结束。

二、练手程序

pom 文件写入依赖

        <!--SpringMVC jar-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>

web.xml 文件

<?xml version="1.0" encoding="UTF-8"?>

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

<!--    打开默认页面-->
    <welcome-file-list>
        <welcome-file>userText.html</welcome-file>
    </welcome-file-list>

</web-app>

DispatcherServlet

DispatcherServlet是前置控制器,配置在 web.xml 文件当中的,拦截匹配的请求,Servlet 拦截匹配规则要自己定义,将拦截下来的请求按照相应的规则分发到目标 Controller 来处理,是配置spring MVC的第一步。

<url-pattern>/</url-pattern>

看官方文档可知,如果我们的项目中配置了"/",会覆盖掉 tomcat 中的默认 servlet,当其他的 url-pattern 匹配不上时都会走这个 servlet。意思就是说,页面来的所有请求都会走这个 servlet,也就是 DispatcherServlet。

springMVC.xml 文件

<?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-4.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
	">

<!--    spring注解-->
<!--    作用:扫描包内及其子包内的所有“类”(不包含接口),并为添加了@Service、@Component、@Controller、@Repository修饰的类创建对象并存入IOC容器-->
<!--    @Service、@Component、@Controller、@Repository修饰的类中含有@Autowired修饰的成员变量,则创建对象时会从IOC容器中取值为该成员变量赋值-->
    <context:component-scan base-package="com.itxzw">
        <context:exclude-filter type="regex" expression="com.itxzw.util"/>
    </context:component-scan>

    <!--SpringMVC相关配置-->
    <!--视图解析器,他的作用是在Controller返回的时候进行解析视图-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".html" />
    </bean>

    <!--启动SpringMVC注解-->
<!--    主要用于spring mvc 中的annotation注解功能,作用是帮我们注入一些内置bean,例如RequestMappingHandlerMapping
        和 RequestMappingHandlerAdapter等,这些类是Aware的子类,能完成特定的供能,例如:
        RequestMappingHandlerMapping负责解析@RequestMapping("/helloworld")注解。
        主要是解析spring mvc的一些标签和语法!
-->
    <mvc:annotation-driven />
    <mvc:default-servlet-handler/>
</beans>

context:component-scan

作用:扫描包内及其子包内的所有“类”(不包含接口),并为添加了@Service、@Component、@Controller、@Repository修饰的类创建对象并存入IOC容器,@Service、@Component、@Controller、@Repository修饰的类中含有@Autowired修饰的成员变量,则创建对象时会从IOC容器中取值为该成员变量赋值

context:include-filter

排除类,排除不需要扫描的类

InternalResourceViewResolver

视图解析器,他的作用是在Controller返回的时候进行解析视图

mvc:annotation-driven

主要用于 spring mvc 中的 annotation 注解功能,作用是帮我们注入一些内置 bean,例如RequestMappingHandlerMapping 和 RequestMappingHandlerAdapter 等,这些类是 Aware 的子类,能完成特定的供能,例如:RequestMappingHandlerMapping 负责解析@RequestMapping("/helloworld")注解。主要是解析spring mvc的一些标签和语法。

<mvc:default-servlet-handler/>

我们在配置 dispatchServlet 时配置<url-pattern>/</url-pattern>拦截所有请求,这时候dispatchServlet完全取代了default servlet,将不会再访问容器中原始默认的servlet,而对静态资源的访问就是通过容器默认servlet处理的,故而这时候静态资源将不可访问。
换句话说我们用了 这个 <url-pattern>/</url-pattern>, html就文件访问不了了,如果想要解决访问静态资源问题,就要加上<mvc:default-servlet-handler/>

自定义处理器

// @Controller 是Spring框架提供的注解。
// @Controller标识的类,该类代表控制器类(控制层/表现层)。
// 这里控制层里面的每个方法,都可以去调用@Service标识的类(业务逻辑层),
@Controller
// 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置
@RequestMapping("/user")
public class UserAction 

    @RequestMapping("/userText")
    public String userText()
        return "userText";
    

@Controller

是Spring框架提供的注解。@Controller标识的类,该类代表控制器类(控制层/表现层)。 这里控制层里面的每个方法,都可以去调用@Service标识的类(业务逻辑层)。

@RequestMapping

在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置。可以理解为访问路径。

userText.html 前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试</title>
</head>
<body>

<p>我是测试1</p>
<p>我是测试2</p>

</body>
</html>

项目名

day09_SpringMvc01

测试地址

http://localhost:8080/day09_SpringMvc01/user/userText

三、有参数的传递

自定义处理器

    @RequestMapping(value = "/test02")
    public String test02(User user)
        System.out.println(user);
        return "userList";
    

User 实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User 

    private String username;
    private String password;
    private int age;
    private String gender;
    private String[] hobby;

index.jsp 请求页面

<html>
<body>

<form action="/day09_SpringMvc01/user/test02" method="post">
    姓名:<input type="text" name="username" /> <br>
    密码:<input type="text" name="password" /><br>
    产品名称:<input type="text" name="proname" /><br>
    爱好:唱<input type="checkbox" name="hobby" value="sing">
    跳<input type="checkbox" name="hobby" value="dance">
    rap<input type="checkbox" name="hobby" value="rap">
    篮球<input type="checkbox" name="hobby" value="basketball">
    <br>
    <input type="submit" value="登录">
</form>

</body>
</html>

测试

效果

如果想让结果显示在另外一个页面上呢?

✅index.jsp 前端页面

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

<form action="/day09_SpringMvc01/user/test03" method="post">
    姓名:<input type="text" name="username" /> <br>
    密码:<input type="text" name="password" /><br>
    产品名称:<input type="text" name="proname" /><br>
    爱好:唱<input type="checkbox" name="hobby" value="sing">
    跳<input type="checkbox" name="hobby" value="dance">
    rap<input type="checkbox" name="hobby" value="rap">
    篮球<input type="checkbox" name="hobby" value="basketball">
    <br>
    <input type="submit" value="登录">
</form>

</body>
</html>

自定义处理器

    @RequestMapping("/test03")
    public ModelAndView test03(User user)

        ModelAndView mv = new ModelAndView();
        mv.addObject("user",user);
        mv.setViewName("userDetail");
        return mv;
    

userDetail.jsp 接收页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <h1>用户详情页</h1>
    <h1>姓名:$user.username</h1>
    <h1>密码:$user.password</h1>
    <h1>爱好:$user.hobby</h1>

</body>
</html>

测试

访问路径

http://localhost:8080/day09_SpringMvc01/index.jsp

效果

 扩:@GetMapping 与 @PostMapping

首先要了解一下@RequestMapping注解。

@RequestMapping用于映射url到控制器类的一个特定处理程序方法。可用于方法或者类上面。也就是可以通过url找到对应的方法。

@RequestMapping有8个属性。

value:指定请求的实际地址。

method:指定请求的method类型(GET,POST,PUT,DELETE)等。

consumes:指定处理请求的提交内容类型(Context-Type)。

produces:指定返回的内容类型,还可以设置返回值的字符编码。

params:指定request中必须包含某些参数值,才让该方法处理。

headers:指定request中必须包含某些指定的header值,才让该方法处理请求。

@getMapping与@postMapping是组合注解。

@GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写

@postMapping 是一个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写

@RequestParam

主要用于将请求参数区域的数据映射到控制层方法的参数上。

什么意思?

举个例子,user实体类有两个成员变量(username 与 password),正常情况下我传一个username,不传password,username 就有值,password就是默认的值,如果加了@RequestParam 就必须要传值,如果加了,则默认一定要传参,如果不想传值,可以@RequestParam(required = false)

    @RequestMapping("/test03")
    public String test03(@RequestParam(name = "id",required = false) String ids )
        System.out.println(ids);
        return "userList";
    

不积跬步无以至千里,趁年轻,使劲拼,给未来的自己一个交代!向着明天更好的自己前进吧!

简单的多层神经网络实现

【中文标题】简单的多层神经网络实现【英文标题】:Simple multi layer neural network implementation [closed] 【发布时间】:2013-03-02 00:12:46 【问题描述】:

前段时间,我开始了机器学习的冒险之旅(在我最近 2 年的学习期间)。我读了很多书,写了很多机器学习算法的代码,除了神经网络,这些超出了我的范围。我对这个话题很感兴趣,但是我有一个很大的问题: 我读过的所有书都有两个主要问题:

    包含数学方程式的音调。课后我对它们非常熟悉,而且我可以在纸上手工计算。 包含嵌入在某些复杂上下文中的大示例(例如调查网上商店的销售率),并且要进入神经网络实现,我必须编写大量代码来重现上下文。 缺少什么 - 简单直接的实现,没有大量上下文和方程式。

您能否告诉我,我在哪里可以找到多层感知(神经网络)的简单实现?我不需要理论知识,也不需要上下文嵌入的示例。我更喜欢一些脚本语言来节省时间和精力 - 我以前的工作 99% 都是用 Python 完成的。

这是我以前读过的书(但没有找到我想要的):

    机器学习实战 编程集体智能 机器学习:算法视角 Java 中的神经网络简介 C# 中的神经网络简介

【问题讨论】:

python 是给定的吗?可能,octave 将是更合适的工具来尝试by hand 【参考方案1】:

你试过PyBrain吗?看起来很不错documented。

【讨论】:

嗨!谢谢你的答复。不,我没有尝试过 PyBrain,因为我想一个人做所有的事情:P 我正在寻找一个教程,而不是其他现成的解决方案,即使它有很好的文档记录。但这听起来像是一个计划,如果没有更好的出现:)【参考方案2】:

嗯,这很棘手。我以前也遇到过同样的问题,但我在好的但大量数学负载的解释和准备使用的实现之间找不到任何东西。

即用型 实现(如 PyBrain)的问题在于它们隐藏了细节,因此对学习如何实现 ANN 感兴趣的人需要其他东西。阅读此类解决方案的代码也可能具有挑战性,因为它们经常使用启发式方法来提高性能,这使得初学者更难理解代码。

但是,您可以使用一些资源:

http://msdn.microsoft.com/en-us/magazine/jj658979.aspx

http://itee.uq.edu.au/~cogs2010/cmc/chapters/BackProp/

http://www.codeproject.com/Articles/19323/Image-Recognition-with-Neural-Networks

http://freedelta.free.fr/r/php-code-samples/artificial-intelligence-neural-network-backpropagation/

【讨论】:

【参考方案3】:

这是一个如何使用 numpy 实现前馈神经网络的示例。首先导入 numpy 并指定输入和目标的维度。

import numpy as np

input_dim = 1000
target_dim = 10

我们现在将构建网络结构。正如 Bishop 伟大的“模式识别和机器学习”中所建议的,您可以简单地将 numpy 矩阵的最后一行视为偏置权重,将激活的最后一列视为偏置神经元。那么第一个/最后一个权重矩阵的输入/输出维度需要大 1。

dimensions = [input_dim+1, 500, 500, target_dim+1]

weight_matrices = []
for i in range(len(dimensions)-1):
  weight_matrix = np.ones((dimensions[i], dimensions[i]))
  weight_matrices.append(weight_matrix)

如果您的输入存储在 2d numpy 矩阵中,其中每一行对应一个样本,列对应于样本的属性,您可以像这样通过网络传播:(假设逻辑 sigmoid 函数作为激活函数)

def activate_network(inputs):
  activations = [] # we store the activations for each layer here
  a = np.ones((inputs.shape[0], inputs.shape[1]+1)) #add the bias to the inputs
  a[:,:-1] = inputs

  for w in weight_matrices:
    x = a.dot(w) # sum of weighted inputs
    a = 1. / (1. - np.exp(-x)) # apply logistic sigmoid activation
    a[:,-1] = 1. # bias for the next layer.
    activations.append(a)

  return activations

activations 中的最后一个元素将是您的网络的输出,但请注意,您需要省略额外的偏差列,因此您的输出将是 activations[-1][:,:-1]

要训练网络,您需要实施反向传播,这需要几行额外的代码。基本上,您需要从activations 的最后一个元素循环到第一个元素。确保在每个反向传播步骤之前将每个层的误差信号中的偏差列设置为零。

【讨论】:

【参考方案4】:

Here 是原生 python 中的反向传播算法。

【讨论】:

【参考方案5】:

一个简单的实现

这是一个使用Python 中的类的可读实现。此实现以效率换取可理解性:

    import math
    import random

    BIAS = -1

    """
    To view the structure of the Neural Network, type
    print network_name
    """

    class Neuron:
        def __init__(self, n_inputs ):
            self.n_inputs = n_inputs
            self.set_weights( [random.uniform(0,1) for x in range(0,n_inputs+1)] ) # +1 for bias weight

        def sum(self, inputs ):
            # Does not include the bias
            return sum(val*self.weights[i] for i,val in enumerate(inputs))

        def set_weights(self, weights ):
            self.weights = weights

        def __str__(self):
            return 'Weights: %s, Bias: %s' % ( str(self.weights[:-1]),str(self.weights[-1]) )

    class NeuronLayer:
        def __init__(self, n_neurons, n_inputs):
            self.n_neurons = n_neurons
            self.neurons = [Neuron( n_inputs ) for _ in range(0,self.n_neurons)]

        def __str__(self):
            return 'Layer:\n\t'+'\n\t'.join([str(neuron) for neuron in self.neurons])+''

    class NeuralNetwork:
        def __init__(self, n_inputs, n_outputs, n_neurons_to_hl, n_hidden_layers):
            self.n_inputs = n_inputs
            self.n_outputs = n_outputs
            self.n_hidden_layers = n_hidden_layers
            self.n_neurons_to_hl = n_neurons_to_hl
    
            # Do not touch
            self._create_network()
            self._n_weights = None
            # end

        def _create_network(self):
            if self.n_hidden_layers>0:
                # create the first layer
                self.layers = [NeuronLayer( self.n_neurons_to_hl,self.n_inputs )]
        
                # create hidden layers
                self.layers += [NeuronLayer( self.n_neurons_to_hl,self.n_neurons_to_hl ) for _ in range(0,self.n_hidden_layers)]
        
                # hidden-to-output layer
                self.layers += [NeuronLayer( self.n_outputs,self.n_neurons_to_hl )]
            else:
                # If we don't require hidden layers
                self.layers = [NeuronLayer( self.n_outputs,self.n_inputs )]

        def get_weights(self):
            weights = []
    
            for layer in self.layers:
                for neuron in layer.neurons:
                    weights += neuron.weights
    
            return weights

        @property
        def n_weights(self):
            if not self._n_weights:
                self._n_weights = 0
                for layer in self.layers:
                    for neuron in layer.neurons:
                        self._n_weights += neuron.n_inputs+1 # +1 for bias weight
            return self._n_weights

        def set_weights(self, weights ):
            assert len(weights)==self.n_weights, "Incorrect amount of weights."
    
            stop = 0
            for layer in self.layers:
                for neuron in layer.neurons:
                    start, stop = stop, stop+(neuron.n_inputs+1)
                    neuron.set_weights( weights[start:stop] )
            return self

        def update(self, inputs ):
            assert len(inputs)==self.n_inputs, "Incorrect amount of inputs."
    
            for layer in self.layers:
                outputs = []
                for neuron in layer.neurons:
                    tot = neuron.sum(inputs) + neuron.weights[-1]*BIAS
                    outputs.append( self.sigmoid(tot) )
                inputs = outputs   
            return outputs

        def sigmoid(self, activation,response=1 ):
            # the activation function
            try:
                return 1/(1+math.e**(-activation/response))
            except OverflowError:
                return float("inf")

        def __str__(self):
            return '\n'.join([str(i+1)+' '+str(layer) for i,layer in enumerate(self.layers)])

更高效的实现(带学习)

如果您正在寻找具有学习(反向传播)功能的神经网络的更有效示例,请查看我的 neural network Github repository here。

【讨论】:

update 方法的参数应该是什么?举个例子就好了。 输入值列表。例如:input_values = [1, 0, 0, 1, 0.5] 培训怎么样? 一个真正知道如何编写代码和NAME 变量的人写的例子!!我发现 Github 存储库非常有用。

以上是关于SpringMVC 的学习冒险之旅的主要内容,如果未能解决你的问题,请参考以下文章

JavaEE学习之旅---->SpringMVC

第04项目:淘淘商城(SpringMVC+Spring+Mybatis) 的学习实践总结第五天

FunnyBear的Java之旅 - Spring篇Spring 静态资源

SpringMVC入门demo

洞穴探险如何防止迷路

Spring学习之旅Spring工作原理再探